Skip to content

Commit 158f0bb

Browse files
teoxoyjimblandy
authored andcommitted
handle bitcast, coopLoad and construction exprs in the lowerer
1 parent b2c927a commit 158f0bb

12 files changed

Lines changed: 1095 additions & 946 deletions

File tree

naga/src/front/wgsl/error.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ pub(crate) enum Error<'a> {
200200
ReservedIdentifierPrefix(Span),
201201
UnknownAddressSpace(Span),
202202
InvalidLocalVariableAddressSpace(Span),
203+
UnknownRayFlag(Span),
203204
RepeatedAttribute(Span),
204205
UnknownAttribute(Span),
205206
UnknownBuiltin(Span),
@@ -276,6 +277,7 @@ pub(crate) enum Error<'a> {
276277
span: Span,
277278
},
278279
CalledEntryPoint(Span),
280+
CalledLocalDecl(Span),
279281
WrongArgumentCount {
280282
span: Span,
281283
expected: Range<u32>,
@@ -422,6 +424,12 @@ pub(crate) enum Error<'a> {
422424
UnexpectedIdentForEnumerant(Span),
423425
UnexpectedExprForEnumerant(Span),
424426
UnusedArgsForTemplate(Vec<Span>),
427+
UnexpectedTemplate(Span),
428+
MissingTemplateArg {
429+
span: Span,
430+
arg: &'static str,
431+
},
432+
UnexpectedExprForTypeExpression(Span),
425433
}
426434

427435
impl From<ConflictingDiagnosticRuleError> for Error<'_> {
@@ -667,6 +675,11 @@ impl<'a> Error<'a> {
667675
labels: vec![(bad_span, "local variables can only use 'function' address space".into())],
668676
notes: vec![],
669677
},
678+
Error::UnknownRayFlag(bad_span) => ParseError {
679+
message: format!("unknown ray flag: `{}`", &source[bad_span]),
680+
labels: vec![(bad_span, "unknown ray flag".into())],
681+
notes: vec![],
682+
},
670683
Error::RepeatedAttribute(bad_span) => ParseError {
671684
message: format!("repeated attribute: `{}`", &source[bad_span]),
672685
labels: vec![(bad_span, "repeated attribute".into())],
@@ -926,6 +939,11 @@ impl<'a> Error<'a> {
926939
labels: vec![(span, "entry point cannot be called".into())],
927940
notes: vec![],
928941
},
942+
Error::CalledLocalDecl(span) => ParseError {
943+
message: "local declaration cannot be called".to_string(),
944+
labels: vec![(span, "local declaration cannot be called".into())],
945+
notes: vec![],
946+
},
929947
Error::WrongArgumentCount {
930948
span,
931949
ref expected,
@@ -1434,6 +1452,27 @@ impl<'a> Error<'a> {
14341452
labels: expr_spans.iter().cloned().map(|span| -> (_, _){ (span, "unused".into()) }).collect(),
14351453
notes: vec![],
14361454
},
1455+
Error::UnexpectedTemplate(span) => ParseError {
1456+
message: "unexpected template".to_string(),
1457+
labels: vec![(span, "expected identifier".into())],
1458+
notes: vec![],
1459+
},
1460+
Error::MissingTemplateArg {
1461+
span,
1462+
arg,
1463+
} => ParseError {
1464+
message: format!(
1465+
"`{}` needs a template argument specified: {arg}",
1466+
&source[span]
1467+
),
1468+
labels: vec![(span, "is missing a template argument".into())],
1469+
notes: vec![],
1470+
},
1471+
Error::UnexpectedExprForTypeExpression(expr_span) => ParseError {
1472+
message: "unexpected expression".to_string(),
1473+
labels: vec![(expr_span, "needs to be an identifier resolving to a type declaration (alias or struct) or predeclared type(-generator)".into())],
1474+
notes: vec![],
1475+
}
14371476
}
14381477
}
14391478
}

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

Lines changed: 28 additions & 131 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::{TryToWgsl, 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 {
@@ -108,24 +100,20 @@ impl<'source> Lowerer<'source, '_> {
108100
/// it's one of the `Partial` variants, we need to consider the argument
109101
/// types as well.
110102
///
111-
/// This is used for [`Construct`] expressions, but also for [`Call`]
112-
/// expressions, once we've determined that the "callable" (in WGSL spec
113-
/// terms) is actually a type.
103+
/// This is used for [`Call`] expressions, once we've determined that
104+
/// the "callable" (in WGSL spec terms) is actually a type.
114105
///
115-
/// [`Construct`]: ast::Expression::Construct
116106
/// [`Call`]: ast::Expression::Call
117107
pub fn construct(
118108
&mut self,
119109
span: Span,
120-
constructor: &ast::ConstructorType<'source>,
110+
constructor: Constructor<Handle<crate::Type>>,
121111
ty_span: Span,
122112
components: &[Handle<ast::Expression<'source>>],
123113
ctx: &mut ExpressionContext<'source, '_, '_>,
124114
) -> Result<'source, Handle<crate::Expression>> {
125115
use crate::proc::TypeResolution as Tr;
126116

127-
let constructor_h = self.constructor(constructor, ctx)?;
128-
129117
let components = match *components {
130118
[] => Components::None,
131119
[component] => {
@@ -160,7 +148,7 @@ impl<'source> Lowerer<'source, '_> {
160148
// Even though we computed `constructor` above, wait until now to borrow
161149
// a reference to the `TypeInner`, so that the component-handling code
162150
// above can have mutable access to the type arena.
163-
let constructor = constructor_h.borrow_inner(ctx.module);
151+
let constructor = constructor.borrow_inner(ctx.module);
164152

165153
let expr;
166154
match (components, constructor) {
@@ -573,14 +561,19 @@ impl<'source> Lowerer<'source, '_> {
573561
Components::One {
574562
span, component, ..
575563
},
576-
constructor,
564+
Constructor::Type((
565+
ty,
566+
&(crate::TypeInner::Scalar { .. }
567+
| crate::TypeInner::Vector { .. }
568+
| crate::TypeInner::Matrix { .. }),
569+
)),
577570
) => {
578571
let component_ty = &ctx.typifier()[component];
579572
let from_type = ctx.type_resolution_to_string(component_ty);
580573
return Err(Box::new(Error::BadTypeCast {
581574
span,
582575
from_type,
583-
to_type: constructor.to_error_string(ctx),
576+
to_type: ctx.type_to_string(ty),
584577
}));
585578
}
586579

@@ -600,100 +593,4 @@ impl<'source> Lowerer<'source, '_> {
600593
let expr = ctx.append_expression(expr, span)?;
601594
Ok(expr)
602595
}
603-
604-
/// Build a [`Constructor`] for a WGSL construction expression.
605-
///
606-
/// If `constructor` conveys enough information to determine which Naga [`Type`]
607-
/// we're actually building (i.e., it's not a partial constructor), then
608-
/// ensure the `Type` exists in [`ctx.module`], and return
609-
/// [`Constructor::Type`].
610-
///
611-
/// Otherwise, return the [`Constructor`] partial variant corresponding to
612-
/// `constructor`.
613-
///
614-
/// [`Type`]: crate::Type
615-
/// [`ctx.module`]: ExpressionContext::module
616-
fn constructor<'out>(
617-
&mut self,
618-
constructor: &ast::ConstructorType<'source>,
619-
ctx: &mut ExpressionContext<'source, '_, 'out>,
620-
) -> Result<'source, Constructor<Handle<crate::Type>>> {
621-
let handle = match *constructor {
622-
ast::ConstructorType::Scalar(scalar) => {
623-
let ty = ctx.ensure_type_exists(scalar.to_inner_scalar());
624-
Constructor::Type(ty)
625-
}
626-
ast::ConstructorType::PartialVector { size } => Constructor::PartialVector { size },
627-
ast::ConstructorType::Vector { size, ty, ty_span } => {
628-
let ty = self.resolve_ast_type(ty, &mut ctx.as_const())?;
629-
let scalar = match ctx.module.types[ty].inner {
630-
crate::TypeInner::Scalar(sc) => sc,
631-
_ => return Err(Box::new(Error::UnknownScalarType(ty_span))),
632-
};
633-
let ty = ctx.ensure_type_exists(crate::TypeInner::Vector { size, scalar });
634-
Constructor::Type(ty)
635-
}
636-
ast::ConstructorType::PartialMatrix { columns, rows } => {
637-
Constructor::PartialMatrix { columns, rows }
638-
}
639-
ast::ConstructorType::Matrix {
640-
rows,
641-
columns,
642-
ty,
643-
ty_span,
644-
} => {
645-
let ty = self.resolve_ast_type(ty, &mut ctx.as_const())?;
646-
let scalar = match ctx.module.types[ty].inner {
647-
crate::TypeInner::Scalar(sc) => sc,
648-
_ => return Err(Box::new(Error::UnknownScalarType(ty_span))),
649-
};
650-
let ty = match scalar.kind {
651-
crate::ScalarKind::Float => ctx.ensure_type_exists(crate::TypeInner::Matrix {
652-
columns,
653-
rows,
654-
scalar,
655-
}),
656-
_ => return Err(Box::new(Error::BadMatrixScalarKind(ty_span, scalar))),
657-
};
658-
Constructor::Type(ty)
659-
}
660-
ast::ConstructorType::PartialCooperativeMatrix { .. } => {
661-
return Err(Box::new(Error::UnderspecifiedCooperativeMatrix));
662-
}
663-
ast::ConstructorType::CooperativeMatrix {
664-
rows,
665-
columns,
666-
ty,
667-
ty_span,
668-
role,
669-
} => {
670-
let ty = self.resolve_ast_type(ty, &mut ctx.as_const())?;
671-
let scalar = match ctx.module.types[ty].inner {
672-
crate::TypeInner::Scalar(s) => s,
673-
_ => return Err(Box::new(Error::UnsupportedCooperativeScalar(ty_span))),
674-
};
675-
let ty = ctx.ensure_type_exists(crate::TypeInner::CooperativeMatrix {
676-
columns,
677-
rows,
678-
scalar,
679-
role,
680-
});
681-
Constructor::Type(ty)
682-
}
683-
ast::ConstructorType::PartialArray => Constructor::PartialArray,
684-
ast::ConstructorType::Array { base, size } => {
685-
let base = self.resolve_ast_type(base, &mut ctx.as_const())?;
686-
let size = self.array_size(size, &mut ctx.as_const())?;
687-
688-
ctx.layouter.update(ctx.module.to_ctx()).unwrap();
689-
let stride = ctx.layouter[base].to_stride();
690-
691-
let ty = ctx.ensure_type_exists(crate::TypeInner::Array { base, size, stride });
692-
Constructor::Type(ty)
693-
}
694-
ast::ConstructorType::Type(ty) => Constructor::Type(ty),
695-
};
696-
697-
Ok(handle)
698-
}
699596
}

0 commit comments

Comments
 (0)