pub struct LoweringBuilder { /* private fields */ }Expand description
Scratchpad shared across per-instruction lower_* calls when walking a
Cranelift cl::Function.
Owns three bidirectional Cranelift → lowered-id maps (values, blocks,
stack slots) plus a monotonic id allocator for each of the two id
namespaces (LoweredValueId and LoweredBlockId).
The wave-2 lowering driver constructs a LoweringBuilder, pre-allocates
ids for entry-block params and constants via Self::get_or_alloc_value
/ Self::bind_value, then calls each per-family lower_* function in
turn (crate::lower_arith::lower_arith_inst et al.) by passing the
builder’s internals through Self::value_map_mut and
Self::next_value_id_mut. The result is an ordered list of
crate::lowered_ir::LoweredOps with consistent SSA numbering.
See the module docs for the namespace rules.
Implementations§
Source§impl LoweringBuilder
impl LoweringBuilder
Sourcepub fn new() -> Self
pub fn new() -> Self
Construct an empty builder. Both id counters start at 0 and all
three maps are empty.
Sourcepub fn alloc_value(&mut self) -> LoweredValueId
pub fn alloc_value(&mut self) -> LoweredValueId
Allocate a fresh LoweredValueId and return it. Increments the
value-id counter. Does not bind the id to any Cranelift Value;
callers wanting a Value → id binding should use
Self::get_or_alloc_value or Self::bind_value instead.
Sourcepub fn alloc_block(&mut self) -> LoweredBlockId
pub fn alloc_block(&mut self) -> LoweredBlockId
Allocate a fresh LoweredBlockId and return it. Increments the
block-id counter. Independent of Self::alloc_value.
Sourcepub fn get_or_alloc_value(&mut self, v: Value) -> LoweredValueId
pub fn get_or_alloc_value(&mut self, v: Value) -> LoweredValueId
Get the LoweredValueId for a Cranelift cl::Value, allocating
one if it’s the first time we’ve seen it.
This is the workhorse for entry-block param setup: the driver
iterates over dfg.block_params(entry) and calls this for each
param to seed the value-map before walking the body. It’s also safe
to call repeatedly for the same value — subsequent calls return the
existing id without advancing the counter.
Sourcepub fn get_or_alloc_block(&mut self, b: Block) -> LoweredBlockId
pub fn get_or_alloc_block(&mut self, b: Block) -> LoweredBlockId
Get the LoweredBlockId for a Cranelift cl::Block, allocating
one if it’s the first time we’ve seen it.
Used by crate::lower_cf when it encounters a branch target: the
target block may not yet have been walked, but its lowered id needs
to be embedded in the Br/CondBr/Switch op now.
Sourcepub fn get_or_alloc_stack_slot(&mut self, ss: StackSlot) -> LoweredValueId
pub fn get_or_alloc_stack_slot(&mut self, ss: StackSlot) -> LoweredValueId
Get the alloca-pointer LoweredValueId for a Cranelift
cl::StackSlot, allocating one (from the value-id counter) if
it’s the first time we’ve seen it.
crate::lower_memory uses this for stack_load / stack_store:
every reference to the same StackSlot resolves to the same alloca
pointer SSA value, so the downstream mem2reg pass can rewrite all
uses uniformly.
Sourcepub fn lookup_value(&self, v: Value) -> Option<LoweredValueId>
pub fn lookup_value(&self, v: Value) -> Option<LoweredValueId>
Look up an existing LoweredValueId for a Cranelift cl::Value.
Returns None if no binding exists yet.
Use this when you want to probe the map without side effects (e.g.
assertions, debugging, or when a missing operand should fail rather
than allocate). For the eager-allocate flavour use
Self::get_or_alloc_value.
Sourcepub fn lookup_block(&self, b: Block) -> Option<LoweredBlockId>
pub fn lookup_block(&self, b: Block) -> Option<LoweredBlockId>
Look up an existing LoweredBlockId for a Cranelift cl::Block.
Returns None if no binding exists yet.
Sourcepub fn lookup_stack_slot(&self, ss: StackSlot) -> Option<LoweredValueId>
pub fn lookup_stack_slot(&self, ss: StackSlot) -> Option<LoweredValueId>
Look up an existing stack-slot alloca-pointer id for a Cranelift
cl::StackSlot. Returns None if no binding exists yet.
Sourcepub fn bind_value(
&mut self,
v: Value,
id: LoweredValueId,
) -> Option<LoweredValueId>
pub fn bind_value( &mut self, v: Value, id: LoweredValueId, ) -> Option<LoweredValueId>
Bind a Cranelift cl::Value to a specific (already-allocated)
LoweredValueId.
Does not advance the value-id counter — this is purely a name
assignment. Returns the previous binding for v, if any (mirroring
HashMap::insert).
Used by per-family lower_* functions that prefer the wave-1
idiom of allocating the result id via *next_id and inserting it
directly: those callers reach for Self::next_value_id_mut /
Self::value_map_mut today, but bind_value is the cleaner
option when the caller already has the id in hand.
Sourcepub fn bind_stack_slot(
&mut self,
ss: StackSlot,
id: LoweredValueId,
) -> Option<LoweredValueId>
pub fn bind_stack_slot( &mut self, ss: StackSlot, id: LoweredValueId, ) -> Option<LoweredValueId>
Bind a Cranelift cl::StackSlot to a specific (already-allocated)
alloca-pointer LoweredValueId, returning the previous binding if
any (mirroring HashMap::insert).
jit HIGH fix (finding 3): the W2.4 driver lifts the builder’s
stack-slot map out into a local &mut HashMap so it can hand a
&mut to the memory-lowering context. Without a way to write
entries back, every new stack slot allocated during memory lowering
was DROPPED on return — so a later stack_load/stack_store of the
same slot would call Self::get_or_alloc_stack_slot, miss, and
allocate a fresh alloca pointer, splitting one logical slot into
several distinct allocas (a miscompile). The driver now reinserts
each entry of the local map through this method after lowering, so
repeated references to one slot resolve to the same alloca id.
Unlike Self::get_or_alloc_stack_slot, this does not advance
the value-id counter — the id was already allocated by the memory
lowering against the same shared counter.
Sourcepub fn value_map_mut(&mut self) -> &mut HashMap<Value, LoweredValueId>
pub fn value_map_mut(&mut self) -> &mut HashMap<Value, LoweredValueId>
Mutable access to the inner value_map.
Provided for compatibility with the wave-1 per-family lowerings
(e.g. crate::lower_arith::lower_arith_inst) that already accept
&mut HashMap<cl::Value, LoweredValueId> directly. The borrow is
tied to &mut self, so the builder cannot be otherwise mutated for
the duration.
Sourcepub fn next_value_id_mut(&mut self) -> &mut LoweredValueId
pub fn next_value_id_mut(&mut self) -> &mut LoweredValueId
Mutable access to the inner next_value_id counter.
Companion to Self::value_map_mut: per-family lowerings receive
both and update them in lockstep. Direct mutation here is
equivalent to calling Self::alloc_value manually.
Sourcepub fn value_map(&self) -> &HashMap<Value, LoweredValueId>
pub fn value_map(&self) -> &HashMap<Value, LoweredValueId>
Read-only view of the value_map. Handy for tests, fingerprinting,
and the wave-2 driver’s post-walk verification.
Sourcepub fn block_map(&self) -> &HashMap<Block, LoweredBlockId>
pub fn block_map(&self) -> &HashMap<Block, LoweredBlockId>
Read-only view of the block_map. Used by crate::lower_cf when
it only needs to look up branch targets that the driver has
already seeded.
Sourcepub fn stack_slot_map(&self) -> &HashMap<StackSlot, LoweredValueId>
pub fn stack_slot_map(&self) -> &HashMap<StackSlot, LoweredValueId>
Read-only view of the stack_slot_map.
Sourcepub fn split_borrow_for_memory(
&mut self,
) -> (&HashMap<Value, LoweredValueId>, &mut HashMap<StackSlot, LoweredValueId>, &mut LoweredValueId)
pub fn split_borrow_for_memory( &mut self, ) -> (&HashMap<Value, LoweredValueId>, &mut HashMap<StackSlot, LoweredValueId>, &mut LoweredValueId)
Split-borrow accessor for the memory-lowering family.
Returns (&value_map, &mut stack_slot_map, &mut next_value_id) in a
single call so the caller gets disjoint borrows of three distinct
fields — exactly the shape MemLowerContext needs (value map read,
stack-slot map + counter mutated).
jit MED fix (finding 6): the W2.4 driver previously CLONED the whole
value_map on every memory instruction (builder.value_map().clone())
because the borrow checker couldn’t see the three accessors were
disjoint — making the driver O(V·M) (values × memory instructions).
This method performs the field split once, in safe code, so the
memory context borrows the live map directly with no per-instruction
allocation.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for LoweringBuilder
impl RefUnwindSafe for LoweringBuilder
impl Send for LoweringBuilder
impl Sync for LoweringBuilder
impl Unpin for LoweringBuilder
impl UnsafeUnpin for LoweringBuilder
impl UnwindSafe for LoweringBuilder
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more