79 return std::numeric_limits<Compiler_CFG_Block_Id>::max();
117 return "Unreachable";
218 template <
typename T,
typename...
Args>
225 [](
void *raw)
noexcept
227 static_cast<T *
>(raw)->~
T();
235 for (
size_t i =
owned_.size(); i > 0; --i)
237 auto &[ptr, destroy] =
owned_.access(i - 1);
238 if (destroy !=
nullptr and ptr !=
nullptr)
260namespace Compiler_CFG_Detail {
265 return "B" + std::to_string(
id);
272 for (
size_t i = 0; i <
ids.size(); ++i)
273 if (
ids.access(i) ==
id)
281 const std::string
padding(indent,
' ');
283 while (begin < text.size())
285 const auto end = text.find(
'\n', begin);
286 if (end == std::string::npos)
293 out <<
padding << text.substr(begin, end - begin) <<
'\n';
306 if (types !=
nullptr)
321 if (types !=
nullptr)
364 return function->
blocks.access(
id);
387 return function->
blocks.size() - 1;
395 auto &src =
block(function, from);
399 src.terminator.successors.append(to);
401 dst.predecessors.append(from);
410 blk.statements.append(stmt);
423 blk.terminator.span = span;
438 blk.terminator.condition = condition;
475 blk.terminator.span = span;
509 for (
size_t i = 0; i < node->statements.size(); ++i)
510 current =
lower_stmt(function, node->statements.access(i), current,
loops);
532 if (node->else_branch !=
nullptr)
541 if (node->else_branch !=
nullptr)
576 if (
loops.is_empty())
589 if (
loops.is_empty())
616 function->
name = name;
617 function->
span = span;
625 for (
size_t i = 0; i < statements.
size(); ++i)
660 if (function->
body ==
nullptr)
683 for (
size_t i = 0; i <
module->functions.size(); ++i)
708 auto fail = [&
report](
const std::string &msg)
711 report.errors.append(msg);
714 if (function.
blocks.is_empty())
716 fail(
"CFG function '" + function.
name +
"' has no basic blocks");
721 fail(
"CFG function '" + function.
name +
"' has invalid entry block");
723 fail(
"CFG function '" + function.
name +
"' has invalid exit block");
727 for (
size_t i = 0; i < function.
blocks.size(); ++i)
729 const auto &block = function.
blocks.access(i);
731 fail(
"CFG function '" + function.
name +
"' has mismatched block id at "
736 +
"' is unterminated");
743 +
" must have exactly one successor");
749 +
" is missing its condition");
752 +
" must have exactly two successors");
758 +
" must point to the canonical exit block");
761 +
" must point to the canonical exit block");
766 fail(
"Only the canonical exit block may use the Exit terminator in function '" + function.
name
780 if (succ >= function.
blocks.size())
812 for (
size_t i = 0; i < function.
blocks.size(); ++i)
819 const auto current =
worklist.pop();
824 const auto &block = function.
blocks.access(current);
833 for (
size_t i = 0; i < function.
blocks.size(); ++i)
836 + function.
name +
"' is unreachable from entry");
854 for (
size_t i = 0; i < child.errors.size(); ++i)
855 report.errors.append(child.errors.access(i));
856 for (
size_t i = 0; i < child.warnings.size(); ++i)
857 report.warnings.append(child.warnings.access(i));
860 for (
size_t i = 0; i <
module.functions.size(); ++i)
876 std::ostringstream
out;
877 if (function ==
nullptr)
879 out <<
"<null-cfg-function>\n";
883 out <<
"CFGFunction(" << function->
name <<
")";
884 if (types !=
nullptr and function->
type_id != 0)
885 out <<
": " << types->to_string(function->
type_id);
890 for (
size_t i = 0; i < function->
blocks.size(); ++i)
892 const auto &block = function->
blocks.access(i);
895 if (block.statements.is_empty())
896 out <<
" Statements: <none>\n";
899 out <<
" Statements:\n";
900 for (
size_t j = 0; j < block.statements.size(); ++j)
909 out <<
" Condition:\n";
919 out <<
" Successors:";
926 out << (j == 0 ?
" " :
", ");
932 out <<
" Predecessors:";
939 out << (j == 0 ?
" " :
", ");
958 std::ostringstream
out;
959 if (module ==
nullptr)
961 out <<
"<null-cfg-module>\n";
965 out <<
"CFGModule\n";
966 for (
size_t i = 0; i <
module->functions.size(); ++i)
Reusable typed high-level IR model independent from any concrete frontend.
Memory arena for fast bulk allocations.
Exception handling system with formatted messages for Aleph-w.
#define ah_runtime_error_unless(C)
Throws std::runtime_error if condition does NOT hold.
size_t size_t int32_t value
size_t size_t int32_t * out
Arena allocator for fast bump-pointer allocation.
void reset() noexcept
Reset arena, making all memory available again.
size_t allocated_size() const noexcept
Get total bytes currently allocated.
static constexpr size_t DEFAULT_SIZE
Default arena size (1 MB).
Arena-backed ownership context for CFG objects.
void reset() noexcept
Resets the arena and destroys all tracked objects.
DynArray< Owned_Object > owned_
size_t allocated_size() const noexcept
Returns currently used bytes.
Compiler_CFG_Context(const Compiler_CFG_Context &)=delete
Compiler_CFG_Context & operator=(const Compiler_CFG_Context &)=delete
~Compiler_CFG_Context() noexcept
Cleans up the context and all managed objects.
Compiler_CFG_Context(const size_t arena_size=AhArenaAllocator::DEFAULT_SIZE)
Constructs a CFG context.
T * make(Args &&...args)
Allocates and constructs an object in the arena.
Transformation engine that lowers typed HIR into reusable CFGs.
void add_edge(Compiler_CFG_Function *function, const Compiler_CFG_Block_Id from, const Compiler_CFG_Block_Id to) const
Adds a directed edge from one block to another.
void set_jump(Compiler_CFG_Function *function, const Compiler_CFG_Block_Id from, const Compiler_CFG_Block_Id to, const Source_Span &span={}) const
Sets a Jump terminator on a block.
Compiler_CFG_Function * lower_function(const Compiler_HIR_Function *function)
Lowers one HIR function into a CFG.
void set_return(Compiler_CFG_Function *function, const Compiler_CFG_Block_Id from, const Compiler_HIR_Expr *value, const Source_Span &span={}) const
Sets a Return terminator on a block.
Compiler_CFG_Context * cfg_
CFG owner.
static void merge_span(Source_Span &dst, const Source_Span &src)
Utility to merge a source span into a destination span.
void set_branch(Compiler_CFG_Function *function, const Compiler_CFG_Block_Id from, const Compiler_HIR_Expr *condition, const Compiler_CFG_Block_Id then_block, const Compiler_CFG_Block_Id else_block) const
Sets a Branch terminator on a block.
Compiler_CFG_Module * lower_module(const Compiler_HIR_Module *module)
Lowers one HIR module into function CFGs and optional top-level CFG.
void set_exit(Compiler_CFG_Function *function, const Compiler_CFG_Block_Id id) const
Sets an Exit terminator (only for the canonical exit block).
size_t dead_counter_
ID generator for unreachable blocks.
Compiler_CFG_Block_Id ensure_current_block(Compiler_CFG_Function *function, Compiler_CFG_Block_Id current)
Ensures a valid current block exists, creating a "dead" one if needed.
Compiler_CFG_Lowering(Compiler_CFG_Context &ctx, const Compiler_Type_Context *type_ctx=nullptr) noexcept
Builds a CFG lowerer over the specified context.
Compiler_CFG_Function * lower_statement_sequence(const std::string &name, const Source_Span &span, const Compiler_Type_Id type_id, const Compiler_HIR_Function *source_function, const DynArray< Compiler_HIR_Stmt * > &statements)
Lowers a sequence of statements into a new CFG function.
Compiler_CFG_Block & block(Compiler_CFG_Function *function, const Compiler_CFG_Block_Id id) const
Accesses a block by ID within a function.
void set_unreachable(Compiler_CFG_Function *function, const Compiler_CFG_Block_Id id, const Source_Span &span={}) const
Sets an Unreachable terminator on a block.
size_t while_counter_
ID generator for loop blocks.
const Compiler_Type_Context * type_context() const noexcept
Returns the optional type context used by this lowerer.
size_t if_counter_
ID generator for conditional blocks.
const Compiler_Type_Context * types_
Type metadata source.
void append_linear_stmt(Compiler_CFG_Function *function, const Compiler_CFG_Block_Id id, const Compiler_HIR_Stmt *stmt) const
Appends a linear statement to a block and updates its span.
Compiler_CFG_Block_Id create_block(Compiler_CFG_Function *function, std::string label) const
Creates a new basic block in the given function.
Compiler_CFG_Block_Id lower_stmt(Compiler_CFG_Function *function, const Compiler_HIR_Stmt *stmt, Compiler_CFG_Block_Id current, DynArray< Loop_Targets > &loops)
Recursively lowers an HIR statement into the CFG.
Context owning all compiler type nodes.
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.
T & append()
Allocate a new entry to the end of array.
bool is_empty() const noexcept
Return true if the array is empty.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Freq_Node * pred
Predecessor node in level-order traversal.
bool contains_block_id(const DynArray< Compiler_CFG_Block_Id > &ids, const Compiler_CFG_Block_Id id) noexcept
Checks if a block ID is present in a list of IDs.
void append_indented_text(std::ostream &out, const std::string &text, const size_t indent)
Appends text to a stream with a consistent indentation.
bool is_linear_stmt(const Compiler_HIR_Stmt *stmt) noexcept
Checks if an HIR statement is linear (non-branching).
void append_hir_stmt_dump(std::ostream &out, const Compiler_HIR_Stmt *stmt, const Compiler_Type_Context *types, const size_t indent)
Dumps a HIR statement to the stream for debugging.
std::string block_name(const Compiler_CFG_Block_Id id)
Generates a standard block label (e.g., "B0").
void append_hir_expr_dump(std::ostream &out, const Compiler_HIR_Expr *expr, const Compiler_Type_Context *types, const size_t indent)
Dumps a HIR expression to the stream for debugging.
Main namespace for Aleph-w library functions.
Compiler_CFG_Terminator_Kind
Categories of basic block terminators.
@ Jump
Unconditional jump to exactly one successor.
@ Unreachable
Marks code paths that should never be executed (e.g., after a break).
@ None
Unset or invalid terminator.
@ Return
Function exit with an optional return value.
@ Branch
Conditional branch to two successors (true and false targets).
@ Exit
Sentinel terminator for the canonical exit block.
@ Return
Return one register value.
@ Branch
pc <- condition ? true_target : false_target
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.
constexpr Compiler_CFG_Block_Id compiler_cfg_invalid_block_id() noexcept
Returns the sentinel value for an invalid block ID.
std::string compiler_dump_cfg_function(const Compiler_CFG_Function *function, const Compiler_Type_Context *types=nullptr)
Dumps a single CFG function in text format for debugging.
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
Compiler_CFG_Validation_Report validate_cfg_function(const Compiler_CFG_Function &function)
Validates one lowered CFG function structurally.
Itor3 merge(Itor1 source1Beg, Itor1 source1End, Itor2 source2Beg, Itor2 source2End, Itor3 destBeg)
Merge two sorted ranges.
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.
std::string compiler_dump_hir_expr(const Compiler_HIR_Expr *expr, const Compiler_Type_Context &types)
Dumps one HIR expression in a deterministic text format.
const char * compiler_cfg_terminator_kind_name(const Compiler_CFG_Terminator_Kind kind) noexcept
Returns a stable string name for a CFG terminator kind.
size_t Compiler_CFG_Block_Id
Typedef for unique block identifiers within a function.
std::string compiler_dump_hir_stmt(const Compiler_HIR_Stmt *stmt, const Compiler_Type_Context &types)
Dumps one HIR statement in a deterministic text format.
Represents a single basic block in a CFG.
Source_Span span
Span covering all statements and the terminator.
DynArray< const Compiler_HIR_Stmt * > statements
Ordered list of linear statements.
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.
DynArray< Compiler_CFG_Block_Id > predecessors
List of block IDs that jump to this block.
bool is_terminated() const noexcept
Checks if the block has a valid terminator set.
Internal tracker for objects with non-trivial destructors.
void(* destroy)(void *) noexcept
CFG representation of a single function or top-level body.
Source_Span span
Overall source span.
Compiler_Type_Id type_id
Return type or function type ID.
bool is_top_level() const noexcept
Checks if this CFG represents the global top-level script.
Compiler_CFG_Block_Id exit_block
Canonical exit block ID.
const Compiler_HIR_Function * source_function
Pointer to original HIR (null for top-level).
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.
Internal state for loop lowering.
Compiler_CFG_Block_Id continue_block
Compiler_CFG_Block_Id break_block
Aggregates all lowered CFGs for a compilation unit.
Compiler_CFG_Function * top_level
Optional CFG for global statements.
DynArray< Compiler_CFG_Function * > functions
CFGs for all defined functions.
Detailed information about a block's termination.
const Compiler_HIR_Expr * value
Return value (valid if kind is Return).
Source_Span span
Source location of the terminator.
const Compiler_HIR_Expr * condition
Branch condition (valid if kind is Branch).
Compiler_CFG_Terminator_Kind kind
Category of terminator.
DynArray< Compiler_CFG_Block_Id > successors
List of successor block IDs.
Detailed results of a CFG structural validation.
DynArray< std::string > errors
List of critical violations.
bool valid
True if no errors were found.
DynArray< std::string > warnings
List of non-fatal issues (e.g., unreachable blocks).
Structured block statement.
DynArray< Compiler_HIR_Stmt * > statements
Nested statements.
Base class for HIR expressions.
std::string name
Function name.
Compiler_Type_Id type_id
Full function type.
Compiler_HIR_Block_Stmt * body
Function body.
Structured conditional statement.
DynArray< Compiler_HIR_Function * > functions
Lowered top-level functions.
DynArray< Compiler_HIR_Stmt * > statements
Lowered top-level statements.
Source_Span span
Source region associated with the HIR node.
Base class for HIR statements.
Compiler_HIR_Stmt_Kind kind
Runtime node kind.
Structured while-loop statement.
DynArray< Compiler_SSA_Block_Id > predecessors
Predecessor ids in deterministic order.
Compiler_SSA_Block_Id id
Dense SSA block id.
std::string label
Deterministic debug label.
Compiler_SSA_Terminator terminator
Explicit block terminator.
DynArray< Compiler_SSA_Block_Id > successors
Successors in deterministic order.
Compiler_IR_Terminator_Kind kind
Terminator category.
Represents a missing value.
Half-open byte range inside a source file.
bool is_valid() const noexcept
Returns whether the span belongs to a registered file.
Lazy and scalable dynamic array implementation.