Skip to content

Commit 07bc345

Browse files
committed
LLVMCodeBuilder: Always store return type in the value argument
1 parent 56453c3 commit 07bc345

File tree

2 files changed

+92
-8
lines changed

2 files changed

+92
-8
lines changed

src/engine/internal/llvm/llvmcodeanalyzer.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -300,12 +300,7 @@ Compiler::StaticType LLVMCodeAnalyzer::writeType(LLVMInstruction *ins) const
300300
auto &arg = ins->args.back(); // value is always the last argument in variable/list write instructions
301301
const LLVMRegister *argReg = arg.second;
302302

303-
if (argReg->instruction) {
304-
if (isVariableRead(argReg->instruction.get()) || isListRead(argReg->instruction.get())) {
305-
// Store the variable/list type in the value argument
306-
arg.first = argReg->instruction->functionReturnReg->type();
307-
}
308-
}
309-
310-
return m_utils.optimizeRegisterType(argReg);
303+
Compiler::StaticType ret = m_utils.optimizeRegisterType(argReg);
304+
arg.first = ret; // store the return type in the value argument
305+
return ret;
311306
}

test/llvm/code_analyzer/variable_type_analysis.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,23 @@ TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, FirstVariableWrite)
7070
ASSERT_EQ(setVar->targetType, Compiler::StaticType::Unknown);
7171
}
7272

73+
TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, FirstVariableWrite_ArgType)
74+
{
75+
LLVMInstructionList list;
76+
Variable var("", "");
77+
78+
auto setVar = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, false);
79+
LLVMConstantRegister value(Compiler::StaticType::String, "test");
80+
setVar->targetVariable = &var;
81+
setVar->args.push_back({ Compiler::StaticType::Unknown, &value });
82+
list.addInstruction(setVar);
83+
84+
m_analyzer->analyzeScript(list);
85+
86+
// The argument should use the constant type
87+
ASSERT_EQ(setVar->args.back().first, Compiler::StaticType::String);
88+
}
89+
7390
TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, SecondVariableWrite)
7491
{
7592
LLVMInstructionList list;
@@ -95,6 +112,62 @@ TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, SecondVariableWrite)
95112
ASSERT_EQ(setVar2->targetType, Compiler::StaticType::Number);
96113
}
97114

115+
TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, InstructionReturnTypePropagation)
116+
{
117+
LLVMInstructionList list;
118+
Variable var("", "");
119+
120+
auto ins = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Add, true);
121+
list.addInstruction(ins);
122+
123+
LLVMRegister ret(Compiler::StaticType::Number);
124+
ret.isRawValue = false;
125+
ret.instruction = ins;
126+
ins->functionReturnReg = &ret;
127+
128+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, false);
129+
setVar1->targetVariable = &var;
130+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &ret });
131+
list.addInstruction(setVar1);
132+
133+
auto setVar2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, false);
134+
LLVMConstantRegister value2(Compiler::StaticType::String, "hello");
135+
setVar2->targetVariable = &var;
136+
setVar2->args.push_back({ Compiler::StaticType::Unknown, &value2 });
137+
list.addInstruction(setVar2);
138+
139+
m_analyzer->analyzeScript(list);
140+
141+
// First write has no previous type
142+
ASSERT_EQ(setVar1->targetType, Compiler::StaticType::Unknown);
143+
// Second write has Number type from the instruction
144+
ASSERT_EQ(setVar2->targetType, Compiler::StaticType::Number);
145+
}
146+
147+
TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, InstructionReturnTypePropagation_ArgType)
148+
{
149+
LLVMInstructionList list;
150+
Variable var("", "");
151+
152+
auto ins = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Add, true);
153+
list.addInstruction(ins);
154+
155+
LLVMRegister ret(Compiler::StaticType::Number);
156+
ret.isRawValue = false;
157+
ret.instruction = ins;
158+
ins->functionReturnReg = &ret;
159+
160+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, false);
161+
setVar1->targetVariable = &var;
162+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &ret });
163+
list.addInstruction(setVar1);
164+
165+
m_analyzer->analyzeScript(list);
166+
167+
// Second write has Number type from the instruction stored in the value argument
168+
ASSERT_EQ(setVar1->args.back().first, Compiler::StaticType::Number);
169+
}
170+
98171
TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, MultipleWritesSameType)
99172
{
100173
LLVMInstructionList list;
@@ -221,6 +294,22 @@ TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, StringOptimization_UnsafeSoundCons
221294
ASSERT_EQ(setVar2->targetType, Compiler::StaticType::String);
222295
}
223296

297+
TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, ArgTypeStringOptimization)
298+
{
299+
LLVMInstructionList list;
300+
Variable var("", "");
301+
302+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, false);
303+
LLVMConstantRegister value1(Compiler::StaticType::String, m_safeNumConstant);
304+
setVar1->targetVariable = &var;
305+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &value1 });
306+
list.addInstruction(setVar1);
307+
308+
m_analyzer->analyzeScript(list);
309+
310+
ASSERT_EQ(setVar1->args.back().first, Compiler::StaticType::Number);
311+
}
312+
224313
TEST_F(LLVMCodeAnalyzer_VariableTypeAnalysis, LoopSingleWrite)
225314
{
226315
LLVMInstructionList list;

0 commit comments

Comments
 (0)