Skip to content

Commit ea7c9b7

Browse files
committed
LLVMTypeAnalyzer: Ignore writes after pos in if statements
1 parent 5b94db0 commit ea7c9b7

File tree

2 files changed

+128
-2
lines changed

2 files changed

+128
-2
lines changed

src/engine/internal/llvm/llvmtypeanalyzer.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@ Compiler::StaticType LLVMTypeAnalyzer::variableType(LLVMVariablePtr *varPtr, LLV
1919
LLVMInstruction *write = nullptr;
2020
LLVMInstruction *firstBranch = nullptr;
2121
LLVMInstruction *firstElseBranch = nullptr;
22+
LLVMInstruction *ourBranch = nullptr;
2223
int level = 0;
2324

2425
while (ins) {
2526
if (isLoopEnd(ins) || isIfEnd(ins))
2627
level++;
2728
else if (isLoopStart(ins) || isIfStart(ins)) {
29+
if (!ourBranch && level == 0)
30+
ourBranch = ins;
31+
2832
level--;
2933
firstBranch = ins;
3034
} else if (isElse(ins)) {
@@ -44,11 +48,18 @@ Compiler::StaticType LLVMTypeAnalyzer::variableType(LLVMVariablePtr *varPtr, LLV
4448

4549
if (firstBranch) {
4650
// Analyze the first branch and else branch
51+
bool ignoreWriteAfterPos = (isIfStart(firstBranch) && firstBranch == ourBranch);
52+
4753
if (write)
4854
previousType = writeValueType(write); // write operation overrides previous type
4955

50-
Compiler::StaticType firstBranchType = variableTypeAfterBranch(varPtr, firstBranch, previousType);
51-
Compiler::StaticType elseBranchType = variableTypeAfterBranch(varPtr, firstElseBranch, previousType);
56+
Compiler::StaticType firstBranchType = previousType;
57+
Compiler::StaticType elseBranchType = previousType;
58+
59+
if (!ignoreWriteAfterPos) {
60+
firstBranchType = variableTypeAfterBranch(varPtr, firstBranch, previousType);
61+
elseBranchType = variableTypeAfterBranch(varPtr, firstElseBranch, previousType);
62+
}
5263

5364
if (typesMatch(firstBranchType, elseBranchType))
5465
return firstBranchType;

test/llvm/type_analyzer/variabletype_test.cpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,121 @@ TEST(LLVMTypeAnalyzer_VariableType, Loop_SingleWriteDifferentTypeStringToBool_Af
666666
ASSERT_EQ(analyzer.variableType(&varPtr, funcCall.get(), Compiler::StaticType::String), Compiler::StaticType::Unknown);
667667
}
668668

669+
TEST(LLVMTypeAnalyzer_VariableType, Loop_SingleWriteDifferentType_BeforeAndAfter)
670+
{
671+
LLVMTypeAnalyzer analyzer;
672+
LLVMInstructionList list;
673+
LLVMVariablePtr varPtr;
674+
Variable var("", "");
675+
varPtr.var = &var;
676+
677+
auto start = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginRepeatLoop, nullptr, false);
678+
list.addInstruction(start);
679+
680+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
681+
LLVMConstantRegister value1(Compiler::StaticType::String, "test");
682+
setVar1->workVariable = &var;
683+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &value1 });
684+
list.addInstruction(setVar1);
685+
686+
auto funcCall = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
687+
list.addInstruction(funcCall);
688+
689+
auto setVar2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
690+
LLVMConstantRegister value2(Compiler::StaticType::Bool, true);
691+
setVar2->workVariable = &var;
692+
setVar2->args.push_back({ Compiler::StaticType::Unknown, &value2 });
693+
list.addInstruction(setVar2);
694+
695+
auto end = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndLoop, nullptr, false);
696+
list.addInstruction(end);
697+
698+
ASSERT_EQ(analyzer.variableType(&varPtr, funcCall.get(), Compiler::StaticType::Number), Compiler::StaticType::String);
699+
}
700+
701+
TEST(LLVMTypeAnalyzer_VariableType, IfStatement_SingleWriteDifferentType_Before)
702+
{
703+
LLVMTypeAnalyzer analyzer;
704+
LLVMInstructionList list;
705+
LLVMVariablePtr varPtr;
706+
Variable var("", "");
707+
varPtr.var = &var;
708+
709+
auto start = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr, false);
710+
list.addInstruction(start);
711+
712+
auto setVar = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
713+
LLVMConstantRegister value(Compiler::StaticType::String, "test");
714+
setVar->workVariable = &var;
715+
setVar->args.push_back({ Compiler::StaticType::Unknown, &value });
716+
list.addInstruction(setVar);
717+
718+
auto funcCall = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
719+
list.addInstruction(funcCall);
720+
721+
auto end = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr, false);
722+
list.addInstruction(end);
723+
724+
ASSERT_EQ(analyzer.variableType(&varPtr, funcCall.get(), Compiler::StaticType::Number), Compiler::StaticType::String);
725+
}
726+
727+
TEST(LLVMTypeAnalyzer_VariableType, IfStatement_SingleWriteDifferentType_After_IfBranch)
728+
{
729+
LLVMTypeAnalyzer analyzer;
730+
LLVMInstructionList list;
731+
LLVMVariablePtr varPtr;
732+
Variable var("", "");
733+
varPtr.var = &var;
734+
735+
auto start = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr, false);
736+
list.addInstruction(start);
737+
738+
auto funcCall = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
739+
list.addInstruction(funcCall);
740+
741+
auto setVar = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
742+
LLVMConstantRegister value(Compiler::StaticType::String, "test");
743+
setVar->workVariable = &var;
744+
setVar->args.push_back({ Compiler::StaticType::Unknown, &value });
745+
list.addInstruction(setVar);
746+
747+
auto end = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr, false);
748+
list.addInstruction(end);
749+
750+
// Since this isn't a loop, the write after the point doesn't affect the type
751+
ASSERT_EQ(analyzer.variableType(&varPtr, funcCall.get(), Compiler::StaticType::Number), Compiler::StaticType::Number);
752+
}
753+
754+
TEST(LLVMTypeAnalyzer_VariableType, IfStatement_SingleWriteDifferentType_After_ElseBranch)
755+
{
756+
LLVMTypeAnalyzer analyzer;
757+
LLVMInstructionList list;
758+
LLVMVariablePtr varPtr;
759+
Variable var("", "");
760+
varPtr.var = &var;
761+
762+
auto start = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr, false);
763+
list.addInstruction(start);
764+
765+
auto elseStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginElse, nullptr, false);
766+
list.addInstruction(elseStart);
767+
768+
auto funcCall = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
769+
list.addInstruction(funcCall);
770+
771+
auto setVar = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
772+
LLVMConstantRegister value(Compiler::StaticType::String, "test");
773+
setVar->workVariable = &var;
774+
setVar->args.push_back({ Compiler::StaticType::Unknown, &value });
775+
list.addInstruction(setVar);
776+
777+
auto end = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr, false);
778+
list.addInstruction(end);
779+
780+
// Since this isn't a loop, the write after the point doesn't affect the type
781+
ASSERT_EQ(analyzer.variableType(&varPtr, funcCall.get(), Compiler::StaticType::Number), Compiler::StaticType::Number);
782+
}
783+
669784
TEST(LLVMTypeAnalyzer_VariableType, WriteSameTypeInLoop)
670785
{
671786
LLVMTypeAnalyzer analyzer;

0 commit comments

Comments
 (0)