Skip to content

Commit a76435b

Browse files
committed
LLVMTypeAnalyzer: Add test cases for reporters assigned to variables
1 parent e89f882 commit a76435b

File tree

3 files changed

+470
-1
lines changed

3 files changed

+470
-1
lines changed

src/engine/internal/llvm/llvmtypeanalyzer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ Compiler::StaticType LLVMTypeAnalyzer::writeValueType(LLVMInstruction *ins, Inst
290290
// If this is a variable read instruction, recursively get the variable type
291291
return variableType(arg->instruction->workVariable, arg->instruction.get(), Compiler::StaticType::Unknown, visitedInstructions);
292292
} else {
293-
// TODO: Use the instruction return register
293+
// The write argument already has the instruction return type
294294
return optimizeRegisterType(arg);
295295
}
296296
} else

test/llvm/type_analyzer/variabletype_test.cpp

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,3 +2153,248 @@ TEST(LLVMTypeAnalyzer_VariableType, SelfAssignmentWithTypeChange_After)
21532153
// Should return number because it's assigned after the no-op
21542154
ASSERT_EQ(analyzer.variableType(&var1, queryPos.get(), Compiler::StaticType::String), Compiler::StaticType::Number);
21552155
}
2156+
2157+
TEST(LLVMTypeAnalyzer_VariableType, InstructionReturnType_AddNumbers)
2158+
{
2159+
LLVMTypeAnalyzer analyzer;
2160+
LLVMInstructionList list;
2161+
Variable var1("", "");
2162+
2163+
// Create add instruction: 5 + 3
2164+
auto addInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Add, nullptr, false);
2165+
LLVMConstantRegister operand1(Compiler::StaticType::Number, 5);
2166+
LLVMConstantRegister operand2(Compiler::StaticType::Number, 3);
2167+
addInstruction->args.push_back({ Compiler::StaticType::Number, &operand1 });
2168+
addInstruction->args.push_back({ Compiler::StaticType::Number, &operand2 });
2169+
2170+
// Set up return register for add instruction
2171+
LLVMRegister addResult(Compiler::StaticType::Number);
2172+
addResult.isRawValue = true;
2173+
addResult.instruction = addInstruction;
2174+
addInstruction->functionReturnReg = &addResult;
2175+
list.addInstruction(addInstruction);
2176+
2177+
// Assign add result to variable: var1 = (5 + 3)
2178+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
2179+
setVar1->workVariable = &var1;
2180+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &addResult });
2181+
list.addInstruction(setVar1);
2182+
2183+
// Query position after the assignment
2184+
auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
2185+
list.addInstruction(queryPos);
2186+
2187+
// var1 should have Number type from add instruction return
2188+
ASSERT_EQ(analyzer.variableType(&var1, queryPos.get(), Compiler::StaticType::String), Compiler::StaticType::Number);
2189+
}
2190+
2191+
TEST(LLVMTypeAnalyzer_VariableType, InstructionReturnType_StringConcat)
2192+
{
2193+
LLVMTypeAnalyzer analyzer;
2194+
LLVMInstructionList list;
2195+
Variable var1("", "");
2196+
2197+
// Create string concatenation instruction: "hello" + "world"
2198+
auto concatInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::StringConcat, nullptr, false);
2199+
LLVMConstantRegister str1(Compiler::StaticType::String, "hello");
2200+
LLVMConstantRegister str2(Compiler::StaticType::String, "world");
2201+
concatInstruction->args.push_back({ Compiler::StaticType::String, &str1 });
2202+
concatInstruction->args.push_back({ Compiler::StaticType::String, &str2 });
2203+
2204+
// Set up return register for concat instruction
2205+
LLVMRegister concatResult(Compiler::StaticType::String);
2206+
concatResult.isRawValue = true;
2207+
concatResult.instruction = concatInstruction;
2208+
concatInstruction->functionReturnReg = &concatResult;
2209+
list.addInstruction(concatInstruction);
2210+
2211+
// Assign concat result to variable: var1 = ("hello" + "world")
2212+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
2213+
setVar1->workVariable = &var1;
2214+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &concatResult });
2215+
list.addInstruction(setVar1);
2216+
2217+
// Query position after the assignment
2218+
auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
2219+
list.addInstruction(queryPos);
2220+
2221+
// var1 should have String type from concat instruction return
2222+
ASSERT_EQ(analyzer.variableType(&var1, queryPos.get(), Compiler::StaticType::Number), Compiler::StaticType::String);
2223+
}
2224+
2225+
TEST(LLVMTypeAnalyzer_VariableType, InstructionReturnType_MathFunction)
2226+
{
2227+
LLVMTypeAnalyzer analyzer;
2228+
LLVMInstructionList list;
2229+
Variable var1("", "");
2230+
2231+
// Create sqrt instruction: sqrt(16)
2232+
auto sqrtInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Sqrt, nullptr, false);
2233+
LLVMConstantRegister operand(Compiler::StaticType::Number, 16);
2234+
sqrtInstruction->args.push_back({ Compiler::StaticType::Number, &operand });
2235+
2236+
// Set up return register for sqrt instruction
2237+
LLVMRegister sqrtResult(Compiler::StaticType::Number);
2238+
sqrtResult.isRawValue = true;
2239+
sqrtResult.instruction = sqrtInstruction;
2240+
sqrtInstruction->functionReturnReg = &sqrtResult;
2241+
list.addInstruction(sqrtInstruction);
2242+
2243+
// Assign sqrt result to variable: var1 = sqrt(16)
2244+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
2245+
setVar1->workVariable = &var1;
2246+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &sqrtResult });
2247+
list.addInstruction(setVar1);
2248+
2249+
// Query position after the assignment
2250+
auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
2251+
list.addInstruction(queryPos);
2252+
2253+
// var1 should have Number type from sqrt instruction return
2254+
ASSERT_EQ(analyzer.variableType(&var1, queryPos.get(), Compiler::StaticType::String), Compiler::StaticType::Number);
2255+
}
2256+
2257+
TEST(LLVMTypeAnalyzer_VariableType, InstructionReturnType_Comparison)
2258+
{
2259+
LLVMTypeAnalyzer analyzer;
2260+
LLVMInstructionList list;
2261+
Variable var1("", "");
2262+
2263+
// Create comparison instruction: 5 > 3
2264+
auto cmpInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::CmpGT, nullptr, false);
2265+
LLVMConstantRegister operand1(Compiler::StaticType::Number, 5);
2266+
LLVMConstantRegister operand2(Compiler::StaticType::Number, 3);
2267+
cmpInstruction->args.push_back({ Compiler::StaticType::Number, &operand1 });
2268+
cmpInstruction->args.push_back({ Compiler::StaticType::Number, &operand2 });
2269+
2270+
// Set up return register for comparison instruction
2271+
LLVMRegister cmpResult(Compiler::StaticType::Bool);
2272+
cmpResult.isRawValue = true;
2273+
cmpResult.instruction = cmpInstruction;
2274+
cmpInstruction->functionReturnReg = &cmpResult;
2275+
list.addInstruction(cmpInstruction);
2276+
2277+
// Assign comparison result to variable: var1 = (5 > 3)
2278+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
2279+
setVar1->workVariable = &var1;
2280+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &cmpResult });
2281+
list.addInstruction(setVar1);
2282+
2283+
// Query position after the assignment
2284+
auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
2285+
list.addInstruction(queryPos);
2286+
2287+
// var1 should have Bool type from comparison instruction return
2288+
ASSERT_EQ(analyzer.variableType(&var1, queryPos.get(), Compiler::StaticType::Number), Compiler::StaticType::Bool);
2289+
}
2290+
2291+
TEST(LLVMTypeAnalyzer_VariableType, InstructionReturnType_FunctionCall)
2292+
{
2293+
LLVMTypeAnalyzer analyzer;
2294+
LLVMInstructionList list;
2295+
Variable var1("", "");
2296+
2297+
// Create function call instruction
2298+
auto funcInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
2299+
funcInstruction->functionName = "some_reporter_function";
2300+
LLVMConstantRegister arg(Compiler::StaticType::Number, 42);
2301+
funcInstruction->args.push_back({ Compiler::StaticType::Number, &arg });
2302+
2303+
// Set up return register for function call
2304+
LLVMRegister funcResult(Compiler::StaticType::String);
2305+
funcResult.isRawValue = true;
2306+
funcResult.instruction = funcInstruction;
2307+
funcInstruction->functionReturnReg = &funcResult;
2308+
list.addInstruction(funcInstruction);
2309+
2310+
// Assign function result to variable: var1 = some_reporter_function(42)
2311+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
2312+
setVar1->workVariable = &var1;
2313+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &funcResult });
2314+
list.addInstruction(setVar1);
2315+
2316+
// Query position after the assignment
2317+
auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
2318+
list.addInstruction(queryPos);
2319+
2320+
// var1 should have String type from function call return
2321+
ASSERT_EQ(analyzer.variableType(&var1, queryPos.get(), Compiler::StaticType::Number), Compiler::StaticType::String);
2322+
}
2323+
2324+
TEST(LLVMTypeAnalyzer_VariableType, InstructionReturnType_ChainedOperations)
2325+
{
2326+
LLVMTypeAnalyzer analyzer;
2327+
LLVMInstructionList list;
2328+
Variable var1("", "");
2329+
2330+
// First operation: 5 + 3
2331+
auto addInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Add, nullptr, false);
2332+
LLVMConstantRegister operand1(Compiler::StaticType::Number, 5);
2333+
LLVMConstantRegister operand2(Compiler::StaticType::Number, 3);
2334+
addInstruction->args.push_back({ Compiler::StaticType::Number, &operand1 });
2335+
addInstruction->args.push_back({ Compiler::StaticType::Number, &operand2 });
2336+
2337+
LLVMRegister addResult(Compiler::StaticType::Number);
2338+
addResult.isRawValue = true;
2339+
addResult.instruction = addInstruction;
2340+
addInstruction->functionReturnReg = &addResult;
2341+
list.addInstruction(addInstruction);
2342+
2343+
// Second operation: (5 + 3) * 2
2344+
auto mulInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Mul, nullptr, false);
2345+
LLVMConstantRegister multiplier(Compiler::StaticType::Number, 2);
2346+
mulInstruction->args.push_back({ Compiler::StaticType::Unknown, &addResult });
2347+
mulInstruction->args.push_back({ Compiler::StaticType::Number, &multiplier });
2348+
2349+
LLVMRegister mulResult(Compiler::StaticType::Number);
2350+
mulResult.isRawValue = true;
2351+
mulResult.instruction = mulInstruction;
2352+
mulInstruction->functionReturnReg = &mulResult;
2353+
list.addInstruction(mulInstruction);
2354+
2355+
// Assign final result to variable: var1 = ((5 + 3) * 2)
2356+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
2357+
setVar1->workVariable = &var1;
2358+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &mulResult });
2359+
list.addInstruction(setVar1);
2360+
2361+
// Query position after the assignment
2362+
auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
2363+
list.addInstruction(queryPos);
2364+
2365+
// var1 should have Number type from chained operations
2366+
ASSERT_EQ(analyzer.variableType(&var1, queryPos.get(), Compiler::StaticType::String), Compiler::StaticType::Number);
2367+
}
2368+
2369+
TEST(LLVMTypeAnalyzer_VariableType, InstructionReturnType_QueryBeforeAssignment)
2370+
{
2371+
LLVMTypeAnalyzer analyzer;
2372+
LLVMInstructionList list;
2373+
Variable var1("", "");
2374+
2375+
// Query position before any operations
2376+
auto queryPos = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::FunctionCall, nullptr, false);
2377+
list.addInstruction(queryPos);
2378+
2379+
// Create add instruction: 5 + 3 (after query position)
2380+
auto addInstruction = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::Add, nullptr, false);
2381+
LLVMConstantRegister operand1(Compiler::StaticType::Number, 5);
2382+
LLVMConstantRegister operand2(Compiler::StaticType::Number, 3);
2383+
addInstruction->args.push_back({ Compiler::StaticType::Number, &operand1 });
2384+
addInstruction->args.push_back({ Compiler::StaticType::Number, &operand2 });
2385+
2386+
LLVMRegister addResult(Compiler::StaticType::Number);
2387+
addResult.isRawValue = true;
2388+
addResult.instruction = addInstruction;
2389+
addInstruction->functionReturnReg = &addResult;
2390+
list.addInstruction(addInstruction);
2391+
2392+
// Assign add result to variable: var1 = (5 + 3) (after query position)
2393+
auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr, false);
2394+
setVar1->workVariable = &var1;
2395+
setVar1->args.push_back({ Compiler::StaticType::Unknown, &addResult });
2396+
list.addInstruction(setVar1);
2397+
2398+
// var1 should have the previous type since assignment is after query position
2399+
ASSERT_EQ(analyzer.variableType(&var1, queryPos.get(), Compiler::StaticType::String), Compiler::StaticType::String);
2400+
}

0 commit comments

Comments
 (0)