Skip to main content

Context

Struct Context 

Source
pub struct Context<'str> {
    pub shared: Shared<'str>,
    pub interfaces: Registry<FunctionId, FunctionInterface<'str>>,
    pub bodies: Registry<FunctionId, FunctionBody<'str>>,
}
Expand description

The central arena that owns all IR state.

Context is the single source of truth for every value (instructions, varnodes, literals, blocks, functions), every memory space, and the bidirectional maps that let you look up values by name or by machine address.

§Usage

Create a context with Context::new and pass &mut references to a Builder when constructing IR, or to analysis passes when transforming it.

use qcode::context::Context;

let ctx = Context::new();
// `ctx.shared.default_space` is the RAM space created by `new`.
let _ram = ctx.shared.default_space;

§Lifetime parameter 'str

The 'str lifetime is the lifetime of interned string data used for names and space identifiers. When names are owned (e.g. generated names), they are stored as Cow::Owned; when they are borrowed from source data they are Cow::Borrowed and must outlive the context.

Fields§

§shared: Shared<'str>

Module-shared IR state: everything that is not per-function interface or body storage (regimes 1–3 of the context-split design — architecture, interners, module maps, truths). Reached today behind &mut Context; Context::split() (stage 5b-ii c.2) will hand it out as a frozen &Shared view while the bodies registry is borrowed mutably.

§interfaces: Registry<FunctionId, FunctionInterface<'str>>

Per-function interface storage — the caller-reasoning surface (name, address, kind, external-ness, signature) held in lockstep with bodies under the same FunctionId space. Never checked out: a co-checked-out callee answers interface queries from here.

§bodies: Registry<FunctionId, FunctionBody<'str>>

Per-function body storage. Each function owns its instruction/block/param/ edge arenas; the composite-ID accessors (Context::instruction etc.) route through here. A checked-out function’s body is moved out of its slot (leaving an empty body); its interface stays put, so callers always read the real interface.

Implementations§

Source§

impl<'str> Context<'str>

Source

pub fn new() -> Self

Creates a new, empty context with a single default RAM space.

The default space has a word size of 1 byte and an address size of 8 bytes (suitable for 64-bit architectures). Its SpaceId is stored in Context::default_space.

Source

pub fn try_get_space(&self, name: &str) -> Option<SpaceId>

Returns the SpaceId for the named space, or None if it has not been registered.

Source

pub fn get_or_make_named_space(&mut self, name: &str) -> SpaceId

Resolve a space by name for textual lowering: an already-registered named space, the default space when its name matches (the default ram space is not in named_spaces), or a freshly-registered RAM space otherwise. Used by the canonical load(space:size, ptr) / store(...) lowering.

Source

pub fn add_space(&mut self, space: Space) -> SpaceId

Adds a space to the context, registering its name, and returns its ID.

Source

pub fn space_count(&self) -> usize

Returns the number of spaces registered in this context.

Source

pub fn set_primary_entrypoint(&mut self, entrypoint: Option<u64>)

Source

pub fn primary_entrypoint(&self) -> Option<u64>

Source

pub fn set_ignored_functions(&mut self, addrs: HashSet<u64>)

Record the set of function entry addresses whose optimization the user asked to skip (--ignore). Per-function passes consult Context::is_function_ignored and skip these functions.

Source

pub fn ignored_functions(&self) -> &HashSet<u64>

The function entry addresses whose optimization is being skipped.

Source

pub fn is_function_ignored(&self, addr: Option<u64>) -> bool

Whether the function at addr was marked ignored (--ignore). A None address (synthetic functions with no entry) is never ignored.

Source

pub fn set_target_os(&mut self, os: TargetOs)

Records the loaded binary’s operating system (set by the loader from the container format).

Source

pub fn target_os(&self) -> TargetOs

The loaded binary’s operating system, or TargetOs::Unknown.

Source

pub fn set_linked_libraries(&mut self, libs: Vec<String>)

Records the library names the binary links against (set by the loader from the container format, or by --assume-libs).

Source

pub fn linked_libraries(&self) -> &[String]

Library names the loaded binary links against (ELF DT_NEEDED sonames, PE import DLL names). Empty when unknown.

Source

pub fn load_spaces(&mut self, spaces: Registry<SpaceId, Space>)

Replaces the spaces registry wholesale. Intended for initialization from a pre-built spec.

Source

pub fn mark_protections_known(&mut self)

Mark the binary’s memory protections as established (the memory_protections pass has run), so executability checks narrow from the permissive default to the real per-segment flags.

Source

pub fn protections_known(&self) -> bool

Whether the binary’s per-segment protection flags are authoritative.

Source

pub fn assume_executable( &mut self, binary: &dyn BinaryFormat, addr: u64, ) -> bool

The lifter’s pre-decode executability gate, modeling executability as a Proposition::ExecutableMemory. Returns whether addr should be lifted:

  • protections not yet established → optimistic default r/x (true); the binary’s segment flags are not consulted in this case;
  • protections known and the region is executable → true;
  • protections known and the region is non-executable (or unmapped) → false (skip), recording the proven fact ExecutableMemory{start, end} = false for the whole containing segment of a mapped-but-non-executable target.

The proposition is keyed by the containing segment, not the individual address, so repeated skips in the same non-executable region collapse to a single truth-map entry rather than one per byte.

A known value for the containing region (a proven fact, or a user override seeded as known) wins over the raw segment flags, so the user can force a region executable or non-executable from the Assumptions panel.

Source

pub fn discover(&mut self, discovery: Discovery) -> bool

Record a discovered code address (typed: a new function or a block within an existing function) for the lift_new_addresses pass to lift.

Source

pub fn discover_code(&mut self, func_entry: u64, source_block: u64, target: u64)

Convenience for the common case: the jump-table pass resolved a branch in the function at func_entry to target, a block within that function.

source_block is the address of the block ending in the indirect branch, so the lifter can connect a real CFG edge from it to target in the clean IR (the resolution is otherwise only reflected in the disposable optimized clone, which would leave the target an orphan that function-splitting and reachability cannot follow).

Source

pub fn drain_discoveries(&mut self) -> Vec<Discovery>

Remove and return every pending discovery, leaving the queue empty.

Source

pub fn discoveries(&self) -> impl Iterator<Item = &Discovery> + '_

Iterate pending discoveries without consuming them.

Source

pub fn has_no_discoveries(&self) -> bool

True if there are no pending discoveries.

Source

pub fn lifted_code_seeds(&self) -> Vec<CodeSeed>

Every code address lifted in this context, as portable CodeSeeds. Used to export a “code map” that pre-seeds a later run of the same binary.

Source

pub fn seed_code(&mut self, seeds: impl IntoIterator<Item = CodeSeed>)

Enqueue exported CodeSeeds as pending discoveries so the lifter reaches them in its first pass. Call before lifting begins; seeds whose key already has a terminal outcome are ignored by the queue.

Source

pub fn mark_discovery_lifted(&mut self, key: DiscoveryKey)

Source

pub fn mark_discovery_failed( &mut self, key: DiscoveryKey, reason: impl Into<String>, )

Source

pub fn mark_discovery_skipped( &mut self, key: DiscoveryKey, reason: impl Into<String>, )

Source

pub fn get_or_make_block(&mut self, addr: u64, func: FunctionId) -> BlockId

Returns the BlockId for a block at addr, creating one if needed.

The newly created block is named after the address in hex and registered in the address map.

Source

pub fn get_or_make_block_indexed( &mut self, addresses: &mut AddressIndex, addr: u64, func: FunctionId, ) -> BlockId

Indexed construction variant of get_or_make_block. The caller owns addresses for the duration of its lifting/lowering operation and threads it through every address-bearing mutation.

Source

pub fn split_block_at_address( &mut self, addresses: &mut AddressIndex, block: BlockId, addr: u64, ) -> BlockId

Re-establishes addr as the start of a block of its own, when it is currently interior to block — one of the addresses block absorbed.

§Why this discards code instead of moving it

The obvious split copies the instructions from addr onward into the new block. That is only sound while a block’s instructions still correspond, one run at a time, to the guest instructions they came from — and they do not: a discovered block is optimized in place, so stores have been forwarded and dead computation removed across the guest instruction boundaries. There is no longer an instruction that “is” the start of addr.

So neither half’s code survives the split. Both blocks are emptied and keep only their place in the graph: block keeps its identity, so every branch already targeting it stays valid, and the new block takes addr. An empty block carrying an address is already this module’s request to lift it, so the code comes back from the guest bytes — which are the only faithful source for it — the next time control reaches either half.

Source

pub fn builder(&mut self, block: BlockId) -> Builder<'str, '_>

Borrows one function body and creates the concrete body-local builder positioned at block.

Source

pub fn builder_at(&mut self, address: u64) -> Builder<'str, '_>

Test/API convenience for preparing a machine-address block before narrowing construction to its body-local builder.

Source

pub fn bytes_display(&self, id: BytesId) -> BytesDisplay

The forced rendering mode for a Bytes blob, or BytesDisplay::Auto if unset.

Source

pub fn set_bytes_display(&mut self, id: BytesId, mode: BytesDisplay)

Force how a Bytes blob renders as a b"..." literal everywhere. Setting BytesDisplay::Auto clears any existing override.

Source

pub fn block_ids(&self) -> Vec<BlockId>

Returns a list of all live blocks in the context (across all functions).

Source

pub fn instruction_ids(&self) -> Vec<InstructionId>

Returns all live instructions across all functions in stable logical-ID order. Function arenas iterate in dense physical order, so this explicit sort preserves the observable whole-context order across compaction.

Source

pub fn function_ids(&self) -> Vec<FunctionId>

Returns a list of all functions in the context.

Source

pub fn anon_function(&mut self) -> FunctionId

Mints a fresh, uniquely-named anonymous function and returns its id.

A block must be born into some function’s arena; this hands out a host for standalone blocks (tests, the raw-hex/bare-block lift paths, and the pyqcode API that build a block without an enclosing function).

Source

pub fn instruction_arena_stats(&self) -> (usize, usize)

(issued_ids, removed_ids) across every function’s instruction arena.

Source

pub fn body_arena_stats(&self) -> BodyArenaStats

Aggregate issued/live/dead and structural capacity for every body arena.

This is the stable reporting surface used by the Stage 7 before/after probe. Keeping the aggregation here avoids exposing arena internals to measurement binaries.

Source

pub fn shrink_bodies_to_fit(&mut self)

Releases body-arena capacity retained from peak analysis churn in every function (see FunctionBody::shrink_to_fit).

Purely an allocator hint: IDs, ordering, and rendered IR are unchanged. Called once at explicit end-of-mutation boundaries such as pipeline convergence; nothing depends on it running.

Source

pub fn instructions( &self, ) -> impl Iterator<Item = InstructionRef<'str, '_>> + '_

Iterates over all the (live) instructions in the context.

Source

pub fn blocks(&self) -> impl Iterator<Item = BlockRef<'str, '_>> + '_

Iterates over all the (live) blocks in the context.

Source

pub fn functions(&self) -> FunctionIter<'str, '_>

Iterates over all the functions in the context

Source

pub fn iter(&self) -> FunctionIter<'str, '_>

Iterates over all the functions in the context alias for functions()

Source

pub fn varnodes(&self) -> impl Iterator<Item = VarnodeRef<'str, '_>> + '_

Source

pub fn varnode_count(&self) -> usize

Number of varnodes in the context. The varnode registry is append-only, so this is monotonic and an unchanged value means an unchanged varnode set — used to validate caches keyed on the register/varnode layout (e.g. the alias RegisterBase in the analysis layer).

Source

pub fn remove_cfg_edge(&mut self, func: FunctionId, edge_id: EdgeId)

Removes a CFG edge, unlinking it from both incident blocks’ edge sets and physically dropping its payload. The module-path (function-qualified) spelling of FunctionBody::remove_cfg_edge.

Source

pub fn rehome_owned_blocks( &mut self, addresses: &mut AddressIndex, target: FunctionId, olds: &[BlockId], ) -> HashMap<BlockId, BlockId>

Relocate every block in olds into target’s own arena. The originals remain owned by their source functions until deletion; only the clones are rostered in target, so ownership and storage never diverge. This is the storage mover split_function_at uses to make a split-off tail self-stored.

A pure storage move: the resulting IR is semantically identical. Every relocated block is deep-cloned into target (preserving instruction types, machine addresses, and labels), all intra-set value/block references are remapped to the clones, the incident CFG edges are rebuilt between the new blocks (and their unmoved neighbours), the block addresses and the function root are re-pointed, and the originals are deleted. target’s reverse-use map is rebuilt from its live instructions afterwards.

Assumes the relocated set is closed (the caller strips every cross-function CFG edge and rewrites foreign terminator targets to TailCalls first): every reference from a relocated block resolves to another relocated block, an unmoved block of target, or a shared value; a reference into a third function is a bug upstream, and debug builds assert against it.

Source

pub fn split_function_at(&mut self, block: BlockId) -> FunctionId

Split at block, returning the function G whose entry is block. This is the strict-locality construction verb (context-split ruling 2): a control transfer that lands mid-function is modelled as a function split — never a foreign block reference.

Concretely it: (i) reuses the function already registered at block’s address (a stub minted by a call, which may already have adopted block as its root) or mints a conventional fn_<addr> (synthesized interface, unknown ABI — the optimization pipeline derives its purity/clobber/ABI facts later); (ii) extracts the tail reachable from block, stopping at other function entries (split_tail), and reassigns it to G (an absorbed tail may currently be owned by the function that absorbed it); (iii) rewrites every terminator that statically targeted block — in the absorbing function and in any already-lifted caller — into a function-level TailCall (G for an unconditional Branch; a fresh intra-function trampoline block ending in a TailCall for a conditional CBranch arm), strips every cross-function CFG edge incident to the moved tail, and rewrites any foreign back-edge out of the tail the same way; (iv) relocates the tail into G’s own arena (rehome_owned_blocks) so G is self-stored. Afterwards no foreign block reference and no cross-function edge survives.

block must carry a machine address.

Source

pub fn split_function_at_indexed( &mut self, addresses: &mut AddressIndex, block: BlockId, ) -> FunctionId

Indexed construction variant of split_function_at.

Source

pub fn assume_true(&mut self, prop: Proposition) -> bool

Assumes prop is true. Returns false (and records nothing) if the proposition is already assumed or known false; returns true if it was recorded or already held with the same polarity (idempotent). The recording pass is taken from pass_scope.

Source

pub fn assume_false(&mut self, prop: Proposition) -> bool

Assumes prop is false. Mirror of assume_true.

Source

pub fn set_known(&mut self, prop: Proposition, value: bool) -> bool

Records prop = value as proven, overriding any assumption. If this contradicts an existing assumption, a Violation is recorded — the checkpoint+replay driver’s signal to discard this working copy. Contradicting an existing known fact is a logic error.

Returns true if the fact is novel (no prior truth, or it overturned an assumption): the driver replays when a round produced novel facts.

Source

pub fn seed_known(&mut self, prop: Proposition, value: bool, pass: PassName)

Seeds a proven fact carried over from an earlier checkpoint+replay round. Unlike set_known this is not “novel”: it must not retrigger a replay, and seeding over an existing entry is a logic error (seed before any pass runs).

pass is the identity of the pass that originally proved the fact (as harvested from known_facts), preserved across the round boundary so the converged context still names the proving pass rather than the re-seeding driver.

Source

pub fn truth(&self, prop: Proposition) -> Option<Truth>

The recorded Truth of prop, if any.

Source

pub fn set_assumed_call_convention(&mut self, effect: Option<AssumedCallEffect>)

Install (or clear) the cached effect backing the opt-in AssumeCallingConvention hypothesis — see Shared::assumed_call_convention. The assume_calling_convention pass calls this alongside recording Proposition::AssumeCallingConvention.

Source

pub fn assumed_call_convention(&self) -> Option<&AssumedCallEffect>

The cached AssumedCallEffect, if the hypothesis is active this round. Mirror of Shared::assumed_call_convention.

Source

pub fn known(&self, prop: Proposition) -> Option<bool>

The proven value of prop: Some only for known entries.

Source

pub fn truths(&self) -> impl Iterator<Item = (Proposition, Truth)> + '_

Iterates over every recorded truth (assumed and known).

Source

pub fn known_facts( &self, ) -> impl Iterator<Item = (Proposition, bool, PassName)> + '_

Iterates over the proven facts, for the replay driver to harvest into the next round’s seed_known calls.

Source

pub fn violations(&self) -> &[Violation]

The violations recorded this round (proven facts that contradicted an assumption). Non-empty means derived IR may be wrong: replay.

Source

pub fn known_contradictions(&self) -> &[KnownContradiction]

Facts proven this round that contradicted an existing known fact (e.g. a user override the analysis disproved). Non-empty means the analysis cannot honor the forced value; the driver surfaces this as a hard error.

Source

pub fn get_literal_value(&self, id: LiteralId) -> u64

Returns the raw u64 backing value of the literal id.

Source

pub fn get_insn(&self, id: InstructionId) -> InstructionRef<'str, '_>

Returns an immutable reference to the instruction identified by id.

Source

pub fn body(&self, fid: FunctionId) -> &FunctionBody<'str>

The function body fid (context-split stage 5a bridging accessor).

Names the owning function explicitly so IR reads route through the body’s function-local raw accessors — ctx.body(fid).block(id) in place of the globally routed BasicBlock::from_id(ctx, id). This is the module-scope (&Context) obtain-form; a function pass reaches the same body accessors through its checked-out host. After the stage-4 func-strip only this obtain step changes (the caller already holds &FunctionBody); the .block(id) call on the result is unchanged.

Source

pub fn body_mut(&mut self, fid: FunctionId) -> &mut FunctionBody<'str>

The function body fid, mutably (see Context::body).

Source

pub fn push_insn( &mut self, func: FunctionId, insn: Instruction<'str>, ) -> InstructionId

Appends an instruction to func’s body and records all its operands in the users map.

§Immutability invariant

Instructions are considered immutable after this call. If you alter the operands of an instruction after insertion the users map will be stale. Rewrite operands through replace_all_uses_with instead.

Source

pub fn instruction(&self, id: InstructionId) -> &Instruction<'str>

Borrows the instruction id, routing through its owning function’s arena.

Source

pub fn instruction_mut(&mut self, id: InstructionId) -> &mut Instruction<'str>

Mutably borrows the instruction id.

Source

pub fn contains_instruction(&self, id: InstructionId) -> bool

Whether id currently names a live instruction payload.

Source

pub fn block(&self, id: BlockId) -> &BasicBlock<'str>

Borrows the basic block id.

Source

pub fn block_mut(&mut self, id: BlockId) -> &mut BasicBlock<'str>

Mutably borrows the basic block id.

Source

pub fn contains_block(&self, id: BlockId) -> bool

Whether id currently names a live block payload.

Source

pub fn block_param(&self, id: BlockParamId) -> &BlockParam<'str>

Borrows the block parameter id.

Source

pub fn block_param_mut(&mut self, id: BlockParamId) -> &mut BlockParam<'str>

Mutably borrows the block parameter id.

Source

pub fn contains_block_param(&self, id: BlockParamId) -> bool

Whether id currently names a live block-parameter payload.

Source

pub fn edge(&self, func: FunctionId, id: EdgeId) -> &EdgeData

Borrows the CFG edge id, stored in function func’s edge arena.

Source

pub fn edge_mut(&mut self, func: FunctionId, id: EdgeId) -> &mut EdgeData

Mutably borrows the CFG edge id, stored in function func’s edge arena.

Source

pub fn users_of(&self, value: ValueId) -> Vec<InstructionId>

Returns the instructions that use value as an operand, read from value’s owning function. For an SSA def (instruction/param) that is the complete user set (all uses are intra-function). For a shared value (literal/bytes/varnode) there is no single owner, so this returns &[].

Source

pub fn has_users(&self, value: ValueId) -> bool

Whether anything uses value, without building the user list to ask.

Source

pub fn push_block( &mut self, func: FunctionId, block: BasicBlock<'str>, ) -> BlockId

Source

pub fn push_block_param( &mut self, func: FunctionId, param: BlockParam<'str>, ) -> BlockParamId

Source

pub fn push_edge(&mut self, func: FunctionId, edge: EdgeData) -> EdgeId

Source

pub fn push_function( &mut self, interface: FunctionInterface<'str>, body: FunctionBody<'str>, ) -> FunctionId

Push a function’s interface and body in lockstep, returning the shared FunctionId. Both registries must always grow together.

Source

pub fn get_register(&self, id: RegisterId) -> VarnodeRef<'str, '_>

Returns an immutable reference to the varnode mapped to the named register id.

Source

pub fn get_const(&self, value: u64, size: usize) -> LiteralRef<'str, '_>

Creates a Value representing an integer constant of the given byte width.

Source

pub fn get_bool_const(&self, value: bool) -> LiteralRef<'str, '_>

Creates a bool-typed constant (true/false), byte-stored with value 1/0. This is the only way to mint a bool literal.

Source

pub fn get_poison(&self, type_id: TypeId) -> ValueId

Mints a fresh typed poison value of the given TypeId. Never deduped: each call yields a distinct poison so GVN keeps them in separate congruence classes (see poison).

Source

pub fn get_typed_const( &self, value: u64, type_id: TypeId, ) -> LiteralRef<'str, '_>

Creates a typed constant literal.

Unlike get_const this accepts an arbitrary TypeId, allowing StackAddress constants (e.g. the stack base) to preserve their type through constant folding.

Source

pub fn get_bytes(&self, data: Vec<u8>) -> BytesRef<'str, '_>

Creates an opaque byte-blob constant from a little-endian, memory-order byte vector.

The blob is typed as an Array(i8, data.len()). Unlike numeric literals, byte blobs are not interned: every call produces a fresh BytesId. Use this for constants wider than a u64 (SSE/AVX pools, wide stack/memory reads, coalesced constant stores).

Source

pub fn get_typed_bytes( &self, data: Vec<u8>, type_id: TypeId, ) -> BytesRef<'str, '_>

Like get_bytes but stamps the blob with an explicit array/sequence TypeId instead of the default Array(i8, len). Mints through the &self append path (no post-hoc type_id write), so a checked-out function pass reading through a BodyView can materialize a typed constant array without mutable access to the shared registry.

Source

pub fn type_of(&self, id: ValueId) -> TypeId

Returns the TypeId of any ValueId in this context.

Varnodes are typed as Int(varnode.size()). Blocks, functions, and other non-data values return Int(0).

Source

pub fn stored_type_of(&self, id: ValueId) -> Option<TypeId>

Returns the stored TypeId for value kinds that carry one directly.

Unlike Context::type_of, this never interns fallback integer types, so it works from immutable formatting and parsing paths. Varnodes, blocks, and functions return None.

Source

pub fn set_varnode_type(&mut self, varnode: VarnodeId, type_id: TypeId)

Gives varnode a global type override, replacing the default Int(size). Used to type ambient register globals — e.g. the FS_OFFSET segment base as PtrTo<TEB> — so every use across all functions reads the richer type. Pass a type whose size matches the varnode’s width.

Source

pub fn users(&self, value: impl Into<ValueId>) -> Vec<InstructionId>

Return all instructions that use value as an operand.

For an SSA value (instruction result or block param) this is the complete user set, read from its owning function. For a shared value (literal/bytes/varnode) it is &[] — those have no owning function and their uses are tracked per using-function; use users_across_functions to find them.

Source

pub fn users_across_functions( &self, value: impl Into<ValueId>, ) -> Vec<InstructionId>

Every instruction across all functions that uses value as an operand. Unlike users this scans every function, so it answers a shared value (literal/bytes/varnode) whose uses span functions. Off the hot path (allocates); prefer users for an SSA value.

Source

pub fn view(&self) -> ModuleView<'_, 'str>

A Copy read view over the whole module (for the mutation refs’ reads).

Source

pub fn shr(&self) -> &Shared<'str>

The module’s shared IR state (Shared) — the module-path twin of ModuleView::shared/BodyMut::shr, so a &mut Context module walker and a checked-out pass spell shared-data reads identically (context-split stage 5b-ii item #1).

Source

pub fn function(&self, f: FunctionId) -> &FunctionBody<'str>

The owning function’s storage (read). Alias of body.

Source

pub fn function_mut(&mut self, f: FunctionId) -> &mut FunctionBody<'str>

The owning function’s storage (write). Alias of body_mut.

Source

pub fn block_ref(&self, id: BlockId) -> BlockRef<'str, '_, ModuleView<'_, 'str>>

A read BlockRef over id, module-routed.

Source

pub fn insn_ref( &self, id: InstructionId, ) -> InstructionRef<'str, '_, ModuleView<'_, 'str>>

A read InstructionRef over id, module-routed.

Source

pub fn param_ref( &self, id: BlockParamId, ) -> BlockParamRef<'str, '_, ModuleView<'_, 'str>>

A read BlockParamRef over id.

Source

pub fn function_ref( &self, id: FunctionId, ) -> FunctionRef<'str, '_, ModuleView<'_, 'str>>

A read FunctionRef over id, module-routed.

Source

pub fn push_mnemonic( &mut self, func: FunctionId, mnemonic: Mnemonic, size: usize, ) -> InstructionId

Mint an Int(size)-typed instruction with mnemonic into func’s arena.

Source

pub fn push_mnemonic_with_type( &mut self, func: FunctionId, mnemonic: Mnemonic, type_id: TypeId, ) -> InstructionId

Mint an instruction with mnemonic and explicit result type_id into func’s arena.

Source

pub fn make_block(&mut self, func: FunctionId) -> BlockId

Mint a fresh empty block into func’s arena, owned (arena membership) and rostered. The module-scope mint of a fresh empty block.

Source

pub fn register_local_name( &mut self, id: ValueId, name: Cow<'str, str>, old_name: Option<&str>, ) -> Result<()>

Register name for id in the table that owns its kind (function-local for block/insn/param/Temp, global otherwise).

Source

pub fn update_name( &mut self, name: Cow<'str, str>, id: ValueId, old_name: Option<&str>, ) -> Result<()>

Changes the name of a value, in the name table that owns its kind (function-local for block/instruction/param/Temp, global otherwise).

Source

pub fn get_named_in_scope(&self, id: ValueId, name: &str) -> Option<ValueId>

Resolve name in the table that owns id’s kind (function-local for block/instruction/param/Temp, global otherwise). Used by the rename path to check for a conflict in the correct namespace, and by passes that mint a unique name for a known SSA value.

Source

pub fn get_named(&self, name: &str) -> Option<ValueId>

Remove name from the name map, keeping the get_unique_name suffix hint exact: if name is a generated base_<n> suffix, lower base’s hint so the freed suffix is reconsidered on the next call (a naive first-free scan would reuse it, and the hint must not skip it). Un-suffixed names are Attempts to get a value ID by its global name (function/varnode/space/ p-code/bytes). Block/instruction/param/Temp names are function-scoped and are resolved through their owning FunctionBody (see NameTable); this returns None for them.

Source

pub fn get_unique_name(&mut self, name: Cow<'str, str>) -> Cow<'str, str>

Gets a unique global name (functions, varnodes, spaces, …), appending a numeric suffix until free. For a block/instruction/param/Temp name, use get_unique_name_in so uniqueness is checked against the owning function’s table.

Source

pub fn get_unique_name_in( &mut self, func: FunctionId, name: Cow<'str, str>, ) -> Cow<'str, str>

Gets a unique name within func’s function-local name table (for block, instruction, block-param, and Temp names). Two functions may thus reuse the same name independently.

Trait Implementations§

Source§

impl<'a, 'str> AsShared<'a, 'str> for &'a Context<'str>

Source§

fn as_shared(self) -> &'a Shared<'str>

Source§

impl<'str> Clone for Context<'str>

Source§

fn clone(&self) -> Context<'str>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'str> Default for Context<'str>

Source§

fn default() -> Context<'str>

Returns the “default value” for a type. Read more
Source§

impl<'de, 'str> Deserialize<'de> for Context<'str>

Source§

fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for Context<'_>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'str, 'ctx> IntoIterator for &'ctx Context<'str>

Source§

type Item = FunctionRef<'str, 'ctx>

The type of the elements being iterated over.
Source§

type IntoIter = FunctionIter<'str, 'ctx>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<'str> QCodeMut<'str> for Context<'str>

Source§

type View<'v> = ModuleView<'v, 'str> where Self: 'v, 'str: 'v

The host’s Copy read provider (ModuleView or BodyView).
Source§

fn function_mut(&mut self, id: FunctionId) -> &mut FunctionBody<'str>

The storage of the function id (write). The checked-out host panics if id is not its own function.
Source§

fn body(&self, id: FunctionId) -> &FunctionBody<'str>

The storage of the function id (read), tied to &self. The borrow-friendly read primitive for host-generic ref code: a fully generic H cannot prove 'str outlives a view GAT borrow, but a plain &self-tied borrow needs no such proof.
Source§

fn shr(&self) -> &Shared<'str>

The module’s shared IR state (read-only through this trait).
Source§

fn interfaces(&self) -> &Registry<FunctionId, FunctionInterface<'str>>

Every function’s published interface (the caller-reasoning surface).
Source§

fn view(&self) -> ModuleView<'_, 'str>

The static immutable provider for reads over this host.
Source§

fn instruction_mut(&mut self, id: InstructionId) -> &mut Instruction<'str>

Mutably borrows the instruction id from its owning function’s arena.
Source§

fn block_mut(&mut self, id: BlockId) -> &mut BasicBlock<'str>

Mutably borrows the block id from its owning function’s arena.
Source§

fn block_param_mut(&mut self, id: BlockParamId) -> &mut BlockParam<'str>

Mutably borrows the block parameter id from its owning function’s arena.
Source§

fn register_body_name( &mut self, id: ValueId, name: Cow<'str, str>, old_name: Option<&str>, ) -> Result<()>

Register name for the function-scoped id (block/instruction/param/ Temp) in its owning function’s local name table. Panics on a global-scoped id — shared-name registration is a module-only operation outside this trait’s body-local contract. Errors only on a duplicate name.
Source§

fn remove_block_param(&mut self, id: BlockParamId)

Physically removes a block parameter and its local bookkeeping. Positional block and edge-argument rewrites belong to the caller and may complete later in the same transformation.
Source§

fn insert_insn_before( &mut self, block: BlockId, before: InstructionId, insn: InstructionId, )

Insert insn immediately before before in block, setting its parent.
Source§

fn move_insn_before(&mut self, insn: InstructionId, before: InstructionId)

Move insn immediately before the arbitrary live instruction before, preserving the moved instruction’s stable ID. Both instructions must belong to the same function; the destination block is inferred from the anchor.
Source§

fn add_cfg_edge(&mut self, from: BlockId, to: BlockId) -> EdgeId

Adds a directed edge in the CFG from from to to, returning its id. Read more
Source§

fn replace_all_uses_with( &mut self, old: impl Into<ValueId>, new: impl Into<ValueId>, )

Replace every use of old with new across old’s owning function and update the reverse use-map (SSA defs only; all uses are intra-function).
Source§

fn remove_instruction(&mut self, id: InstructionId)

Remove instruction id from its block, unlink its outgoing CFG edges if a terminator, clear its name, prune its operand use-lists, and physically drop its payload.
Source§

fn replace_instruction(&mut self, id: InstructionId, new: impl Into<ValueId>)

Replace every use of instruction id with new, then remove id — the standard “rewrite to a cheaper value” epilogue (replace_all_uses_with + remove_instruction).
Source§

fn remove_instructions(&mut self, dead: &FxHashSet<InstructionId>)

Physically removes a set of instructions after pruning their operands from the reverse-use maps, grouped per owning function. Call after removing them from their parent blocks and unlinking any CFG edges owned by terminators.
Source§

fn rehome_outgoing_edges(&mut self, keep: BlockId, remove: BlockId)

Rehome remove’s outgoing CFG edges onto keep. The direct edge and keep’s forwarding terminator have already been removed by the caller.
Source§

fn replace_instruction_mnemonic( &mut self, id: InstructionId, mnemonic: Mnemonic, )

Replace an instruction’s mnemonic in place, keeping the reverse use-map in sync. For transforms that change an instruction without changing its identity, parent block, address, or result type.
Source§

fn unroster_block(&mut self, block: BlockId)

Drop block from its function’s ownership roster. Ownership is derived from the storing arena (block.func); the arena slot is untouched.
Source§

fn delete_block(&mut self, block: BlockId)

Remove block from its function: unlink every incident CFG edge, remove its instructions and params, clear ownership metadata, then drop its payload.
Source§

fn absorb_block(&mut self, keep: BlockId, other: BlockId, edge_ab: EdgeId)

Absorb other into keep: drop keep’s terminal branch, append other’s instructions, rehome its outgoing edges, and remove it. edge_ab is the direct edge keep -> other.
Source§

impl<'str> Serialize for Context<'str>

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl SpaceStore for Context<'_>

Lets Space::from_id resolve against a &Context directly.

Source§

fn spaces(&self) -> &Registry<SpaceId, Space>

The space table this store holds.

Auto Trait Implementations§

§

impl<'str> !Freeze for Context<'str>

§

impl<'str> !UnwindSafe for Context<'str>

§

impl<'str> RefUnwindSafe for Context<'str>

§

impl<'str> Send for Context<'str>

§

impl<'str> Sync for Context<'str>

§

impl<'str> Unpin for Context<'str>

§

impl<'str> UnsafeUnpin for Context<'str>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.