36#include <gtest/gtest.h>
55 const auto file_id =
sm.add_virtual_file(
"main.aw", source);
57 const auto *
module = parser.parse_module();
85 "let value = add(1, 2);\n",
86 sm, dx, ast_ctx, hir_ctx,
cfg_ctx, typed);
96 " CFGFunction(add): fn(Int, Int) -> Int\n"
102 " Binary(Plus): Int\n"
103 " Variable(x): Int\n"
104 " Variable(y): Int\n"
105 " Terminator: Return\n"
107 " Variable(z): Int\n"
109 " Predecessors: <none>\n"
111 " Statements: <none>\n"
112 " Terminator: Exit\n"
113 " Successors: <none>\n"
114 " Predecessors: B0\n"
115 " CFGFunction(<top-level>)\n"
118 " Block B0 [entry]\n"
123 " Variable(add): fn(Int, Int) -> Int\n"
125 " Constant(Integer, 1): Int\n"
126 " Constant(Integer, 2): Int\n"
127 " Terminator: Jump\n"
129 " Predecessors: <none>\n"
131 " Statements: <none>\n"
132 " Terminator: Exit\n"
133 " Successors: <none>\n"
134 " Predecessors: B0\n");
147 "fn choose(flag) {\n"
156 sm, dx, ast_ctx, hir_ctx,
cfg_ctx, typed);
158 const auto & function = *
cfg->functions.access(0);
164 EXPECT_EQ(function.blocks.access(0).terminator.kind,
165 Compiler_CFG_Terminator_Kind::Branch);
166 ASSERT_EQ(function.blocks.access(0).terminator.successors.size(), 2u);
167 EXPECT_EQ(function.blocks.access(0).terminator.successors.access(0), 2u);
168 EXPECT_EQ(function.blocks.access(0).terminator.successors.access(1), 4u);
169 EXPECT_EQ(function.blocks.access(2).terminator.kind,
170 Compiler_CFG_Terminator_Kind::Jump);
171 EXPECT_EQ(function.blocks.access(4).terminator.kind,
172 Compiler_CFG_Terminator_Kind::Jump);
173 EXPECT_EQ(function.blocks.access(3).terminator.kind,
174 Compiler_CFG_Terminator_Kind::Return);
175 EXPECT_EQ(function.blocks.access(1).terminator.kind,
176 Compiler_CFG_Terminator_Kind::Exit);
195 sm, dx, ast_ctx, hir_ctx,
cfg_ctx, typed);
197 const auto & function = *
cfg->functions.access(0);
203 EXPECT_EQ(function.blocks.access(0).terminator.kind,
204 Compiler_CFG_Terminator_Kind::Jump);
205 EXPECT_EQ(function.blocks.access(0).terminator.successors.access(0), 2u);
206 EXPECT_EQ(function.blocks.access(2).terminator.kind,
207 Compiler_CFG_Terminator_Kind::Branch);
208 EXPECT_EQ(function.blocks.access(2).terminator.successors.access(0), 3u);
209 EXPECT_EQ(function.blocks.access(2).terminator.successors.access(1), 4u);
210 EXPECT_EQ(function.blocks.access(3).terminator.kind,
211 Compiler_CFG_Terminator_Kind::Jump);
212 EXPECT_EQ(function.blocks.access(3).terminator.successors.access(0), 2u);
213 EXPECT_EQ(function.blocks.access(4).terminator.kind,
214 Compiler_CFG_Terminator_Kind::Jump);
215 EXPECT_EQ(function.blocks.access(4).terminator.successors.access(0), 1u);
232 sm, dx, ast_ctx, hir_ctx,
cfg_ctx, typed);
237 EXPECT_NE(
report.warnings.access(0).find(
"unreachable"), std::string::npos);
243 function.
name =
"bad_return";
249 entry.
label =
"entry";
256 exit.terminator.kind = Compiler_CFG_Terminator_Kind::Exit;
260 stray.label =
"stray";
261 stray.terminator.kind = Compiler_CFG_Terminator_Kind::Jump;
262 stray.terminator.successors.append(1);
263 stray.predecessors.append(0);
265 function.
blocks.append(entry);
272 for (
size_t i = 0; i <
report.errors.size(); ++i)
273 if (
report.errors.access(i).find(
"must point to the canonical exit block")
274 != std::string::npos)
Basic-block CFG representation and lowering from structured HIR.
Lowering from the current MVP typed AST into the reusable HIR model.
Recursive-descent parser for the compiler-support MVP grammar.
Arena-backed ownership context for AST nodes.
Arena-backed ownership context for CFG objects.
Transformation engine that lowers typed HIR into reusable CFGs.
Arena-backed ownership context for HIR nodes.
Lowers the MVP typed AST into HIR.
Recursive-descent parser that produces an AST in Compiler_Ast_Context.
Inference-oriented semantic pass for the MVP compiler front-end.
void analyze_module(const Compiler_Module *module)
Runs the typed semantic analysis for module.
const Compiler_Type_Context & type_context() const noexcept
Returns the internal type context.
Diagnostic accumulator and renderer.
bool has_errors() const noexcept
Returns whether any error or fatal diagnostic was emitted.
T & append()
Allocate a new entry to the end of array.
Stores source files and resolves offsets into human-readable data.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Main namespace for Aleph-w library functions.
void exit(const char *file, int line, const char *format,...)
Print a message and exit the program.
Compiler_CFG_Validation_Report validate_cfg_function(const Compiler_CFG_Function &function)
Validates one lowered CFG function structurally.
Compiler_CFG_Validation_Report validate_cfg_module(const Compiler_CFG_Module &module)
Validates all CFGs in a lowered module.
std::string compiler_dump_cfg_module(const Compiler_CFG_Module *module, const Compiler_Type_Context *types=nullptr)
Dumps a complete CFG module in text format for debugging.
Represents a single basic block in a CFG.
Compiler_CFG_Block_Id id
Unique identifier in the function.
std::string label
Human-readable debug label (e.g., "entry", "loop.body").
Compiler_CFG_Terminator terminator
How the block ends.
CFG representation of a single function or top-level body.
Compiler_CFG_Block_Id exit_block
Canonical exit block ID.
std::string name
Function or script name.
DynArray< Compiler_CFG_Block > blocks
All basic blocks belonging to this function.
Compiler_CFG_Block_Id entry_block
Starting block ID.
Aggregates all lowered CFGs for a compilation unit.
Compiler_CFG_Terminator_Kind kind
Category of terminator.
DynArray< Compiler_CFG_Block_Id > successors
List of successor block IDs.