Skip to content

Commit 4f22f8d

Browse files
jimblandyErichDonGubler
authored andcommitted
[naga wgsl-in] Apply automatic conversions to values being assigned.
Apply automatic conversions to the right-hand sides of assignment and compound assignment statements. Fix `try_automatic_conversion_for_leaf_scalar` to handle arrays, not just scalars, vectors, and matrices. Previously this was only used for converting the right-hand sides of bit shift operators to `u32`, and bit shift operators don't support arrays. But now we're using `try_automatic_conversion_for_leaf_scalar` for ordinary assignments, and you can assign arrays. Update a test of propagating source code spans through compaction. This test needs validation to report an error, but this commit's fix causes the error in the test to be detected in the front end, which is too early to exercise compaction. Use a new error that the front end still won't notice.
1 parent 04f0de6 commit 4f22f8d

File tree

3 files changed

+63
-17
lines changed

3 files changed

+63
-17
lines changed

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl<'source> super::ExpressionContext<'source, '_, '_> {
9393
}))
9494
};
9595

96-
let expr_scalar = match expr_inner.scalar() {
96+
let expr_scalar = match expr_inner.automatically_convertible_scalar(&self.module.types) {
9797
Some(scalar) => scalar,
9898
None => return Err(make_error()),
9999
};
@@ -436,6 +436,32 @@ impl crate::TypeInner {
436436
| Ti::BindingArray { .. } => None,
437437
}
438438
}
439+
440+
/// Return the leaf scalar type of `pointer`.
441+
///
442+
/// `pointer` must be a `TypeInner` representing a pointer type.
443+
pub fn pointer_automatically_convertible_scalar(
444+
&self,
445+
types: &crate::UniqueArena<crate::Type>,
446+
) -> Option<crate::Scalar> {
447+
use crate::TypeInner as Ti;
448+
match *self {
449+
Ti::Scalar(scalar) | Ti::Vector { scalar, .. } | Ti::Matrix { scalar, .. } => {
450+
Some(scalar)
451+
}
452+
Ti::Atomic(_) => None,
453+
Ti::Pointer { base, .. } | Ti::Array { base, .. } => {
454+
types[base].inner.automatically_convertible_scalar(types)
455+
}
456+
Ti::ValuePointer { scalar, .. } => Some(scalar),
457+
Ti::Struct { .. }
458+
| Ti::Image { .. }
459+
| Ti::Sampler { .. }
460+
| Ti::AccelerationStructure
461+
| Ti::RayQuery
462+
| Ti::BindingArray { .. } => None,
463+
}
464+
}
439465
}
440466

441467
impl crate::Scalar {

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

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,31 +1700,48 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
17001700
} => {
17011701
let mut emitter = Emitter::default();
17021702
emitter.start(&ctx.function.expressions);
1703+
let target_span = ctx.ast_expressions.get_span(ast_target);
17031704

1704-
let target = self.expression_for_reference(
1705-
ast_target,
1706-
&mut ctx.as_expression(block, &mut emitter),
1707-
)?;
1708-
let mut value =
1709-
self.expression(value, &mut ctx.as_expression(block, &mut emitter))?;
1710-
1705+
let mut ectx = ctx.as_expression(block, &mut emitter);
1706+
let target = self.expression_for_reference(ast_target, &mut ectx)?;
17111707
let target_handle = match target {
17121708
Typed::Reference(handle) => handle,
17131709
Typed::Plain(handle) => {
17141710
let ty = ctx.invalid_assignment_type(handle);
17151711
return Err(Error::InvalidAssignment {
1716-
span: ctx.ast_expressions.get_span(ast_target),
1712+
span: target_span,
17171713
ty,
17181714
});
17191715
}
17201716
};
17211717

1718+
// Usually the value needs to be converted to match the type of
1719+
// the memory view you're assigning it to. The bit shift
1720+
// operators are exceptions, in that the right operand is always
1721+
// a `u32` or `vecN<u32>`.
1722+
let target_scalar = match op {
1723+
Some(crate::BinaryOperator::ShiftLeft | crate::BinaryOperator::ShiftRight) => {
1724+
Some(crate::Scalar::U32)
1725+
}
1726+
_ => resolve_inner!(ectx, target_handle)
1727+
.pointer_automatically_convertible_scalar(&ectx.module.types),
1728+
};
1729+
1730+
let value = self.expression_for_abstract(value, &mut ectx)?;
1731+
let mut value = match target_scalar {
1732+
Some(target_scalar) => ectx.try_automatic_conversion_for_leaf_scalar(
1733+
value,
1734+
target_scalar,
1735+
target_span,
1736+
)?,
1737+
None => value,
1738+
};
1739+
17221740
let value = match op {
17231741
Some(op) => {
1724-
let mut ctx = ctx.as_expression(block, &mut emitter);
1725-
let mut left = ctx.apply_load_rule(target)?;
1726-
ctx.binary_op_splat(op, &mut left, &mut value)?;
1727-
ctx.append_expression(
1742+
let mut left = ectx.apply_load_rule(target)?;
1743+
ectx.binary_op_splat(op, &mut left, &mut value)?;
1744+
ectx.append_expression(
17281745
crate::Expression::Binary {
17291746
op,
17301747
left,

naga/tests/wgsl_errors.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,10 +2108,10 @@ fn compaction_preserves_spans() {
21082108
let source = r#"
21092109
fn f() {
21102110
var a: i32 = -(-(-(-42i)));
2111-
var x: i32;
2112-
x = 42u;
2111+
var x: array<i32,1>;
2112+
var y = x[1.0];
21132113
}
2114-
"#; // ^^^ correct error span: 95..98
2114+
"#; // ^^^ correct error span: 108..114
21152115
let mut module = naga::front::wgsl::parse_str(source).expect("source ought to parse");
21162116
naga::compact::compact(&mut module);
21172117
let err = naga::valid::Validator::new(
@@ -2135,7 +2135,10 @@ fn compaction_preserves_spans() {
21352135
.0;
21362136
if !matches!(
21372137
dest_span.to_range(),
2138-
Some(std::ops::Range { start: 95, end: 98 })
2138+
Some(std::ops::Range {
2139+
start: 108,
2140+
end: 114
2141+
})
21392142
) {
21402143
panic!("Error message has wrong span:\n\n{err:#?}");
21412144
}

0 commit comments

Comments
 (0)