Skip to main content

LoweringBuilder

Struct LoweringBuilder 

Source
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

Source

pub fn new() -> Self

Construct an empty builder. Both id counters start at 0 and all three maps are empty.

Source

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.

Source

pub fn alloc_block(&mut self) -> LoweredBlockId

Allocate a fresh LoweredBlockId and return it. Increments the block-id counter. Independent of Self::alloc_value.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn stack_slot_map(&self) -> &HashMap<StackSlot, LoweredValueId>

Read-only view of the stack_slot_map.

Source

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§

Source§

impl Default for LoweringBuilder

Source§

fn default() -> Self

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

Auto Trait Implementations§

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> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts 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>

Converts 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)

Converts &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)

Converts &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
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Send + Sync>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more