From 2266f3b8bbe161ba6b274bccc1f94f93474fa7a3 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Sat, 12 Oct 2024 10:25:24 +0200 Subject: [PATCH] feat(ir, compiler): implementing the IR optimizer --- .github/images/diagram.svg | 2 +- .../IntermediateRepresentation/Entity.hpp | 2 +- include/Ark/Compiler/Welder.hpp | 2 +- src/arkreactor/Compiler/Compiler.cpp | 2 +- .../IROptimizer.cpp | 121 +++++++++++++++++- src/arkreactor/Compiler/Welder.cpp | 4 +- 6 files changed, 126 insertions(+), 7 deletions(-) diff --git a/.github/images/diagram.svg b/.github/images/diagram.svg index 79bc11d69..b39699b05 100644 --- a/.github/images/diagram.svg +++ b/.github/images/diagram.svg @@ -1 +1 @@ -teststestssrcsrcliblibincludeincludefuzzingfuzzingexamplesexamplesdocsdocscmakecmake.vscode.vscode.github.githubunittestsunittestserrorserrorsarkscriptarkscriptarkscriptarkscriptarkreactorarkreactorArkArkuniqueuniqueinputinputcorpuscorpusworkflowsworkflowsresourcesresourcesREPLREPLVMVMCompilerCompilerBuiltinsBuiltinsVMVMREPLREPLCompilerCompilerParserSuiteParserSuiteASTSuiteASTSuiteValueValueMacrosMacrosASTASTinlineinlineValueValueMacrosMacrosASTASTsuccesssuccessfailurefailureExecutorsExecutorsCHANGELO...CHANGELO...CHANGELO...VM.cppVM.cppVM.cppCompiler...Compiler...Compiler...Bytecode...Bytecode...Bytecode...Processo...Processo...Processo...Parser.cppParser.cppParser.cpp.cmake.cpp.gitignore.hpp.inl.json.md.py.sh.svg.txt.xml.yaml.ymleach dot sized by file size +teststestssrcsrcliblibincludeincludeexamplesexamplesdocsdocscmakecmake.github.githubunittestsunittestsfuzzingfuzzingbenchmarksbenchmarksarkscriptarkscriptarkreactorarkreactorCLICLIArkArkgamesgamesworkflowsworkflowsresourcesresourcescorpus-cmin-tmincorpus-cmin-tmincorpus-cmincorpus-cmincorpuscorpusresourcesresourcesREPLREPLVMVMCompilerCompilerBuiltinsBuiltinsVMVMCompilerCompilerParserSuiteParserSuiteLangSuiteLangSuiteDiagnosticsSuiteDiagnosticsSuiteASTSuiteASTSuiteparserparserMacrosMacrosASTASTValueValueMacrosMacrosASTASTsuccesssuccessfailurefailureruntimeruntimecompileTimecompileTime.cmake.cpp.csv.dockerfile.gitignore.hpp.inl.json.md.py.sh.svg.txt.xml.yaml.ymleach dot sized by file size \ No newline at end of file diff --git a/include/Ark/Compiler/IntermediateRepresentation/Entity.hpp b/include/Ark/Compiler/IntermediateRepresentation/Entity.hpp index 676a09074..4f44f9e03 100644 --- a/include/Ark/Compiler/IntermediateRepresentation/Entity.hpp +++ b/include/Ark/Compiler/IntermediateRepresentation/Entity.hpp @@ -64,7 +64,7 @@ namespace Ark::internal::IR Kind m_kind; label_t m_label { 0 }; - Instruction m_inst; + Instruction m_inst { NOP }; uint16_t m_primary_arg { 0 }; uint16_t m_secondary_arg { 0 }; }; diff --git a/include/Ark/Compiler/Welder.hpp b/include/Ark/Compiler/Welder.hpp index cb3c12605..63581b52e 100644 --- a/include/Ark/Compiler/Welder.hpp +++ b/include/Ark/Compiler/Welder.hpp @@ -105,7 +105,7 @@ namespace Ark void dumpIRToFile() const; - bool computeAST(const std::string& filename, const std::string& code, bool fail_with_exception); + bool computeAST(const std::string& filename, const std::string& code); }; } // namespace Ark diff --git a/src/arkreactor/Compiler/Compiler.cpp b/src/arkreactor/Compiler/Compiler.cpp index 90eb2ae19..eebf5058f 100644 --- a/src/arkreactor/Compiler/Compiler.cpp +++ b/src/arkreactor/Compiler/Compiler.cpp @@ -531,7 +531,7 @@ namespace Ark::internal // in order to be able to handle things like (op A B C D...) // which should be transformed into A B op C op D op... if (exp_count >= 2) - page(p).emplace_back(op, 2); // TODO generalize to n arguments (n >= 2) + page(p).emplace_back(op); } if (isUnaryInst(op)) diff --git a/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp b/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp index 1b67e2cca..caf78b79a 100644 --- a/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp +++ b/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp @@ -8,9 +8,128 @@ namespace Ark::internal void IROptimizer::process(const std::vector& pages, const std::vector& symbols, const std::vector& values) { - m_ir = pages; m_symbols = symbols; m_values = values; + + for (const auto& block : pages) + { + m_ir.emplace_back(); + IR::Block& current_block = m_ir.back(); + + std::size_t i = 0; + const std::size_t end = block.size(); + + while (i < end) + { + const Instruction first = block[i].inst(); + const uint16_t arg_1 = block[i].primaryArg(); + + if (i + 1 < end) + { + const Instruction second = block[i + 1].inst(); + const uint16_t arg_2 = block[i + 1].primaryArg(); + + // LOAD_CONST x + // LOAD_CONST y + // ---> LOAD_CONST_LOAD_CONST x y + if (first == LOAD_CONST && second == LOAD_CONST) + { + current_block.emplace_back(LOAD_CONST_LOAD_CONST, arg_1, arg_2); + i += 2; + } + // LOAD_CONST x + // STORE / SET_VAL a + // ---> LOAD_CONST_STORE x a ; LOAD_CONST_SET_VAL x a + else if (first == LOAD_CONST && second == STORE) + { + current_block.emplace_back(LOAD_CONST_STORE, arg_1, arg_2); + i += 2; + } + else if (first == LOAD_CONST && second == SET_VAL) + { + current_block.emplace_back(LOAD_CONST_SET_VAL, arg_1, arg_2); + i += 2; + } + // LOAD_SYMBOL a + // STORE / SET_VAL b + // ---> STORE_FROM a b ; SET_VAL_FROM a b + else if (first == LOAD_SYMBOL && second == STORE) + { + current_block.emplace_back(STORE_FROM, arg_1, arg_2); + i += 2; + } + else if (first == LOAD_SYMBOL && second == SET_VAL) + { + current_block.emplace_back(SET_VAL_FROM, arg_1, arg_2); + i += 2; + } + else if (i + 2 < end) + { + const Instruction third = block[i + 2].inst(); + const uint16_t arg_3 = block[i + 2].primaryArg(); + + // LOAD_SYMBOL a + // LOAD_CONST n (1) + // ADD / SUB + // ---> INCREMENT / DECREMENT a + if (third == ADD && first == LOAD_CONST && second == LOAD_SYMBOL && m_values[arg_1].type == ValTableElemType::Number && std::get(m_values[arg_1].value) == 1) + { + current_block.emplace_back(INCREMENT, arg_2); + i += 3; + } + else if (third == ADD && first == LOAD_SYMBOL && second == LOAD_CONST && m_values[arg_2].type == ValTableElemType::Number && std::get(m_values[arg_2].value) == 1) + { + current_block.emplace_back(INCREMENT, arg_1); + i += 3; + } + else if (third == SUB && first == LOAD_SYMBOL && second == LOAD_CONST && m_values[arg_2].type == ValTableElemType::Number && std::get(m_values[arg_2].value) == 1) + { + current_block.emplace_back(DECREMENT, arg_1); + i += 3; + } + // LOAD_SYMBOL list + // TAIL / HEAD + // STORE / SET_VAL a + // ---> STORE_TAIL list a ; STORE_HEAD ; SET_VAL_TAIL ; SET_VAL_HEAD + else if (first == LOAD_SYMBOL && second == TAIL && third == STORE) + { + current_block.emplace_back(STORE_TAIL, arg_1, arg_3); + i += 3; + } + else if (first == LOAD_SYMBOL && second == TAIL && third == SET_VAL) + { + current_block.emplace_back(SET_VAL_TAIL, arg_1, arg_3); + i += 3; + } + else if (first == LOAD_SYMBOL && second == HEAD && third == STORE) + { + current_block.emplace_back(STORE_HEAD, arg_1, arg_3); + i += 3; + } + else if (first == LOAD_SYMBOL && second == HEAD && third == SET_VAL) + { + current_block.emplace_back(SET_VAL_HEAD, arg_1, arg_3); + i += 3; + } + else + { + current_block.emplace_back(block[i]); + ++i; + } + } + else + { + current_block.emplace_back(block[i]); + ++i; + } + } + else + { + current_block.emplace_back(block[i]); + ++i; + } + } + } } const std::vector& IROptimizer::intermediateRepresentation() const noexcept diff --git a/src/arkreactor/Compiler/Welder.cpp b/src/arkreactor/Compiler/Welder.cpp index 33e758080..0e6cb2e62 100644 --- a/src/arkreactor/Compiler/Welder.cpp +++ b/src/arkreactor/Compiler/Welder.cpp @@ -141,7 +141,7 @@ namespace Ark break; case internal::IR::Kind::Opcode2Args: - fmt::println(output, "\t{} {} ({})", internal::InstructionNames[entity.inst()], entity.primaryArg(), entity.secondaryArg()); + fmt::println(output, "\t{} {}, {}", internal::InstructionNames[entity.inst()], entity.primaryArg(), entity.secondaryArg()); break; } } @@ -153,7 +153,7 @@ namespace Ark output.close(); } - bool Welder::computeAST(const std::string& filename, const std::string& code, const bool fail_with_exception) + bool Welder::computeAST(const std::string& filename, const std::string& code) { try {