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,
layouter: &'temp mut Layouter,
global_expression_kind_tracker: &'temp mut ExpressionKindTracker,
expr_type: ExpressionContextType<'temp, 'out>,
}Expand description
State for lowering an ast::Expression to Naga IR.
ExpressionContexts come in two kinds, distinguished by
the value of the expr_type field:
-
A
Runtimecontext contributesnaga::Expressions to anaga::Function’s runtime expression arena. -
A
Constantcontext contributesnaga::Expressions to anaga::Module’s constant expression arena.
ExpressionContexts are constructed in restricted ways:
-
To get a
RuntimeExpressionContext, callStatementContext::as_expression. -
To get a
ConstantExpressionContext, callGlobalContext::as_const. -
You can demote a
Runtimecontext to aConstantcontext 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
Handles we have built for them, owned by Lowerer::lower.
module: &'out mut ModuleThe IR Module we’re constructing.
const_typifier: &'temp mut TypifierType judgments for module::global_expressions.
layouter: &'temp mut Layouter§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>, Box<Error<'source>>>
pub fn try_automatic_conversions( &mut self, expr: Handle<Expression>, goal_ty: &TypeResolution, goal_span: Span, ) -> Result<Handle<Expression>, Box<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>, Box<Error<'source>>>
pub fn try_automatic_conversion_for_leaf_scalar( &mut self, expr: Handle<Expression>, goal_scalar: Scalar, goal_span: Span, ) -> Result<Handle<Expression>, Box<Error<'source>>>
Try to convert expr’s leaf scalar to goal_scalar 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>, Box<Error<'source>>>
Sourcepub fn try_automatic_conversions_slice(
&mut self,
exprs: &mut [Handle<Expression>],
goal_ty: &TypeResolution,
goal_span: Span,
) -> Result<(), Box<Error<'source>>>
pub fn try_automatic_conversions_slice( &mut self, exprs: &mut [Handle<Expression>], goal_ty: &TypeResolution, goal_span: Span, ) -> Result<(), Box<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<(), Box<Error<'source>>>
pub fn try_automatic_conversions_for_vector( &mut self, exprs: &mut [Handle<Expression>], goal_scalar: Scalar, goal_span: Span, ) -> Result<(), Box<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<(), Box<Error<'source>>>
pub fn convert_to_leaf_scalar( &mut self, expr: &mut Handle<Expression>, goal: Scalar, ) -> Result<(), Box<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<(), Box<Error<'source>>>
pub fn convert_slice_to_common_leaf_scalar( &mut self, exprs: &mut [Handle<Expression>], goal: Scalar, ) -> Result<(), Box<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>, Box<Error<'source>>>
pub fn concretize( &mut self, expr: Handle<Expression>, ) -> Result<Handle<Expression>, Box<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<'_>
Sourcefn as_diagnostic_display<T>(
&self,
value: T,
) -> DiagnosticDisplay<(T, GlobalCtx<'_>)>
fn as_diagnostic_display<T>( &self, value: T, ) -> DiagnosticDisplay<(T, GlobalCtx<'_>)>
Return a wrapper around value suitable for formatting.
Return a wrapper around value that implements
core::fmt::Display in a form suitable for use in
diagnostic messages.
fn append_expression( &mut self, expr: Expression, span: Span, ) -> Result<Handle<Expression>, Box<Error<'source>>>
fn const_eval_expr_to_u32( &self, handle: Handle<Expression>, ) -> Result<u32, U32EvalError>
Sourcefn is_const(&self, handle: Handle<Expression>) -> bool
fn is_const(&self, handle: Handle<Expression>) -> bool
Return true if handle is a constant expression.
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>>, Box<Error<'source>>>
fn runtime_expression_ctx( &mut self, span: Span, ) -> Result<&mut LocalExpressionContext<'temp, 'out>, Box<Error<'source>>>
fn gather_component( &mut self, expr: Handle<Expression>, component_span: Span, gather_span: Span, ) -> Result<SwizzleComponent, Box<Error<'source>>>
Sourcefn register_type(
&mut self,
handle: Handle<Expression>,
) -> Result<Handle<Type>, Box<Error<'source>>>
fn register_type( &mut self, handle: Handle<Expression>, ) -> Result<Handle<Type>, Box<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, Box<Error<'source>>>
fn grow_types( &mut self, handle: Handle<Expression>, ) -> Result<&mut Self, Box<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), Box<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<(), Box<Error<'source>>>
fn binary_op_splat( &mut self, op: BinaryOperator, left: &mut Handle<Expression>, right: &mut Handle<Expression>, ) -> Result<(), Box<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>, Box<Error<'source>>>
fn interrupt_emitter( &mut self, expression: Expression, span: Span, ) -> Result<Handle<Expression>, Box<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>, Box<Error<'source>>>
fn apply_load_rule( &mut self, expr: Typed<Handle<Expression>>, ) -> Result<Handle<Expression>, Box<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.
fn ensure_type_exists(&mut self, inner: TypeInner) -> Handle<Type>
Trait Implementations§
Source§impl TypeContext for ExpressionContext<'_, '_, '_>
impl TypeContext for ExpressionContext<'_, '_, '_>
Source§fn type_name(&self, handle: Handle<Type>) -> &str
fn type_name(&self, handle: Handle<Type>) -> &str
handle.Source§fn write_override<W: Write>(
&self,
handle: Handle<Override>,
out: &mut W,
) -> Result
fn write_override<W: Write>( &self, handle: Handle<Override>, out: &mut W, ) -> Result
override to out.Source§fn write_unnamed_struct<W: Write>(&self, _: &TypeInner, _: &mut W) -> Result
fn write_unnamed_struct<W: Write>(&self, _: &TypeInner, _: &mut W) -> Result
TypeInner::Struct for which we are unable to find a name. Read moreSource§fn write_type<W: Write>(&self, handle: Handle<Type>, out: &mut W) -> Result
fn write_type<W: Write>(&self, handle: Handle<Type>, out: &mut W) -> Result
ty as it would appear in a value’s declaration. Read moreSource§fn write_scalar<W: Write>(&self, scalar: Scalar, out: &mut W) -> Result
fn write_scalar<W: Write>(&self, scalar: Scalar, out: &mut W) -> Result
Scalar scalar as a WGSL type.Source§fn write_type_resolution<W: Write>(
&self,
resolution: &TypeResolution,
out: &mut W,
) -> Result
fn write_type_resolution<W: Write>( &self, resolution: &TypeResolution, out: &mut W, ) -> Result
TypeResolution resolution as a WGSL type.