pub struct ExpressionContext<'source, 'temp, 'out> {
ast_expressions: &'temp Arena<Expression<'source>>,
types: &'temp Arena<Type<'source>>,
globals: &'temp mut FastHashMap<&'source str, LoweredGlobalDecl>,
module: &'out mut Module,
const_typifier: &'temp mut Typifier,
global_expression_kind_tracker: &'temp mut ExpressionKindTracker,
expr_type: ExpressionContextType<'temp, 'out>,
}
Expand description
State for lowering an ast::Expression
to Naga IR.
ExpressionContext
s come in two kinds, distinguished by
the value of the expr_type
field:
-
A
Runtime
context contributesnaga::Expression
s to anaga::Function
’s runtime expression arena. -
A
Constant
context contributesnaga::Expression
s to anaga::Module
’s constant expression arena.
ExpressionContext
s are constructed in restricted ways:
-
To get a
Runtime
ExpressionContext
, callStatementContext::as_expression
. -
To get a
Constant
ExpressionContext
, callGlobalContext::as_const
. -
You can demote a
Runtime
context to aConstant
context by callingas_const
, but there’s no way to go in the other direction, producing a runtime context from a constant one. This is because runtime expressions can refer to constant expressions, viaExpression::Constant
, but constant expressions can’t refer to a function’s expressions.
Not to be confused with wgsl::parse::ExpressionContext
, which is
for parsing the ast::Expression
in the first place.
Fields§
§ast_expressions: &'temp Arena<Expression<'source>>
§types: &'temp Arena<Type<'source>>
§globals: &'temp mut FastHashMap<&'source str, LoweredGlobalDecl>
The map from the names of module-scope declarations to the Naga IR
Handle
s we have built for them, owned by Lowerer::lower
.
module: &'out mut Module
The IR Module
we’re constructing.
const_typifier: &'temp mut Typifier
Type judgments for module::global_expressions
.
global_expression_kind_tracker: &'temp mut ExpressionKindTracker
§expr_type: ExpressionContextType<'temp, 'out>
Whether we are lowering a constant expression or a general runtime expression, and the data needed in each case.
Implementations§
source§impl<'source> ExpressionContext<'source, '_, '_>
impl<'source> ExpressionContext<'source, '_, '_>
sourcepub fn try_automatic_conversions(
&mut self,
expr: Handle<Expression>,
goal_ty: &TypeResolution,
goal_span: Span,
) -> Result<Handle<Expression>, Error<'source>>
pub fn try_automatic_conversions( &mut self, expr: Handle<Expression>, goal_ty: &TypeResolution, goal_span: Span, ) -> Result<Handle<Expression>, Error<'source>>
Try to use WGSL’s automatic conversions to convert expr
to goal_ty
.
If no conversions are necessary, return expr
unchanged.
If automatic conversions cannot convert expr
to goal_ty
, return an
AutoConversion
error.
Although the Load Rule is one of the automatic conversions, this
function assumes it has already been applied if appropriate, as
indicated by the fact that the Rust type of expr
is not Typed<_>
.
sourcepub fn try_automatic_conversion_for_leaf_scalar(
&mut self,
expr: Handle<Expression>,
goal_scalar: Scalar,
goal_span: Span,
) -> Result<Handle<Expression>, Error<'source>>
pub fn try_automatic_conversion_for_leaf_scalar( &mut self, expr: Handle<Expression>, goal_scalar: Scalar, goal_span: Span, ) -> Result<Handle<Expression>, Error<'source>>
Try to convert expr
’s leaf scalar to goal
using automatic conversions.
If no conversions are necessary, return expr
unchanged.
If automatic conversions cannot convert expr
to goal_scalar
, return
an AutoConversionLeafScalar
error.
Although the Load Rule is one of the automatic conversions, this
function assumes it has already been applied if appropriate, as
indicated by the fact that the Rust type of expr
is not Typed<_>
.
fn convert_leaf_scalar( &mut self, expr: Handle<Expression>, expr_span: Span, goal_scalar: Scalar, ) -> Result<Handle<Expression>, Error<'source>>
sourcepub fn try_automatic_conversions_slice(
&mut self,
exprs: &mut [Handle<Expression>],
goal_ty: &TypeResolution,
goal_span: Span,
) -> Result<(), Error<'source>>
pub fn try_automatic_conversions_slice( &mut self, exprs: &mut [Handle<Expression>], goal_ty: &TypeResolution, goal_span: Span, ) -> Result<(), Error<'source>>
Try to convert exprs
to goal_ty
using WGSL’s automatic conversions.
sourcepub fn try_automatic_conversions_for_vector(
&mut self,
exprs: &mut [Handle<Expression>],
goal_scalar: Scalar,
goal_span: Span,
) -> Result<(), Error<'source>>
pub fn try_automatic_conversions_for_vector( &mut self, exprs: &mut [Handle<Expression>], goal_scalar: Scalar, goal_span: Span, ) -> Result<(), Error<'source>>
Apply WGSL’s automatic conversions to a vector constructor’s arguments.
When calling a vector constructor like vec3<f32>(...)
, the parameters
can be a mix of scalars and vectors, with the latter being spread out to
contribute each of their components as a component of the new value.
When the element type is explicit, as with <f32>
in the example above,
WGSL’s automatic conversions should convert abstract scalar and vector
parameters to the constructor’s required scalar type.
sourcepub fn convert_to_leaf_scalar(
&mut self,
expr: &mut Handle<Expression>,
goal: Scalar,
) -> Result<(), Error<'source>>
pub fn convert_to_leaf_scalar( &mut self, expr: &mut Handle<Expression>, goal: Scalar, ) -> Result<(), Error<'source>>
Convert expr
to the leaf scalar type scalar
.
sourcepub fn convert_slice_to_common_leaf_scalar(
&mut self,
exprs: &mut [Handle<Expression>],
goal: Scalar,
) -> Result<(), Error<'source>>
pub fn convert_slice_to_common_leaf_scalar( &mut self, exprs: &mut [Handle<Expression>], goal: Scalar, ) -> Result<(), Error<'source>>
Convert all expressions in exprs
to a common scalar type.
Note that the caller is responsible for making sure these
conversions are actually justified. This function simply
generates As
expressions, regardless of whether they are
permitted WGSL automatic conversions. Callers intending to
implement automatic conversions need to determine for
themselves whether the casts we we generate are justified,
perhaps by calling TypeInner::automatically_converts_to
or
Scalar::automatic_conversion_combine
.
sourcepub fn concretize(
&mut self,
expr: Handle<Expression>,
) -> Result<Handle<Expression>, Error<'source>>
pub fn concretize( &mut self, expr: Handle<Expression>, ) -> Result<Handle<Expression>, Error<'source>>
Return an expression for the concretized value of expr
.
If expr
is already concrete, return it unchanged.
sourcepub fn automatic_conversion_consensus<'handle, I>(
&self,
components: I,
) -> Result<Scalar, usize>
pub fn automatic_conversion_consensus<'handle, I>( &self, components: I, ) -> Result<Scalar, usize>
Find the consensus scalar of components
under WGSL’s automatic
conversions.
If components
can all be converted to any common scalar via
WGSL’s automatic conversions, return the best such scalar.
The components
slice must not be empty. All elements’ types must
have been resolved.
If components
are definitely not acceptable as arguments to such
constructors, return Err(i)
, where i
is the index in
components
of some problematic argument.
This function doesn’t fully type-check the arguments - it only
considers their leaf scalar types. This means it may return Ok
even when the Naga validator will reject the resulting
construction expression later.
source§impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out>
impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out>
fn as_const(&mut self) -> ExpressionContext<'source, '_, '_>
fn as_global(&mut self) -> GlobalContext<'source, '_, '_>
fn as_const_evaluator(&mut self) -> ConstantEvaluator<'_>
fn append_expression( &mut self, expr: Expression, span: Span, ) -> Result<Handle<Expression>, Error<'source>>
fn const_access(&self, handle: Handle<Expression>) -> Option<u32>
fn get_expression_span(&self, handle: Handle<Expression>) -> Span
fn typifier(&self) -> &Typifier
fn local( &mut self, local: &Handle<Local>, span: Span, ) -> Result<Typed<Handle<Expression>>, Error<'source>>
fn runtime_expression_ctx( &mut self, span: Span, ) -> Result<&mut LocalExpressionContext<'temp, 'out>, Error<'source>>
fn gather_component( &mut self, expr: Handle<Expression>, component_span: Span, gather_span: Span, ) -> Result<SwizzleComponent, Error<'source>>
sourcefn register_type(
&mut self,
handle: Handle<Expression>,
) -> Result<Handle<Type>, Error<'source>>
fn register_type( &mut self, handle: Handle<Expression>, ) -> Result<Handle<Type>, Error<'source>>
Determine the type of handle
, and add it to the module’s arena.
If you just need a TypeInner
for handle
’s type, use the
resolve_inner!
macro instead. This function
should only be used when the type of handle
needs to appear
in the module’s final Arena<Type>
, for example, if you’re
creating a LocalVariable
whose type is inferred from its
initializer.
sourcefn grow_types(
&mut self,
handle: Handle<Expression>,
) -> Result<&mut Self, Error<'source>>
fn grow_types( &mut self, handle: Handle<Expression>, ) -> Result<&mut Self, Error<'source>>
Resolve the types of all expressions up through handle
.
Ensure that self.typifier
has a TypeResolution
for
every expression in [self.function.expressions
].
This does not add types to any arena. The Typifier
documentation explains the steps we take to avoid filling
arenas with intermediate types.
This function takes &mut self
, so it can’t conveniently
return a shared reference to the resulting TypeResolution
:
the shared reference would extend the mutable borrow, and you
wouldn’t be able to use self
for anything else. Instead, you
should use register_type
or one of resolve!
,
resolve_inner!
or resolve_inner_binary!
.
fn image_data( &mut self, image: Handle<Expression>, span: Span, ) -> Result<(ImageClass, bool), Error<'source>>
fn prepare_args<'b>( &mut self, args: &'b [Handle<Expression<'source>>], min_args: u32, span: Span, ) -> ArgumentContext<'b, 'source>
sourcefn binary_op_splat(
&mut self,
op: BinaryOperator,
left: &mut Handle<Expression>,
right: &mut Handle<Expression>,
) -> Result<(), Error<'source>>
fn binary_op_splat( &mut self, op: BinaryOperator, left: &mut Handle<Expression>, right: &mut Handle<Expression>, ) -> Result<(), Error<'source>>
Insert splats, if needed by the non-‘*’ operations.
See the “Binary arithmetic expressions with mixed scalar and vector operands” table in the WebGPU Shading Language specification for relevant operators.
Multiply is not handled here as backends are expected to handle vec*scalar operations, so inserting splats into the IR increases size needlessly.
sourcefn interrupt_emitter(
&mut self,
expression: Expression,
span: Span,
) -> Result<Handle<Expression>, Error<'source>>
fn interrupt_emitter( &mut self, expression: Expression, span: Span, ) -> Result<Handle<Expression>, Error<'source>>
Add a single expression to the expression table that is not covered by self.emitter
.
This is useful for CallResult
and AtomicResult
expressions, which should not be covered by
Emit
statements.
sourcefn apply_load_rule(
&mut self,
expr: Typed<Handle<Expression>>,
) -> Result<Handle<Expression>, Error<'source>>
fn apply_load_rule( &mut self, expr: Typed<Handle<Expression>>, ) -> Result<Handle<Expression>, Error<'source>>
Apply the WGSL Load Rule to expr
.
If expr
is has type ref<SC, T, A>
, perform a load to produce a value of type
T
. Otherwise, return expr
unchanged.