41#ifndef COMPILER_IR_BUILDER_H
42#define COMPILER_IR_BUILDER_H
58 if (
not src.is_valid())
71 <<
"Compiler_IR_Builder: invalid block id " << id;
72 return function.
blocks.access(
id);
84 auto &src =
block(function, from);
87 src.terminator.successors.append(to);
89 dst.predecessors.append(from);
96 auto &
blk =
block(function, block_id);
98 <<
"Compiler_IR_Builder::append_instruction(): block "
103 return blk.instructions.access(
blk.instructions.size() - 1);
110 blk.terminator.span = span;
138 slot.
id =
module.global_slots.size();
140 slot.name = std::move(name);
141 slot.type_id = type_id;
143 module.global_slots.append(std::move(slot));
144 return module.global_slots.size() - 1;
154 function->
name = std::move(name);
155 function->type_id = type_id;
156 function->span = span;
157 function->source_function = source_function;
158 function->next_value_id = 0;
167 <<
"Compiler_IR_Builder::append_function(): null function";
168 function->
id =
module.functions.size();
169 module.functions.append(function);
178 <<
"Compiler_IR_Builder::set_top_level(): null function";
180 module.top_level = function;
194 slot.name = std::move(name);
195 slot.type_id = type_id;
207 blk.label = std::move(label);
209 return function.
blocks.size() - 1;
239 const bool bool_value =
false)
244 inst.result_id = result_id;
245 inst.type_id = type_id;
247 inst.text = std::move(text);
248 inst.bool_value = bool_value;
261 <<
"Compiler_IR_Builder::emit_load_local(): invalid slot id " << slot_id;
265 inst.result_id = result_id;
266 inst.type_id = type_id;
268 inst.local_slot_id = slot_id;
283 inst.result_id = result_id;
284 inst.type_id = type_id;
286 inst.global_slot_id = slot_id;
300 <<
"Compiler_IR_Builder::emit_store_local(): invalid slot id " << slot_id;
303 inst.type_id = type_id;
305 inst.local_slot_id = slot_id;
306 inst.operands.append(value_id);
320 inst.type_id = type_id;
322 inst.global_slot_id = slot_id;
323 inst.operands.append(value_id);
338 inst.result_id = result_id;
339 inst.type_id = type_id;
342 inst.operands.append(operand);
359 inst.result_id = result_id;
360 inst.type_id = type_id;
363 inst.operands.append(lhs);
364 inst.operands.append(rhs);
379 inst.result_id = result_id;
380 inst.type_id = type_id;
382 inst.function_id = function_id;
398 inst.result_id = result_id;
399 inst.type_id = type_id;
401 inst.operands.append(callee);
402 for (
size_t i = 0; i < arguments.
size(); ++i)
417 <<
"Compiler_IR_Builder::set_jump(): block already terminated";
435 <<
"Compiler_IR_Builder::set_branch(): block already terminated";
437 blk.terminator.condition_value = condition_value;
450 <<
"Compiler_IR_Builder::set_return(): exit block not set";
453 <<
"Compiler_IR_Builder::set_return(): block already terminated";
455 blk.terminator.return_value = return_value;
465 auto &
blk =
block(function, block_id);
467 <<
"Compiler_IR_Builder::set_exit(): block already terminated";
470 <<
"Compiler_IR_Builder::set_exit(): exit block already set to a different block";
473 blk.terminator.successors.clear();
482 auto &
blk =
block(function, block_id);
484 <<
"Compiler_IR_Builder::set_unreachable(): block already terminated";
Reusable explicit-value IR model, validation, and deterministic dumps.
#define ah_runtime_error_unless(C)
Throws std::runtime_error if condition does NOT hold.
Small reusable helper that allocates and connects IR nodes.
static void set_terminator_span(Compiler_IR_Function &function, Compiler_IR_Block &blk, const Source_Span &span) noexcept
static void emit_store_global(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, const Compiler_IR_Global_Slot_Id slot_id, const Compiler_IR_Value_Id value_id, const Compiler_Type_Id type_id, const Source_Span &span={})
Emits one store into a global slot.
static Compiler_IR_Value_Id emit_constant(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, const Compiler_Type_Id type_id, std::string text, const Source_Span &span={}, const bool bool_value=false)
Emits one constant instruction.
static void set_unreachable(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, const Source_Span &span={})
Marks one block as unreachable.
static Compiler_IR_Function_Id append_function(Compiler_IR_Module &module, Compiler_IR_Function *function)
Appends one non-top-level function to module and assigns its id.
static void emit_store_local(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, const Compiler_IR_Local_Slot_Id slot_id, const Compiler_IR_Value_Id value_id, const Compiler_Type_Id type_id, const Source_Span &span={})
Emits one store into a local or parameter slot.
static Compiler_IR_Local_Slot_Id add_local_slot(Compiler_IR_Function &function, const Compiler_IR_Slot_Kind kind, std::string name, const Compiler_Type_Id type_id, const Source_Span &span={})
Appends one local or parameter slot to function.
static Compiler_IR_Value_Id allocate_value(Compiler_IR_Function &function) noexcept
Allocates the next explicit IR value id in function.
static void merge_span(Source_Span &dst, const Source_Span &src) noexcept
static Compiler_IR_Value_Id emit_load_global(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, const Compiler_IR_Global_Slot_Id slot_id, const Compiler_Type_Id type_id, const Source_Span &span={})
Emits one load from a global slot.
static void set_exit_block(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id)
Marks one block as the canonical exit block.
static Compiler_IR_Block_Id create_block(Compiler_IR_Function &function, std::string label)
Creates one empty block and returns its id.
static Compiler_IR_Value_Id emit_load_local(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, const Compiler_IR_Local_Slot_Id slot_id, const Compiler_Type_Id type_id, const Source_Span &span={})
Emits one load from a local or parameter slot.
static void set_entry_block(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id)
Marks one block as the canonical entry block.
static Compiler_IR_Block & block(Compiler_IR_Function &function, const Compiler_IR_Block_Id id)
static void add_edge(Compiler_IR_Function &function, const Compiler_IR_Block_Id from, const Compiler_IR_Block_Id to)
Compiler_IR_Module * make_module() const
Allocates one empty IR module.
static Compiler_IR_Global_Slot_Id add_global_slot(Compiler_IR_Module &module, std::string name, const Compiler_Type_Id type_id, const Source_Span &span={})
Appends one global slot to module.
static void set_branch(Compiler_IR_Function &function, const Compiler_IR_Block_Id from, const Compiler_IR_Value_Id condition_value, const Compiler_IR_Block_Id then_block, const Compiler_IR_Block_Id else_block, const Source_Span &span={})
Sets one conditional branch terminator and both outgoing edges.
static void set_exit(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, const Source_Span &span={})
Sets one block terminator to Exit.
static Compiler_IR_Value_Id emit_call(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, const Compiler_IR_Value_Id callee, const DynArray< Compiler_IR_Value_Id > &arguments, const Compiler_Type_Id type_id, const Source_Span &span={})
Emits one call instruction.
static void set_return(Compiler_IR_Function &function, const Compiler_IR_Block_Id from, const Compiler_IR_Value_Id return_value, const Source_Span &span={})
Sets one return terminator and connects it to the exit block.
static void merge_function_span(Compiler_IR_Function &function, const Source_Span &span) noexcept
Compiler_IR_Context & context() const noexcept
Returns the underlying ownership context.
static void set_jump(Compiler_IR_Function &function, const Compiler_IR_Block_Id from, const Compiler_IR_Block_Id to, const Source_Span &span={})
Sets one jump terminator and predecessor/successor edge.
Compiler_IR_Function * make_function(std::string name, const Compiler_Type_Id type_id=0, const Source_Span &span={}, const Compiler_HIR_Function *source_function=nullptr) const
Allocates one function without inserting it into a module.
static Compiler_IR_Value_Id emit_binary(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, const Compiler_Operator_Kind op, const Compiler_IR_Value_Id lhs, const Compiler_IR_Value_Id rhs, const Compiler_Type_Id type_id, const Source_Span &span={})
Emits one binary instruction.
static Compiler_IR_Value_Id emit_unary(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, const Compiler_Operator_Kind op, const Compiler_IR_Value_Id operand, const Compiler_Type_Id type_id, const Source_Span &span={})
Emits one unary instruction.
static Compiler_IR_Value_Id emit_function_ref(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, const Compiler_IR_Function_Id function_id, const Compiler_Type_Id type_id, const Source_Span &span={})
Emits one function reference instruction.
static Compiler_IR_Function * set_top_level(Compiler_IR_Module &module, Compiler_IR_Function *function)
Installs one top-level function body in module.
static Compiler_IR_Instruction & append_instruction(Compiler_IR_Function &function, const Compiler_IR_Block_Id block_id, Compiler_IR_Instruction instruction)
Compiler_IR_Builder(Compiler_IR_Context &context) noexcept
Builds IR nodes inside context.
Compiler_IR_Context * ir_
Arena-backed ownership context for IR nodes.
T * make(Args &&...args)
Allocates and constructs one IR object.
size_t size() const noexcept
Return the current dimension of array.
T & access(const size_t i) const noexcept
Fast access without checking allocation and bound_min_clock checking.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
bool contains_block_id(const DynArray< Compiler_IR_Block_Id > &ids, const Compiler_IR_Block_Id id) noexcept
std::string block_name(const Compiler_IR_Block_Id id)
Main namespace for Aleph-w library functions.
size_t Compiler_IR_Function_Id
Source_Span compiler_hir_merge_spans(const Source_Span &lhs, const Source_Span &rhs) noexcept
Merges two spans without depending on the parser-oriented AST layer.
size_t Compiler_IR_Value_Id
constexpr size_t compiler_ir_invalid_id() noexcept
Returns the sentinel invalid IR id.
size_t Compiler_IR_Block_Id
size_t Compiler_IR_Global_Slot_Id
Compiler_Operator_Kind
Stable operator kinds shared by reusable compiler layers.
size_t Compiler_IR_Local_Slot_Id
Compiler_IR_Slot_Kind
Storage-space classification for slots.
One basic block of IR instructions.
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.
DynArray< Compiler_IR_Slot > local_slots
Parameter/local slots in stable order.
Compiler_IR_Function_Id id
Stable function id within the module.
Source_Span span
Source span of the function/body.
One instruction producing an optional explicit result value.
Compiler_IR_Instruction_Kind kind
Instruction category.
Lowered IR module with shared global slots and functions.
One storage slot used by the IR.
size_t id
Stable slot id within its storage space.
Compiler_IR_Terminator_Kind kind
Terminator category.
Half-open byte range inside a source file.