Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
compiler_ir_test.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
36#include <gtest/gtest.h>
37
40#include <Compiler_Parser.H>
41
42using namespace Aleph;
43
44namespace
45{
46 const Compiler_IR_Module *
47 lower_to_ir(const std::string & source,
50 Compiler_Ast_Context & ast_ctx,
51 Compiler_HIR_Context & hir_ctx,
52 Compiler_IR_Context & ir_ctx,
54 {
55 const auto file_id = sm.add_virtual_file("main.aw", source);
56 Compiler_Parser parser(ast_ctx, sm, file_id, &dx);
57 const auto * module = parser.parse_module();
59
60 typed.analyze_module(module);
62
63 Compiler_HIR_Lowering hir_lowering(hir_ctx, typed);
64 const auto * hir = hir_lowering.lower_module(module);
65
67 return ir_lowering.lower_module(hir);
68 }
69}
70
72{
75 Compiler_Ast_Context ast_ctx(1 << 16);
76 Compiler_HIR_Context hir_ctx(1 << 16);
77 Compiler_IR_Context ir_ctx(1 << 16);
79
80 const auto * ir = lower_to_ir(
81 "fn add(x, y) {\n"
82 " let z = x + y;\n"
83 " return z;\n"
84 "}\n"
85 "let value = add(1, 2);\n",
86 sm, dx, ast_ctx, hir_ctx, ir_ctx, typed);
87
88 const auto report = validate_ir_module(*ir);
89 ASSERT_TRUE(report.valid);
90 EXPECT_TRUE(report.warnings.is_empty());
91
92 const auto dump = compiler_dump_ir_module(ir, &typed.type_context());
94 dump,
95 "IRModule\n"
96 " Globals:\n"
97 " g0 value: Int\n"
98 " IRFunction(add): fn(Int, Int) -> Int\n"
99 " Entry: B0\n"
100 " Exit: B1\n"
101 " Slots:\n"
102 " s0 [Parameter] x: Int\n"
103 " s1 [Parameter] y: Int\n"
104 " s2 [Local] z: Int\n"
105 " Block B0 [entry]\n"
106 " Instructions:\n"
107 " v1 = Load s0 : Int\n"
108 " v2 = Load s1 : Int\n"
109 " v3 = Binary(Plus) [v1, v2] : Int\n"
110 " Store s2 [v3] : Int\n"
111 " v4 = Load s2 : Int\n"
112 " Terminator: Return [v4]\n"
113 " Successors: B1\n"
114 " Block B1 [exit]\n"
115 " Instructions: <none>\n"
116 " Terminator: Exit\n"
117 " Successors: <none>\n"
118 " IRFunction(<top-level>)\n"
119 " Entry: B0\n"
120 " Exit: B1\n"
121 " Block B0 [entry]\n"
122 " Instructions:\n"
123 " v1 = FunctionRef f0 : fn(Int, Int) -> Int\n"
124 " v2 = Constant(1) : Int\n"
125 " v3 = Constant(2) : Int\n"
126 " v4 = Call [v1, v2, v3] : Int\n"
127 " Store g0 [v4] : Int\n"
128 " Terminator: Jump\n"
129 " Successors: B1\n"
130 " Block B1 [exit]\n"
131 " Instructions: <none>\n"
132 " Terminator: Exit\n"
133 " Successors: <none>\n");
134}
135
137{
140 Compiler_Ast_Context ast_ctx(1 << 16);
141 Compiler_HIR_Context hir_ctx(1 << 16);
142 Compiler_IR_Context ir_ctx(1 << 16);
144
145 const auto * ir = lower_to_ir(
146 "let base = 10;\n"
147 "fn add_base(x) {\n"
148 " return x + base;\n"
149 "}\n",
150 sm, dx, ast_ctx, hir_ctx, ir_ctx, typed);
151
152 const auto & function = *ir->functions.access(0);
153 ASSERT_EQ(ir->global_slots.size(), 1u);
154 ASSERT_EQ(function.blocks.access(0).instructions.size(), 3u);
155 EXPECT_EQ(function.blocks.access(0).instructions.access(1).kind,
156 Compiler_IR_Instruction_Kind::Load);
157 EXPECT_EQ(function.blocks.access(0).instructions.access(1).global_slot_id, 0u);
158}
159
161{
164 Compiler_Ast_Context ast_ctx(1 << 16);
165 Compiler_HIR_Context hir_ctx(1 << 16);
166 Compiler_IR_Context ir_ctx(1 << 16);
168
169 const auto * ir = lower_to_ir(
170 "fn loop(flag) {\n"
171 " let value = 0;\n"
172 " while (flag) {\n"
173 " if (value == 0) {\n"
174 " value = 1;\n"
175 " } else {\n"
176 " value = 2;\n"
177 " }\n"
178 " continue;\n"
179 " }\n"
180 " return value;\n"
181 "}\n",
182 sm, dx, ast_ctx, hir_ctx, ir_ctx, typed);
183
184 const auto & function = *ir->functions.access(0);
185 const auto report = validate_ir_function(function, ir);
186 ASSERT_TRUE(report.valid);
187 EXPECT_TRUE(report.warnings.is_empty());
188 EXPECT_GE(function.blocks.size(), 7u);
189 EXPECT_EQ(function.blocks.access(2).terminator.kind,
190 Compiler_IR_Terminator_Kind::Branch);
191}
192
194{
197 Compiler_Ast_Context ast_ctx(1 << 16);
198 Compiler_HIR_Context hir_ctx(1 << 16);
199 Compiler_IR_Context ir_ctx(1 << 16);
201
202 const auto * ir = lower_to_ir(
203 "fn dead() {\n"
204 " return 1;\n"
205 " let later = 2;\n"
206 "}\n",
207 sm, dx, ast_ctx, hir_ctx, ir_ctx, typed);
208
209 const auto report = validate_ir_module(*ir);
210 ASSERT_TRUE(report.valid);
211 ASSERT_EQ(report.warnings.size(), 1u);
212 EXPECT_NE(report.warnings.access(0).find("unreachable"), std::string::npos);
213}
214
216{
217 Compiler_IR_Function function;
218 function.name = "manual";
219 function.entry_block = 0;
220 function.exit_block = 1;
221 function.next_value_id = 1;
222
223 Compiler_IR_Block entry;
224 entry.id = 0;
225 entry.label = "entry";
226 entry.terminator.kind = Compiler_IR_Terminator_Kind::Return;
227 entry.terminator.return_value = 1;
229
231 exit.id = 1;
232 exit.label = "exit";
233 exit.terminator.kind = Compiler_IR_Terminator_Kind::Exit;
234
236 wrong_target.id = 2;
237 wrong_target.label = "wrong_target";
238 wrong_target.terminator.kind = Compiler_IR_Terminator_Kind::Unreachable;
239
240 function.blocks.append(entry);
241 function.blocks.append(exit);
242 function.blocks.append(wrong_target);
243
244 const auto report = validate_ir_function(function);
245 ASSERT_FALSE(report.valid);
246 ASSERT_EQ(report.errors.size(), 1u);
247 EXPECT_NE(report.errors.access(0).find("must point to exit block B1"), std::string::npos);
248}
Lowering from the current MVP typed AST into the reusable HIR model.
Lowering from the current MVP HIR into the reusable explicit IR model.
Recursive-descent parser for the compiler-support MVP grammar.
Arena-backed ownership context for AST nodes.
Arena-backed ownership context for HIR nodes.
Lowers the MVP typed AST into HIR.
Arena-backed ownership context for IR nodes.
Lowers typed HIR into explicit-value IR.
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.
Definition ah-source.H:184
#define TEST(name)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::string compiler_dump_ir_module(const Compiler_IR_Module *module, const Compiler_Type_Context *types=nullptr)
Dumps all lowered IR in one module deterministically.
Compiler_IR_Validation_Report validate_ir_module(const Compiler_IR_Module &module)
Validates all functions in one lowered IR module.
void exit(const char *file, int line, const char *format,...)
Print a message and exit the program.
Definition ahDefs.C:125
Compiler_IR_Validation_Report validate_ir_function(const Compiler_IR_Function &function, const Compiler_IR_Module *module=nullptr)
Validates one lowered IR function structurally.
One basic block of IR instructions.
std::string label
Deterministic debug label.
Compiler_IR_Terminator terminator
Explicit block terminator.
Compiler_IR_Block_Id id
Stable block id.
Lowered IR for one function or top-level body.
Compiler_IR_Value_Id next_value_id
Next value id to allocate while lowering.
DynArray< Compiler_IR_Block > blocks
Basic blocks in deterministic id order.
std::string name
Debug or source-level name.
Compiler_IR_Block_Id exit_block
Canonical exit block.
Compiler_IR_Block_Id entry_block
Canonical entry block.
Lowered IR module with shared global slots and functions.
Compiler_IR_Terminator_Kind kind
Terminator category.
DynArray< Compiler_IR_Block_Id > successors
Successor blocks in deterministic order.
Compiler_IR_Value_Id return_value
Return value, if any.