naga::front::spv

Struct BlockContext

source
struct BlockContext<'function> {
    phis: Vec<PhiExpression>,
    blocks: FastHashMap<Word, Block>,
    body_for_label: FastHashMap<Word, usize>,
    mergers: FastHashMap<Word, MergeBlockInformation>,
    bodies: Vec<Body>,
    module: &'function mut Module,
    function_id: Word,
    expressions: &'function mut Arena<Expression>,
    local_arena: &'function mut Arena<LocalVariable>,
    arguments: &'function [FunctionArgument],
    parameter_sampling: &'function mut [SamplingFlags],
}
Expand description

Fragments of Naga IR, to be assembled into Statements once data flow is resolved.

We can’t build a Naga Statement tree directly from SPIR-V blocks for three main reasons:

  • We parse a function’s SPIR-V blocks in the order they appear in the file. Within a function, SPIR-V requires that a block must precede any blocks it structurally dominates, but doesn’t say much else about the order in which they must appear. So while we know we’ll see control flow header blocks before their child constructs and merge blocks, those children and the merge blocks may appear in any order - perhaps even intermingled with children of other constructs.

  • A SPIR-V expression can be used in any SPIR-V block dominated by its definition, whereas Naga expressions are scoped to the rest of their subtree. This means that discovering an expression use later in the function retroactively requires us to have spilled that expression into a local variable back before we left its scope. (The docs for Frontend::get_expr_handle explain this in more detail.)

  • We translate SPIR-V OpPhi expressions as Naga local variables in which we store the appropriate value before jumping to the OpPhi’s block.

All these cases require us to go back and amend previously generated Naga IR based on things we discover later. But modifying old blocks in arbitrary spots in a Statement tree is awkward.

Instead, as we iterate through the function’s body, we accumulate control-flow-free fragments of Naga IR in the blocks table, while building a skeleton of the Naga Statement tree in bodies. We note any spills and temporaries we must introduce in phis.

Finally, once we’ve processed the entire function, we add temporaries and spills to the fragmentary Blocks as directed by phis, and assemble them into the final Naga Statement tree as directed by bodies.

Fields§

§phis: Vec<PhiExpression>

Phi nodes encountered when parsing the function, used to generate spills to local variables.

§blocks: FastHashMap<Word, Block>

Fragments of control-flow-free Naga IR.

These will be stitched together into a proper Statement tree according to bodies, once parsing is complete.

§body_for_label: FastHashMap<Word, usize>

Map from each SPIR-V block’s label id to the index of the Body in bodies the block should append its contents to.

Since each statement in a Naga Block dominates the next, we are sure to encounter their SPIR-V blocks in order. Thus, by having this table map a SPIR-V structured control flow construct’s merge block to the same body index as its header block, when we encounter the merge block, we will simply pick up building the Body where the header left off.

A function’s first block is special: it is the only block we encounter without having seen its label mentioned in advance. (It’s simply the first OpLabel after the OpFunction.) We thus assume that any block missing an entry here must be the first block, which always has body index zero.

§mergers: FastHashMap<Word, MergeBlockInformation>

SPIR-V metadata about merge/continue blocks.

§bodies: Vec<Body>

A table of Body values, each representing a block in the final IR.

The first element is always the function’s top-level block.

§module: &'function mut Module

The module we’re building.

§function_id: Word

Id of the function currently being processed

§expressions: &'function mut Arena<Expression>

Expression arena of the function currently being processed

§local_arena: &'function mut Arena<LocalVariable>

Local variables arena of the function currently being processed

§arguments: &'function [FunctionArgument]

Arguments of the function currently being processed

§parameter_sampling: &'function mut [SamplingFlags]

Metadata about the usage of function parameters as sampling objects

Implementations§

source§

impl BlockContext<'_>

source

pub(super) fn gctx(&self) -> GlobalCtx<'_>

source

fn lower(self) -> Block

Consumes the BlockContext producing a Ir Block

source§

impl BlockContext<'_>

Trait Implementations§

source§

impl<'function> Debug for BlockContext<'function>

source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'function> Freeze for BlockContext<'function>

§

impl<'function> RefUnwindSafe for BlockContext<'function>

§

impl<'function> Send for BlockContext<'function>

§

impl<'function> Sync for BlockContext<'function>

§

impl<'function> Unpin for BlockContext<'function>

§

impl<'function> !UnwindSafe for BlockContext<'function>

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> 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, 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.