Skip to content

Commit 5b04dce

Browse files
committed
handle bitcast and construction expressions in the lowerer
1 parent 393213b commit 5b04dce

File tree

12 files changed

+965
-800
lines changed

12 files changed

+965
-800
lines changed

naga/src/front/wgsl/error.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ pub(crate) enum Error<'a> {
199199
InvalidIdentifierUnderscore(Span),
200200
ReservedIdentifierPrefix(Span),
201201
UnknownAddressSpace(Span),
202+
UnknownRayFlag(Span),
202203
RepeatedAttribute(Span),
203204
UnknownAttribute(Span),
204205
UnknownBuiltin(Span),
@@ -275,6 +276,7 @@ pub(crate) enum Error<'a> {
275276
span: Span,
276277
},
277278
CalledEntryPoint(Span),
279+
CalledLocalDecl(Span),
278280
WrongArgumentCount {
279281
span: Span,
280282
expected: Range<u32>,
@@ -415,6 +417,12 @@ pub(crate) enum Error<'a> {
415417
UnexpectedIdentForEnumerant(Span),
416418
UnexpectedExprForEnumerant(Span),
417419
UnusedArgsForTemplate(Vec<Span>),
420+
UnexpectedTemplate(Span),
421+
MissingTemplateArg {
422+
span: Span,
423+
arg: &'static str,
424+
},
425+
UnexpectedExprForTypeExpression(Span),
418426
}
419427

420428
impl From<ConflictingDiagnosticRuleError> for Error<'_> {
@@ -655,6 +663,11 @@ impl<'a> Error<'a> {
655663
labels: vec![(bad_span, "unknown address space".into())],
656664
notes: vec![],
657665
},
666+
Error::UnknownRayFlag(bad_span) => ParseError {
667+
message: format!("unknown ray flag: `{}`", &source[bad_span]),
668+
labels: vec![(bad_span, "unknown ray flag".into())],
669+
notes: vec![],
670+
},
658671
Error::RepeatedAttribute(bad_span) => ParseError {
659672
message: format!("repeated attribute: `{}`", &source[bad_span]),
660673
labels: vec![(bad_span, "repeated attribute".into())],
@@ -914,6 +927,11 @@ impl<'a> Error<'a> {
914927
labels: vec![(span, "entry point cannot be called".into())],
915928
notes: vec![],
916929
},
930+
Error::CalledLocalDecl(span) => ParseError {
931+
message: "local declaration cannot be called".to_string(),
932+
labels: vec![(span, "local declaration cannot be called".into())],
933+
notes: vec![],
934+
},
917935
Error::WrongArgumentCount {
918936
span,
919937
ref expected,
@@ -1402,6 +1420,27 @@ impl<'a> Error<'a> {
14021420
labels: expr_spans.iter().cloned().map(|span| -> (_, _){ (span, "unused".into()) }).collect(),
14031421
notes: vec![],
14041422
},
1423+
Error::UnexpectedTemplate(span) => ParseError {
1424+
message: "unexpected template".to_string(),
1425+
labels: vec![(span, "expected identifier".into())],
1426+
notes: vec![],
1427+
},
1428+
Error::MissingTemplateArg {
1429+
span,
1430+
arg,
1431+
} => ParseError {
1432+
message: format!(
1433+
"`{}` needs a template argument specified: {arg}",
1434+
&source[span]
1435+
),
1436+
labels: vec![(span, "is missing a template argument".into())],
1437+
notes: vec![],
1438+
},
1439+
Error::UnexpectedExprForTypeExpression(expr_span) => ParseError {
1440+
message: "unexpected expression".to_string(),
1441+
labels: vec![(expr_span, "needs to be an identifier resolving to a type declaration (alias or struct) or predeclared type(-generator)".into())],
1442+
notes: vec![],
1443+
}
14051444
}
14061445
}
14071446
}

naga/src/front/wgsl/lower/construction.rs

Lines changed: 26 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
use alloc::{
2-
boxed::Box,
3-
format,
4-
string::{String, ToString},
5-
vec,
6-
vec::Vec,
7-
};
1+
use alloc::{boxed::Box, vec, vec::Vec};
82
use core::num::NonZeroU32;
93

104
use crate::common::wgsl::TypeContext;
@@ -13,9 +7,22 @@ use crate::front::wgsl::parse::ast;
137
use crate::front::wgsl::{Error, Result};
148
use crate::{Handle, Span};
159

16-
/// A cooked form of `ast::ConstructorType` that uses Naga types whenever
17-
/// possible.
18-
enum Constructor<T> {
10+
/// A [`constructor built-in function`].
11+
///
12+
/// WGSL has two types of such functions:
13+
///
14+
/// - Those that fully specify the type being constructed, like
15+
/// `vec3<f32>(x,y,z)`, which obviously constructs a `vec3<f32>`.
16+
///
17+
/// - Those that leave the component type of the composite being constructed
18+
/// implicit, to be inferred from the argument types, like `vec3(x,y,z)`,
19+
/// which constructs a `vec3<T>` where `T` is the type of `x`, `y`, and `z`.
20+
///
21+
/// This enum represents both cases. The `PartialFoo` variants
22+
/// represent the second case, where the component type is implicit.
23+
///
24+
/// [`constructor built-in function`]: https://gpuweb.github.io/gpuweb/wgsl/#constructor-builtin-function
25+
pub enum Constructor<T> {
1926
/// A vector construction whose component type is inferred from the
2027
/// argument: `vec3(1.0)`.
2128
PartialVector { size: crate::VectorSize },
@@ -62,21 +69,6 @@ impl Constructor<Handle<crate::Type>> {
6269
}
6370
}
6471

65-
impl Constructor<(Handle<crate::Type>, &crate::TypeInner)> {
66-
fn to_error_string(&self, ctx: &ExpressionContext) -> String {
67-
match *self {
68-
Self::PartialVector { size } => {
69-
format!("vec{}<?>", size as u32,)
70-
}
71-
Self::PartialMatrix { columns, rows } => {
72-
format!("mat{}x{}<?>", columns as u32, rows as u32,)
73-
}
74-
Self::PartialArray => "array<?, ?>".to_string(),
75-
Self::Type((handle, _inner)) => ctx.type_to_string(handle),
76-
}
77-
}
78-
}
79-
8072
enum Components<'a> {
8173
None,
8274
One {
@@ -117,15 +109,13 @@ impl<'source> Lowerer<'source, '_> {
117109
pub fn construct(
118110
&mut self,
119111
span: Span,
120-
constructor: &ast::ConstructorType<'source>,
112+
constructor: Constructor<Handle<crate::Type>>,
121113
ty_span: Span,
122114
components: &[Handle<ast::Expression<'source>>],
123115
ctx: &mut ExpressionContext<'source, '_, '_>,
124116
) -> Result<'source, Handle<crate::Expression>> {
125117
use crate::proc::TypeResolution as Tr;
126118

127-
let constructor_h = self.constructor(constructor, ctx)?;
128-
129119
let components = match *components {
130120
[] => Components::None,
131121
[component] => {
@@ -160,7 +150,7 @@ impl<'source> Lowerer<'source, '_> {
160150
// Even though we computed `constructor` above, wait until now to borrow
161151
// a reference to the `TypeInner`, so that the component-handling code
162152
// above can have mutable access to the type arena.
163-
let constructor = constructor_h.borrow_inner(ctx.module);
153+
let constructor = constructor.borrow_inner(ctx.module);
164154

165155
let expr;
166156
match (components, constructor) {
@@ -554,14 +544,19 @@ impl<'source> Lowerer<'source, '_> {
554544
Components::One {
555545
span, component, ..
556546
},
557-
constructor,
547+
Constructor::Type((
548+
ty,
549+
&(crate::TypeInner::Scalar { .. }
550+
| crate::TypeInner::Vector { .. }
551+
| crate::TypeInner::Matrix { .. }),
552+
)),
558553
) => {
559554
let component_ty = &ctx.typifier()[component];
560555
let from_type = ctx.type_resolution_to_string(component_ty);
561556
return Err(Box::new(Error::BadTypeCast {
562557
span,
563558
from_type,
564-
to_type: constructor.to_error_string(ctx),
559+
to_type: ctx.type_to_string(ty),
565560
}));
566561
}
567562

@@ -581,77 +576,4 @@ impl<'source> Lowerer<'source, '_> {
581576
let expr = ctx.append_expression(expr, span)?;
582577
Ok(expr)
583578
}
584-
585-
/// Build a [`Constructor`] for a WGSL construction expression.
586-
///
587-
/// If `constructor` conveys enough information to determine which Naga [`Type`]
588-
/// we're actually building (i.e., it's not a partial constructor), then
589-
/// ensure the `Type` exists in [`ctx.module`], and return
590-
/// [`Constructor::Type`].
591-
///
592-
/// Otherwise, return the [`Constructor`] partial variant corresponding to
593-
/// `constructor`.
594-
///
595-
/// [`Type`]: crate::Type
596-
/// [`ctx.module`]: ExpressionContext::module
597-
fn constructor<'out>(
598-
&mut self,
599-
constructor: &ast::ConstructorType<'source>,
600-
ctx: &mut ExpressionContext<'source, '_, 'out>,
601-
) -> Result<'source, Constructor<Handle<crate::Type>>> {
602-
let handle = match *constructor {
603-
ast::ConstructorType::Scalar(scalar) => {
604-
let ty = ctx.ensure_type_exists(scalar.to_inner_scalar());
605-
Constructor::Type(ty)
606-
}
607-
ast::ConstructorType::PartialVector { size } => Constructor::PartialVector { size },
608-
ast::ConstructorType::Vector { size, ty, ty_span } => {
609-
let ty = self.resolve_ast_type(ty, &mut ctx.as_const())?;
610-
let scalar = match ctx.module.types[ty].inner {
611-
crate::TypeInner::Scalar(sc) => sc,
612-
_ => return Err(Box::new(Error::UnknownScalarType(ty_span))),
613-
};
614-
let ty = ctx.ensure_type_exists(crate::TypeInner::Vector { size, scalar });
615-
Constructor::Type(ty)
616-
}
617-
ast::ConstructorType::PartialMatrix { columns, rows } => {
618-
Constructor::PartialMatrix { columns, rows }
619-
}
620-
ast::ConstructorType::Matrix {
621-
rows,
622-
columns,
623-
ty,
624-
ty_span,
625-
} => {
626-
let ty = self.resolve_ast_type(ty, &mut ctx.as_const())?;
627-
let scalar = match ctx.module.types[ty].inner {
628-
crate::TypeInner::Scalar(sc) => sc,
629-
_ => return Err(Box::new(Error::UnknownScalarType(ty_span))),
630-
};
631-
let ty = match scalar.kind {
632-
crate::ScalarKind::Float => ctx.ensure_type_exists(crate::TypeInner::Matrix {
633-
columns,
634-
rows,
635-
scalar,
636-
}),
637-
_ => return Err(Box::new(Error::BadMatrixScalarKind(ty_span, scalar))),
638-
};
639-
Constructor::Type(ty)
640-
}
641-
ast::ConstructorType::PartialArray => Constructor::PartialArray,
642-
ast::ConstructorType::Array { base, size } => {
643-
let base = self.resolve_ast_type(base, &mut ctx.as_const())?;
644-
let size = self.array_size(size, &mut ctx.as_const())?;
645-
646-
ctx.layouter.update(ctx.module.to_ctx()).unwrap();
647-
let stride = ctx.layouter[base].to_stride();
648-
649-
let ty = ctx.ensure_type_exists(crate::TypeInner::Array { base, size, stride });
650-
Constructor::Type(ty)
651-
}
652-
ast::ConstructorType::Type(ty) => Constructor::Type(ty),
653-
};
654-
655-
Ok(handle)
656-
}
657579
}

0 commit comments

Comments
 (0)