@@ -40,7 +40,7 @@ Compiler::StaticType LLVMTypeAnalyzer::variableType(LLVMVariablePtr *varPtr, LLV
40
40
41
41
if (loopStart) {
42
42
// Analyze the first loop that was found
43
- if (variableTypeChangesInLoop (varPtr, loopStart, previousType))
43
+ if (variableTypeChangesInBranch (varPtr, loopStart, previousType))
44
44
return write ? writeValueType (write) : Compiler::StaticType::Unknown;
45
45
} else if (write) {
46
46
// There wasn't any loop found, so we can just check the last write operation
@@ -51,65 +51,56 @@ Compiler::StaticType LLVMTypeAnalyzer::variableType(LLVMVariablePtr *varPtr, LLV
51
51
return previousType;
52
52
}
53
53
54
- bool LLVMTypeAnalyzer::variableTypeChangesInLoop (LLVMVariablePtr *varPtr, LLVMInstruction *loopBody, Compiler::StaticType preLoopType) const
54
+ bool LLVMTypeAnalyzer::variableTypeChangesInBranch (LLVMVariablePtr *varPtr, LLVMInstruction *loopBody, Compiler::StaticType preLoopType) const
55
55
{
56
56
if (!varPtr || !loopBody)
57
57
return false ;
58
58
59
- // Find loop end
59
+ assert (isLoopStart (loopBody) || isIfStart (loopBody) || isElse (loopBody));
60
+
61
+ // Find loop/if statement end or else branch
60
62
LLVMInstruction *ins = loopBody->next ;
61
- int loopLevel = 0 ;
62
-
63
- while (ins && !(isLoopEnd (ins) && loopLevel == 0 )) {
64
- if (isLoopStart (ins))
65
- loopLevel ++;
66
- else if (isLoopEnd (ins)) {
67
- assert (loopLevel > 0 );
68
- loopLevel --;
63
+ int level = 0 ;
64
+
65
+ while (ins && !(( isLoopEnd (ins) || isIfEnd (ins) || isElse (ins)) && level == 0 )) {
66
+ if (isLoopStart (ins) || isIfStart (ins) )
67
+ level ++;
68
+ else if (isLoopEnd (ins) || isIfEnd (ins) ) {
69
+ assert (level > 0 );
70
+ level --;
69
71
}
70
72
71
73
ins = ins->next ;
72
74
}
73
75
74
- // Loops must always have an end instruction
75
76
if (!ins) {
76
77
assert (false );
77
78
return true ;
78
79
}
79
80
80
- return variableTypeChangesInLoopFromEnd (varPtr, ins, preLoopType);
81
+ // Process the branch from end
82
+ return variableTypeChangesInBranchFromEnd (varPtr, ins, preLoopType);
81
83
}
82
84
83
- bool LLVMTypeAnalyzer::variableTypeChangesInLoopFromEnd (LLVMVariablePtr *varPtr, LLVMInstruction *loopEnd, Compiler::StaticType preLoopType) const
85
+ bool LLVMTypeAnalyzer::variableTypeChangesInBranchFromEnd (LLVMVariablePtr *varPtr, LLVMInstruction *loopEnd, Compiler::StaticType preLoopType) const
84
86
{
85
87
// Find the last write instruction
86
88
LLVMInstruction *ins = loopEnd->previous ;
87
89
88
- while (ins && !isLoopStart (ins)) {
90
+ while (ins && !isLoopStart (ins) && ! isIfStart (ins) ) {
89
91
if (isLoopEnd (ins) || isIfEnd (ins) || isElse (ins)) {
90
- // Nested loop or if statement
91
- if (variableTypeChangesInLoopFromEnd (varPtr, ins, preLoopType))
92
+ // Process the nested loop or if statement
93
+ if (variableTypeChangesInBranchFromEnd (varPtr, ins, preLoopType))
92
94
return true ;
93
95
94
- // Skip the loop or if statement
95
- int level = 0 ;
96
- ins = ins->previous ;
97
-
98
- while (ins && !((isLoopStart (ins) || isIfStart (ins) || isElse (ins)) && level == 0 )) {
99
- if (isLoopStart (ins) || isIfStart (ins)) {
100
- assert (level > 0 );
101
- level--;
102
- }
96
+ ins = skipBranch (ins);
103
97
104
- if (isLoopEnd (ins) || isIfEnd (ins) || isElse (ins))
105
- level++;
98
+ if (isElse (ins)) {
99
+ // Process if branch (the else branch is already processed)
100
+ if (variableTypeChangesInBranchFromEnd (varPtr, ins, preLoopType))
101
+ return true ;
106
102
107
- ins = ins->previous ;
108
- };
109
-
110
- if (!ins) {
111
- assert (false );
112
- return true ;
103
+ ins = skipBranch (ins);
113
104
}
114
105
} else if (ins->type == LLVMInstruction::Type::WriteVariable && ins->workVariable == varPtr->var ) {
115
106
// Variable write instruction
@@ -122,6 +113,31 @@ bool LLVMTypeAnalyzer::variableTypeChangesInLoopFromEnd(LLVMVariablePtr *varPtr,
122
113
return false ;
123
114
}
124
115
116
+ LLVMInstruction *LLVMTypeAnalyzer::skipBranch (LLVMInstruction *pos) const
117
+ {
118
+ int level = 0 ;
119
+ pos = pos->previous ;
120
+
121
+ while (pos && !((isLoopStart (pos) || isIfStart (pos)) && level == 0 )) {
122
+ if (isLoopStart (pos) || isIfStart (pos)) {
123
+ assert (level > 0 );
124
+ level--;
125
+ }
126
+
127
+ if (isLoopEnd (pos) || isIfEnd (pos) || isElse (pos)) {
128
+ if (isElse (pos) && level == 0 )
129
+ break ;
130
+
131
+ level++;
132
+ }
133
+
134
+ pos = pos->previous ;
135
+ };
136
+
137
+ assert (pos);
138
+ return pos;
139
+ }
140
+
125
141
bool LLVMTypeAnalyzer::isLoopStart (LLVMInstruction *ins) const
126
142
{
127
143
return (BEGIN_LOOP_INSTRUCTIONS.find (ins->type ) != BEGIN_LOOP_INSTRUCTIONS.cend ());
0 commit comments