diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/CMakeLists.txt b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/CMakeLists.txt index b0b49a1e2d..6f7d7023ee 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/CMakeLists.txt +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/CMakeLists.txt @@ -2,6 +2,7 @@ set(SOURCES AST/AST.cpp AST/ASTPrinting.cpp Compiler/CompilerPass.cpp + Compiler/ControlFlowGraph.cpp Compiler/GenericASTPass.cpp Compiler/Passes/CFGBuildingPass.cpp Compiler/Passes/FunctionCallCanonicalizationPass.cpp diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/ControlFlowGraph.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/ControlFlowGraph.cpp new file mode 100644 index 0000000000..405e382974 --- /dev/null +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/ControlFlowGraph.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023, Dan Klishch + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#include "AST/AST.h" +#include "Compiler/ControlFlowGraph.h" + +using namespace JSSpecCompiler; + +ErrorOr AK::Formatter::format(FormatBuilder& format_builder, ControlFlowGraph const& control_flow_graph) +{ + auto& builder = format_builder.builder(); + + for (auto const& block : control_flow_graph.blocks) { + builder.appendff("{}:\n", block->m_index); + for (auto const& expression : block->m_expressions) + builder.appendff("{}", expression); + builder.appendff("{}\n", Tree(block->m_continuation)); + } + + // Remove trailing \n + builder.trim(1); + + return {}; +} diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/ControlFlowGraph.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/ControlFlowGraph.h index 46874f39c9..28e0fa3723 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/ControlFlowGraph.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/ControlFlowGraph.h @@ -39,3 +39,12 @@ public: }; } + +namespace AK { + +template<> +struct Formatter : Formatter { + ErrorOr format(FormatBuilder& builder, JSSpecCompiler::ControlFlowGraph const& control_flow_graph); +}; + +} diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/main.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/main.cpp index 85dffdb326..e496d1fd79 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/main.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/main.cpp @@ -21,6 +21,7 @@ using namespace JSSpecCompiler; struct CompilationStepWithDumpOptions { OwnPtr step; bool dump_ast = false; + bool dump_cfg = false; }; class CompilationPipeline { @@ -91,6 +92,9 @@ ErrorOr serenity_main(Main::Arguments arguments) StringView passes_to_dump_ast; args_parser.add_option(passes_to_dump_ast, "Dump AST after specified passes.", "dump-ast", 0, "{all|last||-[,...]}"); + StringView passes_to_dump_cfg; + args_parser.add_option(passes_to_dump_cfg, "Dump CFG after specified passes.", "dump-cfg", 0, "{all|last||-[,...]}"); + args_parser.parse(arguments); CompilationPipeline pipeline; @@ -106,6 +110,9 @@ ErrorOr serenity_main(Main::Arguments arguments) pipeline.for_each_step_in(passes_to_dump_ast, [](CompilationStepWithDumpOptions& step) { step.dump_ast = true; }); + pipeline.for_each_step_in(passes_to_dump_cfg, [](CompilationStepWithDumpOptions& step) { + step.dump_cfg = true; + }); TranslationUnit translation_unit; translation_unit.filename = filename; @@ -132,6 +139,13 @@ ErrorOr serenity_main(Main::Arguments arguments) outln(stderr, "{}", function->m_ast); } } + if (step.dump_cfg && translation_unit.function_definitions[0]->m_cfg != nullptr) { + outln(stderr, "===== CFG after {} =====", step.step->name()); + for (auto const& function : translation_unit.function_definitions) { + outln(stderr, "{}():", function->m_name); + outln(stderr, "{}", *function->m_cfg); + } + } } return 0;