Expand description
Block-local cleanup passes over the qcode IR.
These are the transforms that a lifter wants while it is still building a
function: they are cheap, local, and safe to run on a partially discovered
CFG. They deliberately need no alias analysis, no calling convention, and no
knowledge of the target architecture — which is what lets them sit below
qcode_analysis and be used on their own by qcode_vm and other
consumers that only ever want the cleanup, never the decompiler.
§The context view
A pass reads the module through a PassCtx and mutates a single
FunctionBody borrowed &mut from the bodies registry. Splitting a
Context into those two halves is what with_body_mut does. Because
PassCtx holds only shared references it is Copy, so a caller hands the
same view to every helper.
PassCtx is the environment-free half of the richer view used by the full
analysis pipeline: it carries the module’s shared IR state and published
interfaces, but no architecture configuration. Arch-aware passes live in
qcode_analysis and take the richer view instead.
§Example
A pure instruction nothing reads is removed; one whose result is used is kept.
use qcode::{context::Context, qcode};
use qcode_passes::remove_dead_insns;
let mut ctx = Context::new();
qcode!(
ctx,
"
fn f:
<entry>
%unused = i64 0x2 + 0x3;
%kept = i64 0x4 + 0x5;
goto <exit @r=%kept>;
<exit @r:i64>
goto <0x1001>;
"
);
assert!(remove_dead_insns(&mut ctx, entry));
// Running it again is a no-op: the pass is idempotent.
assert!(!remove_dead_insns(&mut ctx, entry));Re-exports§
pub use cfg::absorb_straight_line;pub use dce::dead_insns;pub use dce::remove_dead_insns;pub use dce::remove_dead_insns_body;pub use symbolize::resolve_addresses;pub use symbolize::resolve_strings;
Modules§
- cfg
- CFG simplification: merging straight-line blocks, dropping empty forwarding blocks, and folding degenerate branches.
- dce
- Dead-instruction elimination: removing pure instructions nothing reads.
- symbolize
- Attaching meaning to bare integer literals.
Structs§
- PassCtx
- The bodies-free module view a block-local pass reads through:
{shared, interfaces}.
Functions§
- replace_
terminator_ with_ branch - split
- Split a context into its mutable bodies registry and the read-only module
view, so a worker can hold one body
&mutwhile reading shared state. - with_
body_ mut - Run
fagainst functionfid’s body borrowed&mutout ofctx, with the matching read-only view.