Skip to content

Commit 111885e

Browse files
committed
LLVMCodeAnalyzer: Fix type change propagation
1 parent 7beb1da commit 111885e

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

src/engine/internal/llvm/llvmcodeanalyzer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ void LLVMCodeAnalyzer::analyzeScript(const LLVMInstructionList &script) const
7373
assert(previousBranch);
7474
}
7575

76+
if (primaryBranch->typeChanges || (primaryBranch->elseBranch && primaryBranch->elseBranch->typeChanges))
77+
previousBranch->typeChanges = true;
78+
7679
if (primaryBranch && primaryBranch->elseBranch) {
7780
// The previous variable types can be ignored in if/else statements
7881
overrideVariableTypes(primaryBranch, previousBranch);

test/llvm/code_analyzer/variable_type_analysis.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,61 @@ TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, LoopMultipleWrites_KnownType)
526526
ASSERT_EQ(setVar2->targetType, Compiler::StaticType::Number);
527527
}
528528

529+
TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, LoopWithIfElseWrites)
530+
{
531+
LLVMInstructionList list;
532+
Variable var("", "");
533+
534+
// var = "string"
535+
auto setVarBefore = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, false);
536+
LLVMConstantRegister valueBefore(Compiler::StaticType::String, "string");
537+
setVarBefore->targetVariable = &var;
538+
setVarBefore->args.push_back({ Compiler::StaticType::Unknown, &valueBefore });
539+
list.addInstruction(setVarBefore);
540+
541+
// repeat
542+
auto loopStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginRepeatLoop, false);
543+
list.addInstruction(loopStart);
544+
545+
// if
546+
auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, false);
547+
list.addInstruction(ifStart);
548+
549+
// var = 1
550+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, false);
551+
LLVMConstantRegister value1(Compiler::StaticType::Number, 1);
552+
setVar1->targetVariable = &var;
553+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &value1 });
554+
list.addInstruction(setVar1);
555+
556+
// else
557+
auto elseStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginElse, false);
558+
list.addInstruction(elseStart);
559+
560+
// var = 2
561+
auto setVar2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, false);
562+
LLVMConstantRegister value2(Compiler::StaticType::Number, 2);
563+
setVar2->targetVariable = &var;
564+
setVar2->args.push_back({ Compiler::StaticType::Unknown, &value2 });
565+
list.addInstruction(setVar2);
566+
567+
// end if
568+
auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, false);
569+
list.addInstruction(ifEnd);
570+
571+
// end loop
572+
auto loopEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndLoop, false);
573+
list.addInstruction(loopEnd);
574+
575+
m_analyzer->analyzeScript(list);
576+
577+
// Before the loop, var is String
578+
// After the if-else (both branches write Number), var becomes Number
579+
// On re-iteration, var could be String (initial) or Number (from previous iteration)
580+
ASSERT_EQ(setVar1->targetType, Compiler::StaticType::String | Compiler::StaticType::Number);
581+
ASSERT_EQ(setVar2->targetType, Compiler::StaticType::String | Compiler::StaticType::Number);
582+
}
583+
529584
TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, IfElseStatementSameTypes)
530585
{
531586
LLVMInstructionList list;

0 commit comments

Comments
 (0)