Skip to content

Commit da38039

Browse files
committed
Implement variableTypeChanges() for basic cases
1 parent b419577 commit da38039

File tree

5 files changed

+657
-0
lines changed

5 files changed

+657
-0
lines changed

src/engine/internal/llvm/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ target_sources(scratchcpp
1717
llvmtypes.h
1818
llvmfunctions.cpp
1919
llvmloopscope.h
20+
llvmloopanalyzer.cpp
21+
llvmloopanalyzer.h
2022
llvmcompilercontext.cpp
2123
llvmcompilercontext.h
2224
llvmexecutablecode.cpp
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#include "llvmloopanalyzer.h"
4+
#include "llvminstruction.h"
5+
#include "llvmvariableptr.h"
6+
7+
using namespace libscratchcpp;
8+
9+
bool LLVMLoopAnalyzer::variableTypeChanges(LLVMVariablePtr *varPtr, LLVMInstruction *loopBody, Compiler::StaticType preLoopType) const
10+
{
11+
if (!varPtr || !loopBody)
12+
return false;
13+
14+
if (preLoopType == Compiler::StaticType::Unknown)
15+
return true;
16+
17+
// Find the last write instruction
18+
LLVMInstruction *lastVarWrite = nullptr;
19+
LLVMInstruction *ins = loopBody;
20+
21+
while (ins && ins->type != LLVMInstruction::Type::EndLoop) {
22+
// TODO: Handle nested loops
23+
if (ins->type == LLVMInstruction::Type::WriteVariable && ins->workVariable == varPtr->var)
24+
lastVarWrite = ins;
25+
26+
ins = ins->next;
27+
}
28+
29+
// Loops must always have an end instruction
30+
assert(ins);
31+
32+
// Check the last write instruction, if any
33+
return lastVarWrite ? !typesMatch(lastVarWrite, preLoopType) : false;
34+
}
35+
36+
Compiler::StaticType LLVMLoopAnalyzer::optimizeRegisterType(LLVMRegister *reg) const
37+
{
38+
// TODO: Move this method out if it's used in LLVMCodeBuilder too
39+
assert(reg);
40+
41+
Compiler::StaticType ret = reg->type();
42+
43+
// Optimize string constants that represent numbers
44+
if (reg->isConst() && reg->type() == Compiler::StaticType::String && reg->constValue().isValidNumber())
45+
ret = Compiler::StaticType::Number;
46+
47+
return ret;
48+
}
49+
50+
bool LLVMLoopAnalyzer::typesMatch(LLVMInstruction *ins, Compiler::StaticType expectedType) const
51+
{
52+
assert(ins);
53+
assert(!ins->args.empty());
54+
const auto arg = ins->args.back().second; // value is always the last argument in variable/list write instructions
55+
auto argIns = arg->instruction;
56+
57+
// TODO: Handle cross-variable dependencies
58+
/*if (argIns && (argIns->type == LLVMInstruction::Type::ReadVariable || argIns->type == LLVMInstruction::Type::GetListItem))
59+
return isVarOrListTypeSafe(argIns.get(), expectedType, log, c);*/
60+
61+
return (optimizeRegisterType(arg) == expectedType);
62+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#include <scratchcpp/compiler.h>
4+
5+
namespace libscratchcpp
6+
{
7+
8+
struct LLVMVariablePtr;
9+
struct LLVMInstruction;
10+
struct LLVMRegister;
11+
12+
class LLVMLoopAnalyzer
13+
{
14+
public:
15+
bool variableTypeChanges(LLVMVariablePtr *varPtr, LLVMInstruction *loopBody, Compiler::StaticType preLoopType) const;
16+
17+
private:
18+
Compiler::StaticType optimizeRegisterType(LLVMRegister *reg) const;
19+
bool typesMatch(LLVMInstruction *ins, Compiler::StaticType expectedType) const;
20+
};
21+
22+
} // namespace libscratchcpp

test/llvm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ add_executable(
2020
llvmexecutablecode_test.cpp
2121
llvmcodebuilder_test.cpp
2222
llvminstructionlist_test.cpp
23+
loop_analyzer/variabletypechanges_test.cpp
2324
)
2425

2526
target_link_libraries(

0 commit comments

Comments
 (0)