@@ -8,6 +8,8 @@ using namespace libscratchcpp;
88static const std::unordered_set<LLVMInstruction::Type>
99 BEGIN_LOOP_INSTRUCTIONS = { LLVMInstruction::Type::BeginRepeatLoop, LLVMInstruction::Type::BeginWhileLoop, LLVMInstruction::Type::BeginRepeatUntilLoop };
1010
11+ static const std::unordered_set<LLVMInstruction::Type> LIST_WRITE_INSTRUCTIONS = { LLVMInstruction::Type::AppendToList, LLVMInstruction::Type::InsertToList, LLVMInstruction::Type::ListReplace };
12+
1113Compiler::StaticType LLVMTypeAnalyzer::variableType (Variable *var, LLVMInstruction *pos, Compiler::StaticType previousType) const
1214{
1315 InstructionSet visitedInstructions;
@@ -20,6 +22,68 @@ Compiler::StaticType LLVMTypeAnalyzer::variableTypeAfterBranch(Variable *var, LL
2022 return variableTypeAfterBranch (var, start, previousType, visitedInstructions);
2123}
2224
25+ Compiler::StaticType LLVMTypeAnalyzer::listTypeAfterBranch (List *list, LLVMInstruction *start, Compiler::StaticType previousType, bool isEmpty) const
26+ {
27+ if (!list || !start)
28+ return previousType;
29+
30+ assert (isLoopStart (start) || isIfStart (start) || isElse (start));
31+
32+ InstructionSet visitedInstructions; // TODO: Handle cross-variable/list dependencies
33+
34+ LLVMInstruction *ins = start->next ;
35+ LLVMInstruction *lastWrite = nullptr ;
36+ Compiler::StaticType lastWriteType = Compiler::StaticType::Unknown;
37+ int level = 0 ;
38+
39+ while (ins && !((isLoopEnd (ins) || isIfEnd (ins) || isElse (ins)) && level == 0 )) {
40+ if (isLoopStart (ins) || isIfStart (ins))
41+ level++;
42+ else if (isLoopEnd (ins) || isIfEnd (ins)) {
43+ assert (level > 0 );
44+ level--;
45+ } else if (isListWrite (ins, list)) {
46+ // List write instruction
47+ Compiler::StaticType writeType = writeValueType (ins, visitedInstructions);
48+
49+ // For non-empty lists, we can just check the write type
50+ if (!isEmpty && !typesMatch (writeType, previousType)) {
51+ return Compiler::StaticType::Unknown;
52+ }
53+
54+ // In empty lists, writes of the same type determine the final type
55+ if (isEmpty) {
56+ if (lastWrite) {
57+ // There was a write before which means it might determine the final type
58+ if (!typesMatch (writeType, lastWriteType))
59+ return Compiler::StaticType::Unknown;
60+ } else {
61+ // This is the first write found, it might determine the final type
62+ lastWrite = ins;
63+ lastWriteType = writeType;
64+ }
65+ }
66+ }
67+
68+ ins = ins->next ;
69+ }
70+
71+ assert (ins);
72+
73+ if (isEmpty) {
74+ if (lastWrite) {
75+ // Only writes of the same type modify the list
76+ return lastWriteType;
77+ } else {
78+ // No writes to empty list found, keep the previous type
79+ return previousType;
80+ }
81+ } else {
82+ // No type conflicts found for non-empty list
83+ return previousType;
84+ }
85+ }
86+
2387Compiler::StaticType LLVMTypeAnalyzer::variableType (Variable *var, LLVMInstruction *pos, Compiler::StaticType previousType, InstructionSet &visitedInstructions) const
2488{
2589 if (!var || !pos)
@@ -258,6 +322,11 @@ bool LLVMTypeAnalyzer::isVariableWrite(LLVMInstruction *ins, Variable *var) cons
258322 return (ins->type == LLVMInstruction::Type::WriteVariable && ins->workVariable == var);
259323}
260324
325+ bool LLVMTypeAnalyzer::isListWrite (LLVMInstruction *ins, List *list) const
326+ {
327+ return (LIST_WRITE_INSTRUCTIONS.find (ins->type ) != LIST_WRITE_INSTRUCTIONS.cend () && ins->workList == list);
328+ }
329+
261330Compiler::StaticType LLVMTypeAnalyzer::optimizeRegisterType (LLVMRegister *reg) const
262331{
263332 // TODO: Move this method out if it's used in LLVMCodeBuilder too
0 commit comments