Helper Functions
The toolkit a pass is built from.
You rarely inspect an ir_stat field by hand or construct one from scratch: the tools:: helpers recognize hueristics, answer analysis questions, and build correct replacements for you.
This page is the map of what lives where.
Two families cover almost everything a pass writes:
- tools::stat / tools::exprs - predicates (
is_*), mutators, and generators over statements and expressions. Declared underir/lifter/tools/extras/. - tools:: analysis namespaces - the questions passes ask about the surrounding code: what dominates what, what is safe, what a value resolves to. Declared in
ir/lifter/tools/tools.hpp, defined underir/lifter/tools/code/.
Prefer a helper over hand-written field access. The predicates encode the exact field layout each kind uses, so a helper stays correct even when a hueristic has edge cases the obvious check would miss.
Recognizing Hueristics
Every kind has an is_* predicate, and most take optional arguments to narrow the match.
They are the first line of almost every pass.
tools::stat (statements)
- Kinds -
is_goto_label,is_label,is_end,is_condition,is_call,is_return, and one per keyword. Prefer these over a rawp->is_k<...>()when the named predicate exists. - tools::stat::branch - branch-specific queries:
is_cond_goto_label,same_cond_goto_labels,is_single_label_ref, and the family that reasons about conditional gotos and their targets. - tools::stat::flags - Flag-statement predicates.
- tools::stat::assignment - Assignment-hueristic queries.
- tools::stat::mutate - In-place statement rewrites, including
extract_volatiles_stats(pull the side-effecting parts out of a statement before you remove it) andmimic_compare.
tools::exprs (expressions)
Under tools::exprs::values, one predicate per expression hueristic:
is_arith, is_reg, is_arg, is_upvalue, is_call, is_closure, is_condition, and more.
Most are overloaded to also match a specific value example: is_reg(e, r) matches register r, is_integer(e, n) matches literal n, is_boolean(e, b) matches a specific bool.
The tools::exprs::values::types sub-namespace answers type questions on an expression:
is_basic, is_same_implicit, is_restricted, is_resulting_type, is_under_signed / is_under_unsigned, is_reg_cast, is_boolean_cast.
Building Replacements: Generate Helpers
When a pass produces new code, it builds through the generators, never by adding stuff to ir_stat.
tools::stat::generate
One builder per statement kind, each returning a ready
shared_ptr<ir_stat>: end(), label(loc), goto_label(loc), cond_goto_label(l, b, loc, r), while_stat(...), until(...), repeat(), else_stat(), break_stat(),
continue_stat(), assignment(l, r), table_assignment(t, idx, v), create_stack(l), and more.
tools::exprs::generate
The matching expression builders: memoryread(target, bits) and the rest plus the raw emit_* API on ir_expr itself.
See Data Model -> the emit API for the full list.
SSA (tools::ssa)
Everything a pass needs to reason about definitions and uses without rebuilding SSA. See Control Flow & SSA for the model.
- defined_scope(pm, ssa, start, target) - Is the register defined in scope at
start. - used(pm, ssa, start, end, target) - Is the register read anywhere in the range.
- use_def_chain(ssa, target, limit) - The definition chain of a value, scalar or phi. Returns
use_def_resultentries carrying theassignment_kind, the scalar version, and any phi members. - is_placeholder_variable(pm, ssa, target, start) - A value assigned before every branch overwrites it, so it never affects execution.
- same_highlevel_scope_id(pm, ssa, l, r) - Do two addresses share a high-level scope.
- tools::ssa::extract - the heavier queries:
dominant_define,same_assignments,block_assignment(withhit_type::all/first/dominant),next_assignment_same_scope_assignment,all_dominant_singletons,parent_page, andlinked.
Analysis namespaces
Grouped by the question they answer, all under luramas::ir::tools:
- accumulate - Gather things across a block or range: label refs, dominant addresses, jump-outs, break-outs, keywords in a block. The accumulate::orphans sub-namespace gathers page starts/ends and implicit gotos.
- find - Locate a statement by pointer or predicate (
findreturnspm.amount()when nothing matches), or find an expression by callback. - violations - Does a block break the branch rules;
violations::accumulatecollects them. - contains - Membership queries over statements and expressions, with
orphansandimplicitsub-namespaces. - types - Type queries over expressions and definitions.
- extract - Pull sub-structures out (
space_stat,stats,exprs,ir). - count - Counts by callback, kind, or tkind:
instsin a range,definition_parameters,refsto a label, and thetk<>/keyword<>templates. - dominant - Dominance queries and
dominant::extract. - control_flow - Control-flow-level helpers, with a
blocksub-namespace. - loops - Loop recognition and structure.
- paging - The native page model helpers (the largest analysis namespace).
- compute - Evaluate expressions and statements, including
compute::integralsandcompute::strings, backed by gmp/mpfr so wide math never loses precision. - simulate - Reach a target through basic loop threading when direct control flow cannot.
- safety - Safety queries, including
safety::arith. - guarantee - What an expression or statement is guaranteed to do.
- match / replace - Hueristic matching and rewriting; replace::match_wild_cards powers the virtual-function tables (see Customization).
- inliner - Inlining support, with a
cvasub-namespace. - mutations - Higher-level mutations like
pop_condandsafe_if_dupe. - Remaining helpers, each named for what it does.
When You Need Something That is Not Here
If you find yourself reading ir_stat fields directly or building an ir_expr by hand, check for an is_* predicate and a generate::* builder first.
Adding a new helper to the right namespace is almost always better than inlining the logic into a pass: the next pass will want it too. See Writing a Pass.