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