11#include < scratchcpp/project.h>
2- #include < scratchcpp/target.h>
2+ #include < scratchcpp/sprite.h>
3+ #include < scratchcpp/costume.h>
4+ #include < scratchcpp/sound.h>
5+ #include < scratchcpp/iengine.h>
36#include < scratchcpp/list.h>
47#include < engine/internal/llvm/llvmcodeanalyzer.h>
58#include < engine/internal/llvm/llvmcompilercontext.h>
@@ -18,17 +21,33 @@ class LLVMCodeAnalyzer_ListTypeAnalysis : public testing::Test
1821 void SetUp () override
1922 {
2023 auto engine = m_project.engine ();
21- m_ctx = std::make_unique<LLVMCompilerContext>(engine.get (), &m_target);
24+ m_target = std::make_shared<Target>();
25+ m_spriteWithUnsafeConstants = std::make_shared<Sprite>();
26+
27+ auto costume = std::make_shared<Costume>(m_unsafeCostumeNumConstant, " " , " " );
28+ m_spriteWithUnsafeConstants->addCostume (costume);
29+
30+ auto sound = std::make_shared<Sound>(m_unsafeSoundNumConstant, " " , " " );
31+ m_spriteWithUnsafeConstants->addSound (sound);
32+
33+ engine->setTargets ({ m_target, m_spriteWithUnsafeConstants });
34+
35+ m_ctx = std::make_unique<LLVMCompilerContext>(engine.get (), m_target.get ());
2236 m_builder = std::make_unique<llvm::IRBuilder<>>(*m_ctx->llvmCtx ());
2337 m_utils = std::make_unique<LLVMBuildUtils>(m_ctx.get (), *m_builder, Compiler::CodeType::Script);
2438 m_analyzer = std::make_unique<LLVMCodeAnalyzer>(*m_utils);
2539 }
2640
2741 std::unique_ptr<LLVMCodeAnalyzer> m_analyzer;
2842
43+ const std::string m_safeNumConstant = " 3.14" ;
44+ const std::string m_unsafeCostumeNumConstant = " 12" ;
45+ const std::string m_unsafeSoundNumConstant = " -27.672" ;
46+
2947 private:
3048 Project m_project;
31- Target m_target;
49+ std::shared_ptr<Target> m_target;
50+ std::shared_ptr<Sprite> m_spriteWithUnsafeConstants;
3251 std::unique_ptr<LLVMCompilerContext> m_ctx;
3352 std::unique_ptr<llvm::IRBuilder<>> m_builder;
3453 std::unique_ptr<LLVMBuildUtils> m_utils;
@@ -155,7 +174,7 @@ TEST_F(LLVMCodeAnalyzer_ListTypeAnalysis, StringOptimization_AfterClear)
155174 list.addInstruction (clearList);
156175
157176 auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
158- LLVMConstantRegister value1 (Compiler::StaticType::String, " 3.14 " );
177+ LLVMConstantRegister value1 (Compiler::StaticType::String, m_safeNumConstant );
159178 appendList1->targetList = &targetList;
160179 appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
161180 list.addInstruction (appendList1);
@@ -170,7 +189,7 @@ TEST_F(LLVMCodeAnalyzer_ListTypeAnalysis, StringOptimization_AfterClear)
170189
171190 ASSERT_EQ (appendList1->targetType , Compiler::StaticType::Void);
172191
173- // String "3.14" optimized to Number, so second write sees Number type
192+ // String gets optimized to Number, so second write sees Number type
174193 ASSERT_EQ (appendList2->targetType , Compiler::StaticType::Number);
175194}
176195
@@ -203,6 +222,64 @@ TEST_F(LLVMCodeAnalyzer_ListTypeAnalysis, StringOptimization_AfterClear_Differen
203222 ASSERT_EQ (appendList2->targetType , Compiler::StaticType::String);
204223}
205224
225+ TEST_F (LLVMCodeAnalyzer_ListTypeAnalysis, StringOptimization_AfterClear_UnsafeCostumeConstant)
226+ {
227+ LLVMInstructionList list;
228+ List targetList (" " , " " );
229+
230+ auto clearList = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::ClearList, false );
231+ clearList->targetList = &targetList;
232+ list.addInstruction (clearList);
233+
234+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
235+ LLVMConstantRegister value1 (Compiler::StaticType::String, m_unsafeCostumeNumConstant);
236+ appendList1->targetList = &targetList;
237+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
238+ list.addInstruction (appendList1);
239+
240+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
241+ LLVMConstantRegister value2 (Compiler::StaticType::Bool, true );
242+ appendList2->targetList = &targetList;
243+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
244+ list.addInstruction (appendList2);
245+
246+ m_analyzer->analyzeScript (list);
247+
248+ ASSERT_EQ (appendList1->targetType , Compiler::StaticType::Void);
249+
250+ // String does NOT get optimized to Number because there's a costume with the same name
251+ ASSERT_EQ (appendList2->targetType , Compiler::StaticType::String);
252+ }
253+
254+ TEST_F (LLVMCodeAnalyzer_ListTypeAnalysis, StringOptimization_AfterClear_UnsafeSoundConstant)
255+ {
256+ LLVMInstructionList list;
257+ List targetList (" " , " " );
258+
259+ auto clearList = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::ClearList, false );
260+ clearList->targetList = &targetList;
261+ list.addInstruction (clearList);
262+
263+ auto appendList1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
264+ LLVMConstantRegister value1 (Compiler::StaticType::String, m_unsafeSoundNumConstant);
265+ appendList1->targetList = &targetList;
266+ appendList1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
267+ list.addInstruction (appendList1);
268+
269+ auto appendList2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::AppendToList, false );
270+ LLVMConstantRegister value2 (Compiler::StaticType::Bool, true );
271+ appendList2->targetList = &targetList;
272+ appendList2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
273+ list.addInstruction (appendList2);
274+
275+ m_analyzer->analyzeScript (list);
276+
277+ ASSERT_EQ (appendList1->targetType , Compiler::StaticType::Void);
278+
279+ // String does NOT get optimized to Number because there's a sound with the same name
280+ ASSERT_EQ (appendList2->targetType , Compiler::StaticType::String);
281+ }
282+
206283TEST_F (LLVMCodeAnalyzer_ListTypeAnalysis, ClearListOperation)
207284{
208285 LLVMInstructionList list;
0 commit comments