|
5 | 5 | #include <scratchcpp/list.h> |
6 | 6 | #include <scratchcpp/blockprototype.h> |
7 | 7 | #include <scratchcpp/compiler.h> |
| 8 | +#include <scratchcpp/iengine.h> |
| 9 | +#include <scratchcpp/costume.h> |
8 | 10 |
|
9 | 11 | #include "llvmbuildutils.h" |
10 | 12 | #include "llvmfunctions.h" |
@@ -40,6 +42,35 @@ LLVMBuildUtils::LLVMBuildUtils(LLVMCompilerContext *ctx, llvm::IRBuilder<> &buil |
40 | 42 | initTypes(); |
41 | 43 | createVariableMap(); |
42 | 44 | createListMap(); |
| 45 | + |
| 46 | + // Find unsafe numeric string constants in costume and sound names |
| 47 | + if (m_target) { |
| 48 | + IEngine *engine = m_target->engine(); |
| 49 | + |
| 50 | + if (engine) { |
| 51 | + auto checkConstant = [this](const std::string &str) { |
| 52 | + Value stringValue(str); |
| 53 | + Value numberValue(stringValue.toDouble()); |
| 54 | + |
| 55 | + if (stringValue.isValidNumber() && str == numberValue.toString()) |
| 56 | + m_unsafeConstants.insert(str); |
| 57 | + }; |
| 58 | + |
| 59 | + const auto &targets = engine->targets(); |
| 60 | + bool found = false; |
| 61 | + |
| 62 | + for (const auto &target : targets) { |
| 63 | + const auto &costumes = target->costumes(); |
| 64 | + const auto &sounds = target->sounds(); |
| 65 | + |
| 66 | + for (const auto &costume : costumes) |
| 67 | + checkConstant(costume->name()); |
| 68 | + |
| 69 | + for (const auto &sound : sounds) |
| 70 | + checkConstant(sound->name()); |
| 71 | + } |
| 72 | + } |
| 73 | + } |
43 | 74 | } |
44 | 75 |
|
45 | 76 | void LLVMBuildUtils::init(llvm::Function *function, BlockPrototype *procedurePrototype, bool warp, const std::vector<std::shared_ptr<LLVMRegister>> ®s) |
@@ -423,13 +454,20 @@ std::vector<LLVMLoop> &LLVMBuildUtils::loops() |
423 | 454 | return m_loops; |
424 | 455 | } |
425 | 456 |
|
426 | | -Compiler::StaticType LLVMBuildUtils::optimizeRegisterType(const LLVMRegister *reg) |
| 457 | +Compiler::StaticType LLVMBuildUtils::optimizeRegisterType(const LLVMRegister *reg) const |
427 | 458 | { |
428 | 459 | Compiler::StaticType ret = reg->type(); |
429 | 460 |
|
430 | 461 | // Optimize string constants that represent numbers |
431 | | - if (reg->isConst() && reg->type() == Compiler::StaticType::String && reg->constValue().isValidNumber()) |
432 | | - ret = Compiler::StaticType::Number; |
| 462 | + if (reg->isConst() && reg->type() == Compiler::StaticType::String) { |
| 463 | + const Value &value = reg->constValue(); |
| 464 | + Value numberValue(value.toDouble()); |
| 465 | + std::string str = value.toString(); |
| 466 | + |
| 467 | + // Apply this optimization only if the number matches the string and the constant is safe |
| 468 | + if (value.isValidNumber() && numberValue.toString() == str && m_unsafeConstants.find(str) == m_unsafeConstants.cend()) |
| 469 | + ret = Compiler::StaticType::Number; |
| 470 | + } |
433 | 471 |
|
434 | 472 | return ret; |
435 | 473 | } |
|
0 commit comments