Proof of concept for "span" feature, with WGSL & GLSL parsing augmented. (#1092)

* Proof of concept for "span" feature, with WGSL parsing augmented.

* Review:

1) add_span was actually a bad idea, make it set_span and add
set_span_if_unknown too.
2) panics on getting/setting span for invalid handles.
3) only set span for constants with a name
4) don't overwrite spans for types.

* Added spans to blocks & more expressions getting spans in frontends.

Definitely the shotgunny type of commit, but what can you do. The design
I went with made spans mandatory to specify, so I had to go and wire
them through wherever I could.

* Moved Block to a separate module, +clippy

* More spans for types in GLSL.

* Remove pointless body method.

* Make Arena interface require spans.

Another shotgun commit, oh boy...

* Fix tests.

My loathsome habit to "quickly fix things along the way" made a lot of
extra work for me here, having to fix my "fixes" for WGSL parser.

* Rustfmt + clippy.

* Fix compile-errors with span feature enabled.

* Nuked set_span* from orbit. Deleting code feels great!

* Code review - move feature flags inside functions.

* Fix build with "deserialize" feature enabled.
This commit is contained in:
Alex Es
2021-08-11 23:04:32 +03:00
committed by GitHub
parent e2fc7ffd03
commit fd70116668
29 changed files with 2819 additions and 1568 deletions

View File

@@ -42,6 +42,7 @@ spv-out = ["spirv"]
wgsl-in = ["codespan-reporting"]
wgsl-out = []
hlsl-out = []
span = ["codespan-reporting"]
[dev-dependencies]
diff = "0.1"

View File

@@ -5,6 +5,8 @@ use std::{cmp::Ordering, fmt, hash, marker::PhantomData, num::NonZeroU32, ops};
/// the same size and representation as `Handle<T>`.
type Index = NonZeroU32;
use crate::Span;
/// A strongly typed reference to an arena item.
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
@@ -123,7 +125,6 @@ impl<T> Iterator for Range<T> {
/// The arena can be indexed using the given handle to obtain
/// a reference to the stored item.
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
#[cfg_attr(
any(feature = "serialize", feature = "deserialize"),
serde(transparent)
@@ -132,6 +133,9 @@ impl<T> Iterator for Range<T> {
pub struct Arena<T> {
/// Values of this arena.
data: Vec<T>,
#[cfg(feature = "span")]
#[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(skip))]
span_info: Vec<Span>,
}
impl<T> Default for Arena<T> {
@@ -148,7 +152,11 @@ impl<T: fmt::Debug> fmt::Debug for Arena<T> {
impl<T> Arena<T> {
/// Create a new arena with no initial capacity allocated.
pub fn new() -> Self {
Arena { data: Vec::new() }
Arena {
data: Vec::new(),
#[cfg(feature = "span")]
span_info: Vec::new(),
}
}
/// Extracts the inner vector.
@@ -187,11 +195,15 @@ impl<T> Arena<T> {
}
/// Adds a new value to the arena, returning a typed handle.
pub fn append(&mut self, value: T) -> Handle<T> {
pub fn append(&mut self, value: T, span: Span) -> Handle<T> {
#[cfg(not(feature = "span"))]
let _ = span;
let position = self.data.len() + 1;
let index =
Index::new(position as u32).expect("Failed to append to Arena. Handle overflows");
self.data.push(value);
#[cfg(feature = "span")]
self.span_info.push(span);
Handle::new(index)
}
@@ -207,30 +219,35 @@ impl<T> Arena<T> {
/// returns a handle pointing to
/// an existing element if the check succeeds, or adds a new
/// element otherwise.
pub fn fetch_if_or_append<F: Fn(&T, &T) -> bool>(&mut self, value: T, fun: F) -> Handle<T> {
pub fn fetch_if_or_append<F: Fn(&T, &T) -> bool>(
&mut self,
value: T,
span: Span,
fun: F,
) -> Handle<T> {
if let Some(index) = self.data.iter().position(|d| fun(d, &value)) {
let index = unsafe { Index::new_unchecked((index + 1) as u32) };
Handle::new(index)
} else {
self.append(value)
self.append(value, span)
}
}
/// Adds a value with a check for uniqueness, where the check is plain comparison.
pub fn fetch_or_append(&mut self, value: T) -> Handle<T>
pub fn fetch_or_append(&mut self, value: T, span: Span) -> Handle<T>
where
T: PartialEq,
{
self.fetch_if_or_append(value, T::eq)
self.fetch_if_or_append(value, span, T::eq)
}
pub fn try_get(&self, handle: Handle<T>) -> Option<&T> {
self.data.get(handle.index.get() as usize - 1)
self.data.get(handle.index())
}
/// Get a mutable reference to an element in the arena.
pub fn get_mut(&mut self, handle: Handle<T>) -> &mut T {
self.data.get_mut(handle.index.get() as usize - 1).unwrap()
self.data.get_mut(handle.index()).unwrap()
}
/// Get the range of handles from a particular number of elements to the end.
@@ -245,6 +262,39 @@ impl<T> Arena<T> {
pub fn clear(&mut self) {
self.data.clear()
}
pub fn get_span(&self, handle: Handle<T>) -> &Span {
#[cfg(feature = "span")]
{
return self.span_info.get(handle.index()).unwrap_or(&Span::Unknown);
}
#[cfg(not(feature = "span"))]
{
let _ = handle;
&Span::Unknown
}
}
}
#[cfg(feature = "deserialize")]
impl<'de, T> serde::Deserialize<'de> for Arena<T>
where
T: serde::Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let data = Vec::deserialize(deserializer)?;
#[cfg(feature = "span")]
let span_info = std::iter::repeat(Span::Unknown).take(data.len()).collect();
Ok(Self {
data,
#[cfg(feature = "span")]
span_info,
})
}
}
impl<T> ops::Index<Handle<T>> for Arena<T> {
@@ -254,6 +304,12 @@ impl<T> ops::Index<Handle<T>> for Arena<T> {
}
}
impl<T> ops::IndexMut<Handle<T>> for Arena<T> {
fn index_mut(&mut self, handle: Handle<T>) -> &mut T {
&mut self.data[handle.index()]
}
}
impl<T> ops::Index<Range<T>> for Arena<T> {
type Output = [T];
fn index(&self, range: Range<T>) -> &[T] {
@@ -268,8 +324,8 @@ mod tests {
#[test]
fn append_non_unique() {
let mut arena: Arena<u8> = Arena::new();
let t1 = arena.append(0);
let t2 = arena.append(0);
let t1 = arena.append(0, Default::default());
let t2 = arena.append(0, Default::default());
assert!(t1 != t2);
assert!(arena[t1] == arena[t2]);
}
@@ -277,8 +333,8 @@ mod tests {
#[test]
fn append_unique() {
let mut arena: Arena<u8> = Arena::new();
let t1 = arena.append(0);
let t2 = arena.append(1);
let t1 = arena.append(0, Default::default());
let t2 = arena.append(1, Default::default());
assert!(t1 != t2);
assert!(arena[t1] != arena[t2]);
}
@@ -286,8 +342,8 @@ mod tests {
#[test]
fn fetch_or_append_non_unique() {
let mut arena: Arena<u8> = Arena::new();
let t1 = arena.fetch_or_append(0);
let t2 = arena.fetch_or_append(0);
let t1 = arena.fetch_or_append(0, Default::default());
let t2 = arena.fetch_or_append(0, Default::default());
assert!(t1 == t2);
assert!(arena[t1] == arena[t2])
}
@@ -295,8 +351,8 @@ mod tests {
#[test]
fn fetch_or_append_unique() {
let mut arena: Arena<u8> = Arena::new();
let t1 = arena.fetch_or_append(0);
let t2 = arena.fetch_or_append(1);
let t1 = arena.fetch_or_append(0, Default::default());
let t2 = arena.fetch_or_append(1, Default::default());
assert!(t1 != t2);
assert!(arena[t1] != arena[t2]);
}

View File

@@ -2555,30 +2555,41 @@ fn test_stack_size() {
use crate::valid::{Capabilities, ValidationFlags};
// create a module with at least one expression nested
let mut module = crate::Module::default();
let constant = module.constants.append(crate::Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
value: crate::ScalarValue::Float(1.0),
width: 4,
let constant = module.constants.append(
crate::Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
value: crate::ScalarValue::Float(1.0),
width: 4,
},
},
});
Default::default(),
);
let mut fun = crate::Function::default();
let const_expr = fun
.expressions
.append(crate::Expression::Constant(constant));
let nested_expr = fun.expressions.append(crate::Expression::Unary {
op: crate::UnaryOperator::Negate,
expr: const_expr,
});
fun.body
.push(crate::Statement::Emit(fun.expressions.range_from(1)));
fun.body.push(crate::Statement::If {
condition: nested_expr,
accept: Vec::new(),
reject: Vec::new(),
});
let _ = module.functions.append(fun);
.append(crate::Expression::Constant(constant), Default::default());
let nested_expr = fun.expressions.append(
crate::Expression::Unary {
op: crate::UnaryOperator::Negate,
expr: const_expr,
},
Default::default(),
);
fun.body.push(
crate::Statement::Emit(fun.expressions.range_from(1)),
Default::default(),
);
fun.body.push(
crate::Statement::If {
condition: nested_expr,
accept: crate::Block::new(),
reject: crate::Block::new(),
},
Default::default(),
);
let _ = module.functions.append(fun, Default::default());
// analyse the module
let info = crate::valid::Validator::new(ValidationFlags::empty(), Capabilities::empty())
.validate(&module)

View File

@@ -119,13 +119,12 @@ impl<'w> BlockContext<'w> {
Some(ix) => ix,
};
let array_index_u32_id = self.cached[array_index];
let coordinate_scalar_type_id =
self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Float,
width: 4,
pointer_class: None,
}))?;
let coordinate_scalar_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Float,
width: 4,
pointer_class: None,
}))?;
let array_index_f32_id = self.gen_id();
block.body.push(Instruction::unary(
spirv::Op::ConvertUToF,
@@ -161,7 +160,7 @@ impl<'w> BlockContext<'w> {
block.body.push(Instruction::composite_construct(
extended_coordinate_type_id,
id,
&[coordinate_id, array_index_f32_id]
&[coordinate_id, array_index_f32_id],
));
Ok(id)
}

131
src/block.rs Normal file
View File

@@ -0,0 +1,131 @@
use crate::{Span, Statement};
use std::ops::{Deref, DerefMut, RangeBounds};
/// A code block is a vector of statements, with maybe a vector of spans.
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(
any(feature = "serialize", feature = "deserialize"),
serde(transparent)
)]
pub struct Block {
body: Vec<Statement>,
#[cfg(feature = "span")]
#[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(skip))]
span_info: Vec<Span>,
}
impl Block {
pub fn new() -> Self {
Self {
body: Vec::new(),
#[cfg(feature = "span")]
span_info: Vec::new(),
}
}
pub fn from_vec(body: Vec<Statement>) -> Self {
#[cfg(feature = "span")]
let span_info = std::iter::repeat(Span::Unknown).take(body.len()).collect();
Self {
body,
#[cfg(feature = "span")]
span_info,
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
body: Vec::with_capacity(capacity),
#[cfg(feature = "span")]
span_info: Vec::with_capacity(capacity),
}
}
#[allow(unused_variables)]
pub fn push(&mut self, end: Statement, span: Span) {
self.body.push(end);
#[cfg(feature = "span")]
self.span_info.push(span);
}
pub fn extend(&mut self, item: Option<(Statement, Span)>) {
if let Some((end, span)) = item {
self.push(end, span)
}
}
pub fn extend_block(&mut self, other: Self) {
#[cfg(feature = "span")]
self.span_info.extend(other.span_info);
self.body.extend(other.body);
}
pub fn cull<R: RangeBounds<usize> + Clone>(&mut self, range: R) {
#[cfg(feature = "span")]
self.span_info.drain(range.clone());
self.body.drain(range);
}
pub fn splice<R: RangeBounds<usize> + Clone>(&mut self, range: R, other: Self) {
#[cfg(feature = "span")]
self.span_info
.splice(range.clone(), other.span_info.into_iter());
self.body.splice(range, other.body.into_iter());
}
pub fn span_iter_mut(&mut self) -> impl Iterator<Item = (&mut Statement, Option<&mut Span>)> {
#[cfg(feature = "span")]
let span_iter = self.span_info.iter_mut().map(Some);
#[cfg(not(feature = "span"))]
let span_iter = std::iter::repeat_with(|| None);
self.body.iter_mut().zip(span_iter)
}
pub fn is_empty(&self) -> bool {
self.body.is_empty()
}
pub fn len(&self) -> usize {
self.body.len()
}
}
impl Deref for Block {
type Target = [Statement];
fn deref(&self) -> &[Statement] {
&self.body
}
}
impl DerefMut for Block {
fn deref_mut(&mut self) -> &mut [Statement] {
&mut self.body
}
}
impl<'a> IntoIterator for &'a Block {
type Item = &'a Statement;
type IntoIter = std::slice::Iter<'a, Statement>;
fn into_iter(self) -> std::slice::Iter<'a, Statement> {
self.iter()
}
}
#[cfg(feature = "deserialize")]
impl<'de> serde::Deserialize<'de> for Block {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(Self::from_vec(Vec::deserialize(deserializer)?))
}
}
impl From<Vec<Statement>> for Block {
fn from(body: Vec<Statement>) -> Self {
Self::from_vec(body)
}
}

View File

@@ -64,6 +64,7 @@ impl<'a> ConstantSolver<'a> {
&mut self,
expr: Handle<Expression>,
) -> Result<Handle<Constant>, ConstantSolvingError> {
let span = self.expressions.get_span(expr).clone();
match self.expressions[expr] {
Expression::Constant(constant) => Ok(constant),
Expression::AccessIndex { base, index } => self.access(base, index as usize),
@@ -88,14 +89,17 @@ impl<'a> ConstantSolver<'a> {
//TODO: register the new type if needed
let ty = ty.ok_or(ConstantSolvingError::DestinationTypeNotFound)?;
Ok(self.constants.fetch_or_append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite {
ty,
components: vec![value_constant; size as usize],
Ok(self.constants.fetch_or_append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite {
ty,
components: vec![value_constant; size as usize],
},
},
}))
span,
))
}
Expression::Swizzle {
size,
@@ -129,11 +133,14 @@ impl<'a> ConstantSolver<'a> {
.map(|&sc| src_components[sc as usize])
.collect();
Ok(self.constants.fetch_or_append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite { ty, components },
}))
Ok(self.constants.fetch_or_append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite { ty, components },
},
span,
))
}
Expression::Compose { ty, ref components } => {
let components = components
@@ -141,22 +148,25 @@ impl<'a> ConstantSolver<'a> {
.map(|c| self.solve(*c))
.collect::<Result<_, _>>()?;
Ok(self.constants.fetch_or_append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite { ty, components },
}))
Ok(self.constants.fetch_or_append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite { ty, components },
},
span,
))
}
Expression::Unary { expr, op } => {
let expr_constant = self.solve(expr)?;
self.unary_op(op, expr_constant)
self.unary_op(op, expr_constant, span)
}
Expression::Binary { left, right, op } => {
let left_constant = self.solve(left)?;
let right_constant = self.solve(right)?;
self.binary_op(op, left_constant, right_constant)
self.binary_op(op, left_constant, right_constant, span)
}
Expression::Math { fun, arg, arg1, .. } => {
let arg = self.solve(arg)?;
@@ -192,11 +202,14 @@ impl<'a> ConstantSolver<'a> {
_ => return Err(ConstantSolvingError::InvalidMathArg),
};
Ok(self.constants.fetch_or_append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar { width, value },
}))
Ok(self.constants.fetch_or_append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar { width, value },
},
span,
))
}
_ => Err(ConstantSolvingError::NotImplemented(format!("{:?}", fun))),
}
@@ -209,7 +222,7 @@ impl<'a> ConstantSolver<'a> {
let expr_constant = self.solve(expr)?;
match convert {
Some(width) => self.cast(expr_constant, kind, width),
Some(width) => self.cast(expr_constant, kind, width, span),
None => Err(ConstantSolvingError::Bitcast),
}
}
@@ -288,6 +301,7 @@ impl<'a> ConstantSolver<'a> {
constant: Handle<Constant>,
kind: ScalarKind,
target_width: crate::Bytes,
span: crate::Span,
) -> Result<Handle<Constant>, ConstantSolvingError> {
fn inner_cast<A: num_traits::FromPrimitive>(value: ScalarValue) -> A {
match value {
@@ -324,22 +338,26 @@ impl<'a> ConstantSolver<'a> {
}
for component in components {
*component = self.cast(*component, kind, target_width)?;
*component = self.cast(*component, kind, target_width, span.clone())?;
}
}
}
Ok(self.constants.fetch_or_append(Constant {
name: None,
specialization: None,
inner,
}))
Ok(self.constants.fetch_or_append(
Constant {
name: None,
specialization: None,
inner,
},
span,
))
}
fn unary_op(
&mut self,
op: UnaryOperator,
constant: Handle<Constant>,
span: crate::Span,
) -> Result<Handle<Constant>, ConstantSolvingError> {
let mut inner = self.constants[constant].inner.clone();
@@ -367,16 +385,19 @@ impl<'a> ConstantSolver<'a> {
}
for component in components {
*component = self.unary_op(op, *component)?
*component = self.unary_op(op, *component, span.clone())?
}
}
}
Ok(self.constants.fetch_or_append(Constant {
name: None,
specialization: None,
inner,
}))
Ok(self.constants.fetch_or_append(
Constant {
name: None,
specialization: None,
inner,
},
span,
))
}
fn binary_op(
@@ -384,6 +405,7 @@ impl<'a> ConstantSolver<'a> {
op: BinaryOperator,
left: Handle<Constant>,
right: Handle<Constant>,
span: crate::Span,
) -> Result<Handle<Constant>, ConstantSolvingError> {
let left_inner = &self.constants[left].inner;
let right_inner = &self.constants[right].inner;
@@ -464,25 +486,28 @@ impl<'a> ConstantSolver<'a> {
(&ConstantInner::Composite { ref components, ty }, &ConstantInner::Scalar { .. }) => {
let mut components = components.clone();
for comp in components.iter_mut() {
*comp = self.binary_op(op, *comp, right)?;
*comp = self.binary_op(op, *comp, right, span.clone())?;
}
ConstantInner::Composite { ty, components }
}
(&ConstantInner::Scalar { .. }, &ConstantInner::Composite { ref components, ty }) => {
let mut components = components.clone();
for comp in components.iter_mut() {
*comp = self.binary_op(op, left, *comp)?;
*comp = self.binary_op(op, left, *comp, span.clone())?;
}
ConstantInner::Composite { ty, components }
}
_ => return Err(ConstantSolvingError::InvalidBinaryOpArgs),
};
Ok(self.constants.fetch_or_append(Constant {
name: None,
specialization: None,
inner,
}))
Ok(self.constants.fetch_or_append(
Constant {
name: None,
specialization: None,
inner,
},
span,
))
}
}
@@ -503,59 +528,80 @@ mod tests {
let mut expressions = Arena::new();
let mut constants = Arena::new();
let vec_ty = types.append(Type {
name: None,
inner: TypeInner::Vector {
size: VectorSize::Bi,
kind: ScalarKind::Sint,
width: 4,
let vec_ty = types.append(
Type {
name: None,
inner: TypeInner::Vector {
size: VectorSize::Bi,
kind: ScalarKind::Sint,
width: 4,
},
},
});
Default::default(),
);
let h = constants.append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Sint(4),
let h = constants.append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Sint(4),
},
},
});
Default::default(),
);
let h1 = constants.append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Sint(8),
let h1 = constants.append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Sint(8),
},
},
});
Default::default(),
);
let vec_h = constants.append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite {
ty: vec_ty,
components: vec![h, h1],
let vec_h = constants.append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite {
ty: vec_ty,
components: vec![h, h1],
},
},
});
Default::default(),
);
let expr = expressions.append(Expression::Constant(h));
let expr1 = expressions.append(Expression::Constant(vec_h));
let expr = expressions.append(Expression::Constant(h), Default::default());
let expr1 = expressions.append(Expression::Constant(vec_h), Default::default());
let root1 = expressions.append(Expression::Unary {
op: UnaryOperator::Negate,
expr,
});
let root1 = expressions.append(
Expression::Unary {
op: UnaryOperator::Negate,
expr,
},
Default::default(),
);
let root2 = expressions.append(Expression::Unary {
op: UnaryOperator::Not,
expr,
});
let root2 = expressions.append(
Expression::Unary {
op: UnaryOperator::Not,
expr,
},
Default::default(),
);
let root3 = expressions.append(Expression::Unary {
op: UnaryOperator::Not,
expr: expr1,
});
let root3 = expressions.append(
Expression::Unary {
op: UnaryOperator::Not,
expr: expr1,
},
Default::default(),
);
let mut solver = ConstantSolver {
types: &types,
@@ -614,22 +660,28 @@ mod tests {
let mut expressions = Arena::new();
let mut constants = Arena::new();
let h = constants.append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Sint(4),
let h = constants.append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Sint(4),
},
},
});
Default::default(),
);
let expr = expressions.append(Expression::Constant(h));
let expr = expressions.append(Expression::Constant(h), Default::default());
let root = expressions.append(Expression::As {
expr,
kind: ScalarKind::Bool,
convert: Some(crate::BOOL_WIDTH),
});
let root = expressions.append(
Expression::As {
expr,
kind: ScalarKind::Bool,
convert: Some(crate::BOOL_WIDTH),
},
Default::default(),
);
let mut solver = ConstantSolver {
types: &Arena::new(),
@@ -654,86 +706,113 @@ mod tests {
let mut expressions = Arena::new();
let mut constants = Arena::new();
let matrix_ty = types.append(Type {
name: None,
inner: TypeInner::Matrix {
columns: VectorSize::Bi,
rows: VectorSize::Tri,
width: 4,
let matrix_ty = types.append(
Type {
name: None,
inner: TypeInner::Matrix {
columns: VectorSize::Bi,
rows: VectorSize::Tri,
width: 4,
},
},
});
Default::default(),
);
let vec_ty = types.append(Type {
name: None,
inner: TypeInner::Vector {
size: VectorSize::Tri,
kind: ScalarKind::Float,
width: 4,
let vec_ty = types.append(
Type {
name: None,
inner: TypeInner::Vector {
size: VectorSize::Tri,
kind: ScalarKind::Float,
width: 4,
},
},
});
Default::default(),
);
let mut vec1_components = Vec::with_capacity(3);
let mut vec2_components = Vec::with_capacity(3);
for i in 0..3 {
let h = constants.append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Float(i as f64),
let h = constants.append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Float(i as f64),
},
},
});
Default::default(),
);
vec1_components.push(h)
}
for i in 3..6 {
let h = constants.append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Float(i as f64),
let h = constants.append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Float(i as f64),
},
},
});
Default::default(),
);
vec2_components.push(h)
}
let vec1 = constants.append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite {
ty: vec_ty,
components: vec1_components,
let vec1 = constants.append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite {
ty: vec_ty,
components: vec1_components,
},
},
});
Default::default(),
);
let vec2 = constants.append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite {
ty: vec_ty,
components: vec2_components,
let vec2 = constants.append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite {
ty: vec_ty,
components: vec2_components,
},
},
});
Default::default(),
);
let h = constants.append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite {
ty: matrix_ty,
components: vec![vec1, vec2],
let h = constants.append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Composite {
ty: matrix_ty,
components: vec![vec1, vec2],
},
},
});
Default::default(),
);
let base = expressions.append(Expression::Constant(h));
let root1 = expressions.append(Expression::AccessIndex { base, index: 1 });
let root2 = expressions.append(Expression::AccessIndex {
base: root1,
index: 2,
});
let base = expressions.append(Expression::Constant(h), Default::default());
let root1 = expressions.append(
Expression::AccessIndex { base, index: 1 },
Default::default(),
);
let root2 = expressions.append(
Expression::AccessIndex {
base: root1,
index: 2,
},
Default::default(),
);
let mut solver = ConstantSolver {
types: &types,

View File

@@ -79,8 +79,9 @@ impl Context {
self.emit_flush(body);
let (expr, load) = match kind {
GlobalLookupKind::Variable(v) => {
let span = parser.module.global_variables.get_span(v).clone();
let res = (
self.expressions.append(Expression::GlobalVariable(v)),
self.expressions.append(Expression::GlobalVariable(v), span),
parser.module.global_variables[v].class != StorageClass::Handle,
);
self.emit_start();
@@ -88,11 +89,14 @@ impl Context {
res
}
GlobalLookupKind::BlockSelect(handle, index) => {
let base = self.expressions.append(Expression::GlobalVariable(handle));
let span = parser.module.global_variables.get_span(handle).clone();
let base = self
.expressions
.append(Expression::GlobalVariable(handle), span.clone());
self.emit_start();
let expr = self
.expressions
.append(Expression::AccessIndex { base, index });
.append(Expression::AccessIndex { base, index }, span);
(expr, {
let ty = parser.module.global_variables[handle].ty;
@@ -114,7 +118,11 @@ impl Context {
})
}
GlobalLookupKind::Constant(v) => {
let res = (self.expressions.append(Expression::Constant(v)), false);
let span = parser.module.constants.get_span(v).clone();
let res = (
self.expressions.append(Expression::Constant(v), span),
false,
);
self.emit_start();
res
}
@@ -138,15 +146,21 @@ impl Context {
body.extend(self.emitter.finish(&self.expressions))
}
pub fn add_expression(&mut self, expr: Expression, body: &mut Block) -> Handle<Expression> {
if expr.needs_pre_emit() {
pub fn add_expression(
&mut self,
expr: Expression,
meta: SourceMetadata,
body: &mut Block,
) -> Handle<Expression> {
let needs_pre_emit = expr.needs_pre_emit();
if needs_pre_emit {
self.emit_flush(body);
let handle = self.expressions.append(expr);
self.emit_start();
handle
} else {
self.expressions.append(expr)
}
let handle = self.expressions.append(expr, meta.as_span());
if needs_pre_emit {
self.emit_start();
}
handle
}
pub fn lookup_local_var(&self, name: &str) -> Option<VariableReference> {
@@ -191,13 +205,13 @@ impl Context {
&mut self,
parser: &mut Parser,
body: &mut Block,
name: Option<String>,
name_meta: Option<(String, SourceMetadata)>,
ty: Handle<Type>,
qualifier: ParameterQualifier,
) {
let index = self.arguments.len();
let mut arg = FunctionArgument {
name: name.clone(),
name: name_meta.as_ref().map(|&(ref name, _)| name.clone()),
ty,
binding: None,
};
@@ -209,13 +223,17 @@ impl Context {
};
if qualifier.is_lhs() {
arg.ty = parser.module.types.fetch_or_append(Type {
name: None,
inner: TypeInner::Pointer {
base: arg.ty,
class: StorageClass::Function,
let span = parser.module.types.get_span(arg.ty).clone();
arg.ty = parser.module.types.fetch_or_append(
Type {
name: None,
inner: TypeInner::Pointer {
base: arg.ty,
class: StorageClass::Function,
},
},
})
span,
)
}
self.arguments.push(arg);
@@ -225,26 +243,32 @@ impl Context {
depth: false,
});
if let Some(name) = name {
let expr = self.add_expression(Expression::FunctionArgument(index as u32), body);
if let Some((name, meta)) = name_meta {
let expr = self.add_expression(Expression::FunctionArgument(index as u32), meta, body);
let mutable = qualifier != ParameterQualifier::Const && !opaque;
let load = qualifier.is_lhs();
if mutable && !load {
let handle = self.locals.append(LocalVariable {
name: Some(name.clone()),
ty,
init: None,
});
let local_expr = self.add_expression(Expression::LocalVariable(handle), body);
let handle = self.locals.append(
LocalVariable {
name: Some(name.clone()),
ty,
init: None,
},
meta.as_span(),
);
let local_expr = self.add_expression(Expression::LocalVariable(handle), meta, body);
self.emit_flush(body);
self.emit_start();
body.push(Statement::Store {
pointer: local_expr,
value: expr,
});
body.push(
Statement::Store {
pointer: local_expr,
value: expr,
},
meta.as_span(),
);
if let Some(current) = self.scopes.last_mut() {
(*current).insert(
@@ -395,18 +419,19 @@ impl Context {
_ => return None,
},
},
meta,
body,
))
})
.unwrap_or_else(|| {
self.add_expression(Expression::Access { base, index }, body)
self.add_expression(Expression::Access { base, index }, meta, body)
});
if !lhs {
let resolved = parser.resolve_type(self, pointer, meta)?;
if resolved.pointer_class().is_some() {
return Ok((
Some(self.add_expression(Expression::Load { pointer }, body)),
Some(self.add_expression(Expression::Load { pointer }, meta, body)),
meta,
));
}
@@ -420,7 +445,7 @@ impl Context {
parser.field_selection(self, lhs, body, base, field, meta)?
}
HirExprKind::Constant(constant) if !lhs => {
self.add_expression(Expression::Constant(constant), body)
self.add_expression(Expression::Constant(constant), meta, body)
}
HirExprKind::Binary { left, op, right } if !lhs => {
let (mut left, left_meta) =
@@ -453,13 +478,19 @@ impl Context {
false => (BinaryOperator::NotEqual, RelationalFunction::Any),
};
let argument =
self.expressions
.append(Expression::Binary { op, left, right });
let argument = self
.expressions
.append(Expression::Binary { op, left, right }, meta.as_span());
self.add_expression(Expression::Relational { fun, argument }, body)
self.add_expression(
Expression::Relational { fun, argument },
meta,
body,
)
}
_ => {
self.add_expression(Expression::Binary { left, op, right }, meta, body)
}
_ => self.add_expression(Expression::Binary { left, op, right }, body),
},
(&TypeInner::Vector { size, .. }, &TypeInner::Scalar { .. }) => match op {
BinaryOperator::Add
@@ -467,8 +498,11 @@ impl Context {
| BinaryOperator::Divide
| BinaryOperator::ShiftLeft
| BinaryOperator::ShiftRight => {
let scalar_vector =
self.add_expression(Expression::Splat { size, value: right }, body);
let scalar_vector = self.add_expression(
Expression::Splat { size, value: right },
meta,
body,
);
self.add_expression(
Expression::Binary {
@@ -476,15 +510,21 @@ impl Context {
left,
right: scalar_vector,
},
meta,
body,
)
}
_ => self.add_expression(Expression::Binary { left, op, right }, body),
_ => {
self.add_expression(Expression::Binary { left, op, right }, meta, body)
}
},
(&TypeInner::Scalar { .. }, &TypeInner::Vector { size, .. }) => match op {
BinaryOperator::Add | BinaryOperator::Subtract | BinaryOperator::Divide => {
let scalar_vector =
self.add_expression(Expression::Splat { size, value: left }, body);
let scalar_vector = self.add_expression(
Expression::Splat { size, value: left },
meta,
body,
);
self.add_expression(
Expression::Binary {
@@ -492,18 +532,21 @@ impl Context {
left: scalar_vector,
right,
},
meta,
body,
)
}
_ => self.add_expression(Expression::Binary { left, op, right }, body),
_ => {
self.add_expression(Expression::Binary { left, op, right }, meta, body)
}
},
_ => self.add_expression(Expression::Binary { left, op, right }, body),
_ => self.add_expression(Expression::Binary { left, op, right }, meta, body),
}
}
HirExprKind::Unary { op, expr } if !lhs => {
let expr = self.lower_expect_inner(stmt, parser, expr, false, body)?.0;
self.add_expression(Expression::Unary { op, expr }, body)
self.add_expression(Expression::Unary { op, expr }, meta, body)
}
HirExprKind::Variable(ref var) => {
if lhs {
@@ -518,7 +561,7 @@ impl Context {
var.expr
} else if var.load {
self.add_expression(Expression::Load { pointer: var.expr }, body)
self.add_expression(Expression::Load { pointer: var.expr }, meta, body)
} else {
var.expr
}
@@ -561,6 +604,7 @@ impl Context {
accept,
reject,
},
meta,
body,
)
}
@@ -600,6 +644,7 @@ impl Context {
base: vector,
index: pattern[index].index(),
},
meta,
body,
);
let src = self.add_expression(
@@ -607,22 +652,26 @@ impl Context {
base: value,
index: index as u32,
},
meta,
body,
);
self.emit_flush(body);
self.emit_start();
body.push(Statement::Store {
pointer: dst,
value: src,
});
body.push(
Statement::Store {
pointer: dst,
value: src,
},
meta.as_span(),
);
}
} else {
self.emit_flush(body);
self.emit_start();
body.push(Statement::Store { pointer, value });
body.push(Statement::Store { pointer, value }, meta.as_span());
}
value
@@ -638,7 +687,7 @@ impl Context {
};
let pointer = self.lower_expect_inner(stmt, parser, expr, true, body)?.0;
let left = self.add_expression(Expression::Load { pointer }, body);
let left = self.add_expression(Expression::Load { pointer }, meta, body);
let uint = match parser.resolve_type(self, left, meta)?.scalar_kind() {
Some(ScalarKind::Sint) => false,
@@ -654,59 +703,71 @@ impl Context {
}
};
let one = parser.module.constants.append(Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
width: 4,
value: match uint {
true => crate::ScalarValue::Uint(1),
false => crate::ScalarValue::Sint(1),
let one = parser.module.constants.append(
Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
width: 4,
value: match uint {
true => crate::ScalarValue::Uint(1),
false => crate::ScalarValue::Sint(1),
},
},
},
});
let right = self.add_expression(Expression::Constant(one), body);
Default::default(),
);
let right = self.add_expression(Expression::Constant(one), meta, body);
let value = self.add_expression(Expression::Binary { op, left, right }, body);
let value = self.add_expression(Expression::Binary { op, left, right }, meta, body);
if postfix {
let local = self.locals.append(LocalVariable {
name: None,
ty: parser.module.types.fetch_or_append(Type {
let local = self.locals.append(
LocalVariable {
name: None,
inner: TypeInner::Scalar {
kind: match uint {
true => ScalarKind::Uint,
false => ScalarKind::Sint,
ty: parser.module.types.fetch_or_append(
Type {
name: None,
inner: TypeInner::Scalar {
kind: match uint {
true => ScalarKind::Uint,
false => ScalarKind::Sint,
},
width: 4,
},
},
width: 4,
},
}),
init: None,
});
meta.as_span(),
),
init: None,
},
meta.as_span(),
);
let expr = self.add_expression(Expression::LocalVariable(local), body);
let load = self.add_expression(Expression::Load { pointer: expr }, body);
let expr = self.add_expression(Expression::LocalVariable(local), meta, body);
let load = self.add_expression(Expression::Load { pointer: expr }, meta, body);
self.emit_flush(body);
self.emit_start();
body.push(Statement::Store {
pointer: expr,
value: left,
});
body.push(
Statement::Store {
pointer: expr,
value: left,
},
meta.as_span(),
);
self.emit_flush(body);
self.emit_start();
body.push(Statement::Store { pointer, value });
body.push(Statement::Store { pointer, value }, meta.as_span());
load
} else {
self.emit_flush(body);
self.emit_start();
body.push(Statement::Store { pointer, value });
body.push(Statement::Store { pointer, value }, meta.as_span());
left
}
@@ -758,11 +819,14 @@ impl Context {
(type_power(kind), self.expr_power(parser, *expr, meta)?)
{
if tgt_power > expr_power {
*expr = self.expressions.append(Expression::As {
expr: *expr,
kind,
convert: Some(width),
})
*expr = self.expressions.append(
Expression::As {
expr: *expr,
kind,
convert: Some(width),
},
meta.as_span(),
)
}
}
@@ -789,19 +853,25 @@ impl Context {
) {
match left_power.cmp(&right_power) {
std::cmp::Ordering::Less => {
*left = self.expressions.append(Expression::As {
expr: *left,
kind: right_kind,
convert: Some(right_width),
})
*left = self.expressions.append(
Expression::As {
expr: *left,
kind: right_kind,
convert: Some(right_width),
},
left_meta.as_span(),
)
}
std::cmp::Ordering::Equal => {}
std::cmp::Ordering::Greater => {
*right = self.expressions.append(Expression::As {
expr: *right,
kind: left_kind,
convert: Some(left_width),
})
*right = self.expressions.append(
Expression::As {
expr: *right,
kind: left_kind,
convert: Some(left_width),
},
right_meta.as_span(),
)
}
}
}
@@ -822,7 +892,7 @@ impl Context {
if let (&TypeInner::Scalar { .. }, Some(size)) = (expr_type, vector_size) {
*expr = self
.expressions
.append(Expression::Splat { size, value: *expr })
.append(Expression::Splat { size, value: *expr }, meta.as_span())
}
Ok(())
@@ -832,6 +902,7 @@ impl Context {
&mut self,
size: VectorSize,
vector: Handle<Expression>,
meta: SourceMetadata,
body: &mut Block,
) -> Handle<Expression> {
self.add_expression(
@@ -840,6 +911,7 @@ impl Context {
vector,
pattern: crate::SwizzleComponent::XYZW,
},
meta,
body,
)
}

View File

@@ -23,7 +23,12 @@ struct CoordComponents {
}
impl Parser {
fn add_constant_value(&mut self, scalar_kind: ScalarKind, value: u64) -> Handle<Constant> {
fn add_constant_value(
&mut self,
scalar_kind: ScalarKind,
value: u64,
meta: SourceMetadata,
) -> Handle<Constant> {
let value = match scalar_kind {
ScalarKind::Uint => ScalarValue::Uint(value),
ScalarKind::Sint => ScalarValue::Sint(value as i64),
@@ -31,11 +36,14 @@ impl Parser {
_ => unreachable!(),
};
self.module.constants.fetch_or_append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar { width: 4, value },
})
self.module.constants.fetch_or_append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar { width: 4, value },
},
meta.as_span(),
)
}
pub(crate) fn function_or_constructor_call(
@@ -68,10 +76,13 @@ impl Parser {
if expr_type.scalar_kind() == Some(ScalarKind::Bool)
&& result_scalar_kind != ScalarKind::Bool =>
{
let c0 = self.add_constant_value(result_scalar_kind, 0u64);
let c1 = self.add_constant_value(result_scalar_kind, 1u64);
let mut reject = ctx.add_expression(Expression::Constant(c0), body);
let mut accept = ctx.add_expression(Expression::Constant(c1), body);
let (condition, expr_meta) = args[0];
let c0 = self.add_constant_value(result_scalar_kind, 0u64, meta);
let c1 = self.add_constant_value(result_scalar_kind, 1u64, meta);
let mut reject =
ctx.add_expression(Expression::Constant(c0), expr_meta, body);
let mut accept =
ctx.add_expression(Expression::Constant(c1), expr_meta, body);
ctx.implicit_splat(self, &mut reject, meta, vector_size)?;
ctx.implicit_splat(self, &mut accept, meta, vector_size)?;
@@ -80,8 +91,9 @@ impl Parser {
Expression::Select {
accept,
reject,
condition: args[0].0,
condition,
},
expr_meta,
body,
);
@@ -95,7 +107,7 @@ impl Parser {
let (mut value, meta) = args[0];
ctx.implicit_conversion(self, &mut value, meta, kind, width)?;
ctx.add_expression(Expression::Splat { size, value }, body)
ctx.add_expression(Expression::Splat { size, value }, meta, body)
}
TypeInner::Scalar { kind, width } => ctx.add_expression(
Expression::As {
@@ -103,13 +115,14 @@ impl Parser {
expr: args[0].0,
convert: Some(width),
},
args[0].1,
body,
),
TypeInner::Vector { size, kind, width } => {
let mut expr = args[0].0;
if vector_size.map_or(true, |s| s != size) {
expr = ctx.vector_resize(size, expr, body);
expr = ctx.vector_resize(size, expr, args[0].1, body);
}
ctx.add_expression(
@@ -118,6 +131,7 @@ impl Parser {
expr,
convert: Some(width),
},
args[0].1,
body,
)
}
@@ -144,25 +158,33 @@ impl Parser {
// value is used to initialize all the values along the diagonal of
// the matrix; the rest are given zeros.
let mut components = Vec::with_capacity(columns as usize);
let vector_ty = self.module.types.fetch_or_append(Type {
name: None,
inner: TypeInner::Vector {
size: rows,
kind: ScalarKind::Float,
width,
let vector_ty = self.module.types.fetch_or_append(
Type {
name: None,
inner: TypeInner::Vector {
size: rows,
kind: ScalarKind::Float,
width,
},
},
});
let zero_constant =
self.module.constants.fetch_or_append(Constant {
meta.as_span(),
);
let zero_constant = self.module.constants.fetch_or_append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width,
value: ScalarValue::Float(0.0),
},
});
let zero = ctx
.add_expression(Expression::Constant(zero_constant), body);
},
meta.as_span(),
);
let zero = ctx.add_expression(
Expression::Constant(zero_constant),
meta,
body,
);
for i in 0..columns as u32 {
components.push(
@@ -177,12 +199,17 @@ impl Parser {
})
.collect(),
},
meta,
body,
),
)
}
ctx.add_expression(Expression::Compose { ty, components }, body)
ctx.add_expression(
Expression::Compose { ty, components },
meta,
body,
)
}
TypeInner::Matrix { rows: ori_rows, .. } => {
let mut components = Vec::new();
@@ -193,17 +220,22 @@ impl Parser {
base: value,
index: n,
},
meta,
body,
);
if ori_rows != rows {
vector = ctx.vector_resize(rows, vector, body);
vector = ctx.vector_resize(rows, vector, meta, body);
}
components.push(vector)
}
ctx.add_expression(Expression::Compose { ty, components }, body)
ctx.add_expression(
Expression::Compose { ty, components },
meta,
body,
)
}
_ => {
let columns =
@@ -214,6 +246,7 @@ impl Parser {
ty,
components: columns,
},
meta,
body,
)
}
@@ -224,6 +257,7 @@ impl Parser {
ty,
components: args.into_iter().map(|arg| arg.0).collect(),
},
meta,
body,
),
_ => {
@@ -262,6 +296,7 @@ impl Parser {
base: arg,
index: i,
},
meta,
body,
))
}
@@ -270,14 +305,17 @@ impl Parser {
}
}
let ty = self.module.types.fetch_or_append(Type {
name: None,
inner: TypeInner::Vector {
size: rows,
kind: ScalarKind::Float,
width,
let ty = self.module.types.fetch_or_append(
Type {
name: None,
inner: TypeInner::Vector {
size: rows,
kind: ScalarKind::Float,
width,
},
},
});
meta.as_span(),
);
for chunk in flattened.chunks(rows as usize) {
components.push(ctx.add_expression(
@@ -285,6 +323,7 @@ impl Parser {
ty,
components: Vec::from(chunk),
},
meta,
body,
))
}
@@ -302,7 +341,7 @@ impl Parser {
}
}
ctx.add_expression(Expression::Compose { ty, components }, body)
ctx.add_expression(Expression::Compose { ty, components }, meta, body)
};
Ok(Some(h))
@@ -371,6 +410,7 @@ impl Parser {
}),
depth_ref: comps.depth_ref,
},
meta,
body,
),
))
@@ -401,6 +441,7 @@ impl Parser {
level: SampleLevel::Exact(args[2].0),
depth_ref: comps.depth_ref,
},
meta,
body,
)))
} else {
@@ -437,17 +478,19 @@ impl Parser {
base,
index: size as u32 - 1,
},
meta,
body,
);
let left = if let VectorSize::Bi = size {
ctx.add_expression(Expression::AccessIndex { base, index: 0 }, body)
ctx.add_expression(Expression::AccessIndex { base, index: 0 }, meta, body)
} else {
let size = match size {
VectorSize::Tri => VectorSize::Bi,
_ => VectorSize::Tri,
};
right = ctx.add_expression(Expression::Splat { size, value: right }, body);
ctx.vector_resize(size, base, body)
right =
ctx.add_expression(Expression::Splat { size, value: right }, meta, body);
ctx.vector_resize(size, base, meta, body)
};
let coords = ctx.add_expression(
Expression::Binary {
@@ -455,6 +498,7 @@ impl Parser {
left,
right,
},
meta,
body,
);
let comps = self.coordinate_components(ctx, args[0], (coords, base_meta), body)?;
@@ -469,6 +513,7 @@ impl Parser {
level,
depth_ref: comps.depth_ref,
},
meta,
body,
)))
} else {
@@ -503,6 +548,7 @@ impl Parser {
},
depth_ref: comps.depth_ref,
},
meta,
body,
)))
} else {
@@ -526,6 +572,7 @@ impl Parser {
level: args.get(1).map(|e| e.0),
},
},
meta,
body,
)))
}
@@ -546,6 +593,7 @@ impl Parser {
array_index: comps.array_index,
index: Some(args[2].0),
},
meta,
body,
)))
} else {
@@ -599,6 +647,7 @@ impl Parser {
arg1: None,
arg2: None,
},
meta,
body,
)))
}
@@ -618,7 +667,7 @@ impl Parser {
},
_ => return Err(Error::wrong_function_args(name, 2, args.len(), meta)),
};
Ok(Some(ctx.add_expression(expr, body)))
Ok(Some(ctx.add_expression(expr, meta, body)))
}
"mod" => {
if args.len() != 2 {
@@ -636,6 +685,7 @@ impl Parser {
left,
right,
},
meta,
body,
)))
}
@@ -667,6 +717,7 @@ impl Parser {
arg1: Some(arg1),
arg2: None,
},
meta,
body,
)))
}
@@ -700,6 +751,7 @@ impl Parser {
arg1: Some(arg1),
arg2: None,
},
meta,
body,
)))
}
@@ -739,6 +791,7 @@ impl Parser {
size,
value: selector,
},
meta,
body,
)
}
@@ -771,7 +824,7 @@ impl Parser {
},
};
Ok(Some(ctx.add_expression(expr, body)))
Ok(Some(ctx.add_expression(expr, meta, body)))
}
"clamp" => {
if args.len() != 3 {
@@ -801,6 +854,7 @@ impl Parser {
arg1: Some(arg1),
arg2: Some(arg2),
},
meta,
body,
)))
}
@@ -821,6 +875,7 @@ impl Parser {
arg1: Some(args[1].0),
arg2: Some(args[2].0),
},
meta,
body,
)))
}
@@ -843,6 +898,7 @@ impl Parser {
left: args[0].0,
right: args[1].0,
},
meta,
body,
)))
}
@@ -986,22 +1042,31 @@ impl Parser {
if parameter_info.qualifier.is_lhs()
&& matches!(ctx[handle], Expression::Swizzle { .. })
{
let ty = self.module.types.fetch_or_append(Type {
name: None,
inner: TypeInner::Vector { size, kind, width },
});
let temp_var = ctx.locals.append(LocalVariable {
name: None,
ty,
init: None,
});
let ty = self.module.types.fetch_or_append(
Type {
name: None,
inner: TypeInner::Vector { size, kind, width },
},
meta.as_span(),
);
let temp_var = ctx.locals.append(
LocalVariable {
name: None,
ty,
init: None,
},
meta.as_span(),
);
let temp_expr =
ctx.add_expression(Expression::LocalVariable(temp_var), body);
ctx.add_expression(Expression::LocalVariable(temp_var), meta, body);
body.push(Statement::Store {
pointer: temp_expr,
value: handle,
});
body.push(
Statement::Store {
pointer: temp_expr,
value: handle,
},
meta.as_span(),
);
arguments.push(temp_expr);
proxy_writes.push((*expr, temp_expr));
@@ -1020,27 +1085,33 @@ impl Parser {
ctx.emit_flush(body);
let result = if !is_void {
Some(ctx.add_expression(Expression::CallResult(function), body))
Some(ctx.add_expression(Expression::CallResult(function), meta, body))
} else {
None
};
body.push(crate::Statement::Call {
function,
arguments,
result,
});
body.push(
crate::Statement::Call {
function,
arguments,
result,
},
meta.as_span(),
);
ctx.emit_start();
for (tgt, pointer) in proxy_writes {
let value = ctx.add_expression(Expression::Load { pointer }, body);
let value = ctx.add_expression(Expression::Load { pointer }, meta, body);
let target = ctx.lower_expect_inner(stmt, self, tgt, true, body)?.0;
ctx.emit_flush(body);
body.push(Statement::Store {
pointer: target,
value,
});
body.push(
Statement::Store {
pointer: target,
value,
},
meta.as_span(),
);
ctx.emit_start();
}
@@ -1067,6 +1138,7 @@ impl Parser {
fun,
argument: args[0].0,
},
meta,
body,
))
}
@@ -1135,7 +1207,7 @@ impl Parser {
return;
}
let handle = module.functions.append(function);
let handle = module.functions.append(function, meta.as_span());
declarations.push(FunctionDeclaration {
parameters,
parameters_info,
@@ -1195,7 +1267,7 @@ impl Parser {
});
}
let handle = module.functions.append(function);
let handle = module.functions.append(function, meta.as_span());
declarations.push(FunctionDeclaration {
parameters,
parameters_info,
@@ -1208,7 +1280,7 @@ impl Parser {
pub(crate) fn add_entry_point(
&mut self,
function: Handle<Function>,
mut global_init_body: Block,
global_init_body: Block,
mut expressions: Arena<Expression>,
) {
let mut arguments = Vec::new();
@@ -1235,19 +1307,23 @@ impl Parser {
binding: Some(arg.binding.clone()),
});
let pointer = expressions.append(Expression::GlobalVariable(arg.handle));
let value = expressions.append(Expression::FunctionArgument(idx));
let pointer =
expressions.append(Expression::GlobalVariable(arg.handle), Default::default());
let value = expressions.append(Expression::FunctionArgument(idx), Default::default());
body.push(Statement::Store { pointer, value });
body.push(Statement::Store { pointer, value }, Default::default());
}
body.append(&mut global_init_body);
body.extend_block(global_init_body);
body.push(Statement::Call {
function,
arguments: Vec::new(),
result: None,
});
body.push(
Statement::Call {
function,
arguments: Vec::new(),
result: None,
},
Default::default(),
);
let mut span = 0;
let mut members = Vec::new();
@@ -1269,33 +1345,44 @@ impl Parser {
span += self.module.types[ty].inner.span(&self.module.constants);
let pointer = expressions.append(Expression::GlobalVariable(arg.handle));
let pointer =
expressions.append(Expression::GlobalVariable(arg.handle), Default::default());
let len = expressions.len();
let load = expressions.append(Expression::Load { pointer });
body.push(Statement::Emit(expressions.range_from(len)));
let load = expressions.append(Expression::Load { pointer }, Default::default());
body.push(
Statement::Emit(expressions.range_from(len)),
Default::default(),
);
components.push(load)
}
let (ty, value) = if !components.is_empty() {
let ty = self.module.types.append(Type {
name: None,
inner: TypeInner::Struct {
top_level: false,
members,
span,
let ty = self.module.types.append(
Type {
name: None,
inner: TypeInner::Struct {
top_level: false,
members,
span,
},
},
});
Default::default(),
);
let len = expressions.len();
let res = expressions.append(Expression::Compose { ty, components });
body.push(Statement::Emit(expressions.range_from(len)));
let res =
expressions.append(Expression::Compose { ty, components }, Default::default());
body.push(
Statement::Emit(expressions.range_from(len)),
Default::default(),
);
(Some(ty), Some(res))
} else {
(None, None)
};
body.push(Statement::Return { value });
body.push(Statement::Return { value }, Default::default());
self.module.entry_points.push(EntryPoint {
name: "main".to_string(),
@@ -1344,13 +1431,14 @@ impl Parser {
let coordinate = match (image_size, coord_size) {
(Some(size), Some(coord_s)) if size != coord_s => {
ctx.vector_resize(size, coord, body)
ctx.vector_resize(size, coord, coord_meta, body)
}
(None, Some(_)) => ctx.add_expression(
Expression::AccessIndex {
base: coord,
index: 0,
},
coord_meta,
body,
),
_ => coord,
@@ -1362,7 +1450,11 @@ impl Parser {
false => image_size.map_or(0, |s| s as u32),
};
Some(ctx.add_expression(Expression::AccessIndex { base: coord, index }, body))
Some(ctx.add_expression(
Expression::AccessIndex { base: coord, index },
coord_meta,
body,
))
}
_ => None,
};
@@ -1370,7 +1462,11 @@ impl Parser {
true => {
let index = image_size.map_or(0, |s| s as u32);
Some(ctx.add_expression(Expression::AccessIndex { base: coord, index }, body))
Some(ctx.add_expression(
Expression::AccessIndex { base: coord, index },
coord_meta,
body,
))
}
false => None,
};
@@ -1423,14 +1519,17 @@ fn sampled_to_depth(
arrayed,
} => match class {
ImageClass::Sampled { multi, .. } => {
*ty = module.types.fetch_or_append(Type {
name: None,
inner: TypeInner::Image {
dim,
arrayed,
class: ImageClass::Depth { multi },
*ty = module.types.fetch_or_append(
Type {
name: None,
inner: TypeInner::Image {
dim,
arrayed,
class: ImageClass::Depth { multi },
},
},
})
module.types.get_span(*ty).clone(),
)
}
ImageClass::Depth { .. } => {}
_ => errors.push(Error {

View File

@@ -84,14 +84,18 @@ pub fn calculate_offset(
crate::ArraySize::Dynamic => stride,
};
ty = types.fetch_or_append(Type {
name,
inner: TypeInner::Array {
base: info.ty,
size,
stride,
let ty_span = types.get_span(ty).clone();
ty = types.fetch_or_append(
Type {
name,
inner: TypeInner::Array {
base: info.ty,
size,
stride,
},
},
});
ty_span,
);
(align, span)
}
@@ -138,14 +142,18 @@ pub fn calculate_offset(
span += info.span;
}
ty = types.fetch_or_append(Type {
name,
inner: TypeInner::Struct {
top_level,
members,
span,
let ty_span = types.get_span(ty).clone();
ty = types.fetch_or_append(
Type {
name,
inner: TypeInner::Struct {
top_level,
members,
span,
},
},
});
ty_span,
);
(align, span)
}

View File

@@ -393,7 +393,7 @@ impl<'ctx> DeclarationContext<'ctx> {
GlobalOrConstant::Global(handle) => Expression::GlobalVariable(handle),
GlobalOrConstant::Constant(handle) => Expression::Constant(handle),
};
Ok(self.ctx.add_expression(expr, self.body))
Ok(self.ctx.add_expression(expr, meta, self.body))
}
false => parser.add_local_var(self.ctx, self.body, decl),
}

View File

@@ -25,7 +25,10 @@ impl<'source> ParsingContext<'source> {
global_ctx: &mut Context,
global_body: &mut Block,
) -> Result<()> {
if !self.parse_declaration(parser, global_ctx, global_body, true)? {
if self
.parse_declaration(parser, global_ctx, global_body, true)?
.is_none()
{
let token = self.bump(parser)?;
match token.value {
TokenValue::Semicolon if parser.meta.version == 460 => Ok(()),
@@ -94,7 +97,7 @@ impl<'source> ParsingContext<'source> {
}
Ok((
ctx.add_expression(Expression::Compose { ty, components }, body),
ctx.add_expression(Expression::Compose { ty, components }, meta, body),
meta,
))
} else {
@@ -173,7 +176,7 @@ impl<'source> ParsingContext<'source> {
// NOTE: unlike other parse methods this one doesn't expect an array specifier and
// returns Ok(None) rather than an error if there is not one
let array_specifier = self.parse_array_specifier(parser)?;
let ty = parser.maybe_array(ty, array_specifier);
let ty = parser.maybe_array(ty, meta, array_specifier);
let init = self
.bump_if(parser, TokenValue::Assign)
@@ -203,7 +206,8 @@ impl<'source> ParsingContext<'source> {
if let Some((value, _)) = init.filter(|_| maybe_constant.is_none()) {
ctx.flush_expressions();
ctx.body.push(Statement::Store { pointer, value });
ctx.body
.push(Statement::Store { pointer, value }, meta.as_span());
}
let token = self.bump(parser)?;
@@ -232,7 +236,7 @@ impl<'source> ParsingContext<'source> {
ctx: &mut Context,
body: &mut Block,
external: bool,
) -> Result<bool> {
) -> Result<Option<SourceMetadata>> {
//declaration:
// function_prototype SEMICOLON
//
@@ -276,7 +280,7 @@ impl<'source> ParsingContext<'source> {
// This branch handles function prototypes
parser.add_prototype(context, name, result, meta);
Ok(true)
Ok(Some(meta))
}
TokenValue::LeftBrace if external => {
// This branch handles function definitions
@@ -284,11 +288,16 @@ impl<'source> ParsingContext<'source> {
// only happens if external is also true
// parse the body
self.parse_compound_statement(parser, &mut context, &mut body)?;
self.parse_compound_statement(
token.meta,
parser,
&mut context,
&mut body,
)?;
parser.add_function(context, name, result, body, meta);
Ok(true)
Ok(Some(meta))
}
_ if external => Err(Error {
kind: ErrorKind::InvalidToken(
@@ -338,7 +347,7 @@ impl<'source> ParsingContext<'source> {
})
}
Ok(true)
Ok(Some(meta))
} else {
// This branch handles struct definitions and modifiers like
// ```glsl
@@ -356,6 +365,7 @@ impl<'source> ParsingContext<'source> {
ty_name,
token.meta,
)
.map(Some)
} else {
//TODO: declaration
// type_qualifier IDENTIFIER SEMICOLON
@@ -367,7 +377,9 @@ impl<'source> ParsingContext<'source> {
}
}
TokenValue::Semicolon => {
let mut meta_all = token.meta;
for &(ref qualifier, meta) in qualifiers.iter() {
meta_all = meta_all.union(&meta);
match *qualifier {
TypeQualifier::WorkGroupSize(i, value) => {
parser.meta.workgroup_size[i] = value
@@ -391,7 +403,7 @@ impl<'source> ParsingContext<'source> {
}
}
Ok(true)
Ok(Some(meta_all))
}
_ => Err(Error {
kind: ErrorKind::InvalidToken(
@@ -447,9 +459,9 @@ impl<'source> ParsingContext<'source> {
self.expect(parser, TokenValue::Semicolon)?;
Ok(true)
Ok(Some(meta))
}
_ => Ok(false),
_ => Ok(None),
}
}
}
@@ -461,8 +473,8 @@ impl<'source> ParsingContext<'source> {
body: &mut Block,
qualifiers: &[(TypeQualifier, SourceMetadata)],
ty_name: String,
mut meta: SourceMetadata,
) -> Result<bool> {
meta: SourceMetadata,
) -> Result<SourceMetadata> {
let mut storage = None;
let mut layout = None;
@@ -486,29 +498,24 @@ impl<'source> ParsingContext<'source> {
let span = self.parse_struct_declaration_list(parser, &mut members, layout)?;
self.expect(parser, TokenValue::RightBrace)?;
let mut ty = parser.module.types.append(Type {
name: Some(ty_name),
inner: TypeInner::Struct {
top_level: true,
members: members.clone(),
span,
let mut ty = parser.module.types.append(
Type {
name: Some(ty_name),
inner: TypeInner::Struct {
top_level: true,
members: members.clone(),
span,
},
},
});
Default::default(),
);
let token = self.bump(parser)?;
let name = match token.value {
TokenValue::Semicolon => None,
TokenValue::Identifier(name) => {
if let Some(size) = self.parse_array_specifier(parser)? {
ty = parser.module.types.fetch_or_append(Type {
name: None,
inner: TypeInner::Array {
base: ty,
size,
stride: parser.module.types[ty].inner.span(&parser.module.constants),
},
});
}
let array_specifier = self.parse_array_specifier(parser)?;
ty = parser.maybe_array(ty, token.meta, array_specifier);
self.expect(parser, TokenValue::Semicolon)?;
@@ -524,7 +531,6 @@ impl<'source> ParsingContext<'source> {
})
}
};
meta = meta.union(&token.meta);
let global = parser.add_global_var(
ctx,
@@ -556,7 +562,7 @@ impl<'source> ParsingContext<'source> {
parser.global_variables.push((k, lookup));
}
Ok(true)
Ok(meta)
}
// TODO: Accept layout arguments
@@ -578,7 +584,7 @@ impl<'source> ParsingContext<'source> {
meta = meta.union(&end_meta);
let array_specifier = self.parse_array_specifier(parser)?;
let ty = parser.maybe_array(ty, array_specifier);
let ty = parser.maybe_array(ty, meta, array_specifier);
self.expect(parser, TokenValue::Semicolon)?;

View File

@@ -59,16 +59,22 @@ impl<'source> ParsingContext<'source> {
}
};
let handle = parser.module.constants.fetch_or_append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar { width, value },
});
let handle = parser.module.constants.fetch_or_append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar { width, value },
},
token.meta.as_span(),
);
Ok(stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Constant(handle),
meta: token.meta,
}))
Ok(stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::Constant(handle),
meta: token.meta,
},
Default::default(),
))
}
pub fn parse_function_call_args(
@@ -133,7 +139,7 @@ impl<'source> ParsingContext<'source> {
meta,
}
} else {
let var = match parser.lookup_variable(ctx, body, &name) {
let var = match parser.lookup_variable(ctx, body, &name, meta) {
Some(var) => var,
None => {
return Err(Error {
@@ -149,13 +155,17 @@ impl<'source> ParsingContext<'source> {
}
};
stmt.hir_exprs.append(expr)
stmt.hir_exprs.append(expr, Default::default())
}
TokenValue::TypeName(_) => {
let Token { value, mut meta } = self.bump(parser)?;
let Token {
value,
meta: name_meta,
} = self.bump(parser)?;
let mut meta = name_meta;
let mut handle = if let TokenValue::TypeName(ty) = value {
parser.module.types.fetch_or_append(ty)
parser.module.types.fetch_or_append(ty, name_meta.as_span())
} else {
unreachable!()
};
@@ -165,7 +175,7 @@ impl<'source> ParsingContext<'source> {
self.expect(parser, TokenValue::LeftParen)?;
let args = self.parse_function_call_args(parser, ctx, stmt, body, &mut meta)?;
if let Some(array_size) = maybe_size {
if let Some((array_size, array_meta)) = maybe_size {
let stride = parser.module.types[handle]
.inner
.span(&parser.module.constants);
@@ -173,36 +183,45 @@ impl<'source> ParsingContext<'source> {
let size = match array_size {
ArraySize::Constant(size) => ArraySize::Constant(size),
ArraySize::Dynamic => {
let constant = parser.module.constants.fetch_or_append(Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Sint(args.len() as i64),
let constant = parser.module.constants.fetch_or_append(
Constant {
name: None,
specialization: None,
inner: ConstantInner::Scalar {
width: 4,
value: ScalarValue::Sint(args.len() as i64),
},
},
});
meta.as_span(),
);
ArraySize::Constant(constant)
}
};
handle = parser.module.types.fetch_or_append(Type {
name: None,
inner: TypeInner::Array {
base: handle,
size,
stride,
handle = parser.module.types.fetch_or_append(
Type {
name: None,
inner: TypeInner::Array {
base: handle,
size,
stride,
},
},
})
name_meta.union(&array_meta).as_span(),
);
}
stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Call(FunctionCall {
kind: FunctionCallKind::TypeConstructor(handle),
args,
}),
meta,
})
stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::Call(FunctionCall {
kind: FunctionCallKind::TypeConstructor(handle),
args,
}),
meta,
},
Default::default(),
)
}
_ => self.parse_primary(parser, ctx, stmt, body)?,
};
@@ -219,38 +238,50 @@ impl<'source> ParsingContext<'source> {
let index = self.parse_expression(parser, ctx, stmt, body)?;
let end_meta = self.expect(parser, TokenValue::RightBracket)?.meta;
base = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Access { base, index },
meta: meta.union(&end_meta),
})
base = stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::Access { base, index },
meta: meta.union(&end_meta),
},
Default::default(),
)
}
TokenValue::Dot => {
let (field, end_meta) = self.expect_ident(parser)?;
base = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Select { base, field },
meta: meta.union(&end_meta),
})
base = stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::Select { base, field },
meta: meta.union(&end_meta),
},
Default::default(),
)
}
TokenValue::Increment => {
base = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::IncDec {
increment: true,
postfix: true,
expr: base,
base = stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::IncDec {
increment: true,
postfix: true,
expr: base,
},
meta,
},
meta,
})
Default::default(),
)
}
TokenValue::Decrement => {
base = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::IncDec {
increment: false,
postfix: true,
expr: base,
base = stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::IncDec {
increment: false,
postfix: true,
expr: base,
},
meta,
},
meta,
})
Default::default(),
)
}
_ => unreachable!(),
}
@@ -286,28 +317,34 @@ impl<'source> ParsingContext<'source> {
_ => return Ok(expr),
};
stmt.hir_exprs.append(HirExpr {
kind,
meta: meta.union(&end_meta),
})
stmt.hir_exprs.append(
HirExpr {
kind,
meta: meta.union(&end_meta),
},
Default::default(),
)
}
TokenValue::Increment | TokenValue::Decrement => {
let Token { value, meta } = self.bump(parser)?;
let expr = self.parse_unary(parser, ctx, stmt, body)?;
stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::IncDec {
increment: match value {
TokenValue::Increment => true,
TokenValue::Decrement => false,
_ => unreachable!(),
stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::IncDec {
increment: match value {
TokenValue::Increment => true,
TokenValue::Decrement => false,
_ => unreachable!(),
},
postfix: false,
expr,
},
postfix: false,
expr,
meta,
},
meta,
})
Default::default(),
)
}
_ => self.parse_postfix(parser, ctx, stmt, body)?,
})
@@ -337,35 +374,38 @@ impl<'source> ParsingContext<'source> {
let right = self.parse_binary(parser, ctx, stmt, body, None, r_bp)?;
let end_meta = stmt.hir_exprs[right].meta;
left = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Binary {
left,
op: match value {
TokenValue::LogicalOr => BinaryOperator::LogicalOr,
TokenValue::LogicalXor => BinaryOperator::NotEqual,
TokenValue::LogicalAnd => BinaryOperator::LogicalAnd,
TokenValue::VerticalBar => BinaryOperator::InclusiveOr,
TokenValue::Caret => BinaryOperator::ExclusiveOr,
TokenValue::Ampersand => BinaryOperator::And,
TokenValue::Equal => BinaryOperator::Equal,
TokenValue::NotEqual => BinaryOperator::NotEqual,
TokenValue::GreaterEqual => BinaryOperator::GreaterEqual,
TokenValue::LessEqual => BinaryOperator::LessEqual,
TokenValue::LeftAngle => BinaryOperator::Less,
TokenValue::RightAngle => BinaryOperator::Greater,
TokenValue::LeftShift => BinaryOperator::ShiftLeft,
TokenValue::RightShift => BinaryOperator::ShiftRight,
TokenValue::Plus => BinaryOperator::Add,
TokenValue::Dash => BinaryOperator::Subtract,
TokenValue::Star => BinaryOperator::Multiply,
TokenValue::Slash => BinaryOperator::Divide,
TokenValue::Percent => BinaryOperator::Modulo,
_ => unreachable!(),
left = stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::Binary {
left,
op: match value {
TokenValue::LogicalOr => BinaryOperator::LogicalOr,
TokenValue::LogicalXor => BinaryOperator::NotEqual,
TokenValue::LogicalAnd => BinaryOperator::LogicalAnd,
TokenValue::VerticalBar => BinaryOperator::InclusiveOr,
TokenValue::Caret => BinaryOperator::ExclusiveOr,
TokenValue::Ampersand => BinaryOperator::And,
TokenValue::Equal => BinaryOperator::Equal,
TokenValue::NotEqual => BinaryOperator::NotEqual,
TokenValue::GreaterEqual => BinaryOperator::GreaterEqual,
TokenValue::LessEqual => BinaryOperator::LessEqual,
TokenValue::LeftAngle => BinaryOperator::Less,
TokenValue::RightAngle => BinaryOperator::Greater,
TokenValue::LeftShift => BinaryOperator::ShiftLeft,
TokenValue::RightShift => BinaryOperator::ShiftRight,
TokenValue::Plus => BinaryOperator::Add,
TokenValue::Dash => BinaryOperator::Subtract,
TokenValue::Star => BinaryOperator::Multiply,
TokenValue::Slash => BinaryOperator::Divide,
TokenValue::Percent => BinaryOperator::Modulo,
_ => unreachable!(),
},
right,
},
right,
meta: start_meta.union(&end_meta),
},
meta: start_meta.union(&end_meta),
})
Default::default(),
)
}
Ok(left)
@@ -388,14 +428,17 @@ impl<'source> ParsingContext<'source> {
let reject = self.parse_assignment(parser, ctx, stmt, body)?;
let end_meta = stmt.hir_exprs[reject].meta;
condition = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Conditional {
condition,
accept,
reject,
condition = stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::Conditional {
condition,
accept,
reject,
},
meta: start_meta.union(&end_meta),
},
meta: start_meta.union(&end_meta),
})
Default::default(),
)
}
Ok(condition)
@@ -417,10 +460,13 @@ impl<'source> ParsingContext<'source> {
let value = self.parse_assignment(parser, ctx, stmt, body)?;
let end_meta = stmt.hir_exprs[value].meta;
stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Assign { tgt, value },
meta: start_meta.union(&end_meta),
})
stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::Assign { tgt, value },
meta: start_meta.union(&end_meta),
},
Default::default(),
)
}
TokenValue::OrAssign
| TokenValue::AndAssign
@@ -436,31 +482,37 @@ impl<'source> ParsingContext<'source> {
let right = self.parse_assignment(parser, ctx, stmt, body)?;
let end_meta = stmt.hir_exprs[right].meta;
let value = stmt.hir_exprs.append(HirExpr {
meta: start_meta.union(&end_meta),
kind: HirExprKind::Binary {
left: tgt,
op: match token.value {
TokenValue::OrAssign => BinaryOperator::InclusiveOr,
TokenValue::AndAssign => BinaryOperator::And,
TokenValue::AddAssign => BinaryOperator::Add,
TokenValue::DivAssign => BinaryOperator::Divide,
TokenValue::ModAssign => BinaryOperator::Modulo,
TokenValue::SubAssign => BinaryOperator::Subtract,
TokenValue::MulAssign => BinaryOperator::Multiply,
TokenValue::LeftShiftAssign => BinaryOperator::ShiftLeft,
TokenValue::RightShiftAssign => BinaryOperator::ShiftRight,
TokenValue::XorAssign => BinaryOperator::ExclusiveOr,
_ => unreachable!(),
let value = stmt.hir_exprs.append(
HirExpr {
meta: start_meta.union(&end_meta),
kind: HirExprKind::Binary {
left: tgt,
op: match token.value {
TokenValue::OrAssign => BinaryOperator::InclusiveOr,
TokenValue::AndAssign => BinaryOperator::And,
TokenValue::AddAssign => BinaryOperator::Add,
TokenValue::DivAssign => BinaryOperator::Divide,
TokenValue::ModAssign => BinaryOperator::Modulo,
TokenValue::SubAssign => BinaryOperator::Subtract,
TokenValue::MulAssign => BinaryOperator::Multiply,
TokenValue::LeftShiftAssign => BinaryOperator::ShiftLeft,
TokenValue::RightShiftAssign => BinaryOperator::ShiftRight,
TokenValue::XorAssign => BinaryOperator::ExclusiveOr,
_ => unreachable!(),
},
right,
},
right,
},
});
Default::default(),
);
stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Assign { tgt, value },
meta: start_meta.union(&end_meta),
})
stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::Assign { tgt, value },
meta: start_meta.union(&end_meta),
},
Default::default(),
)
}
_ => self.parse_conditional(parser, ctx, stmt, body, Some(tgt))?,
})

View File

@@ -1,3 +1,4 @@
use crate::front::glsl::SourceMetadata;
use crate::{
front::glsl::{
ast::ParameterQualifier,
@@ -38,7 +39,7 @@ impl<'source> ParsingContext<'source> {
parser: &mut Parser,
ctx: &mut Context,
body: &mut Block,
) -> Result<()> {
) -> Result<Option<SourceMetadata>> {
// TODO: This prevents snippets like the following from working
// ```glsl
// vec4(1.0);
@@ -47,55 +48,60 @@ impl<'source> ParsingContext<'source> {
// declarations and since this statement is very unlikely and most
// likely an error, for now we don't support it
if self.peek_type_name(parser) || self.peek_type_qualifier(parser) {
self.parse_declaration(parser, ctx, body, false)?;
return Ok(());
return self.parse_declaration(parser, ctx, body, false);
}
match self.expect_peek(parser)?.value {
let new_break = || {
let mut block = Block::new();
block.push(Statement::Break, crate::Span::Unknown);
block
};
let &Token { ref value, meta } = self.expect_peek(parser)?;
let meta_rest = match *value {
TokenValue::Continue => {
self.bump(parser)?;
body.push(Statement::Continue);
self.expect(parser, TokenValue::Semicolon)?;
body.push(Statement::Continue, self.bump(parser)?.meta.as_span());
self.expect(parser, TokenValue::Semicolon)?.meta
}
TokenValue::Break => {
self.bump(parser)?;
body.push(Statement::Break);
self.expect(parser, TokenValue::Semicolon)?;
body.push(Statement::Break, self.bump(parser)?.meta.as_span());
self.expect(parser, TokenValue::Semicolon)?.meta
}
TokenValue::Return => {
self.bump(parser)?;
let value = match self.expect_peek(parser)?.value {
TokenValue::Semicolon => {
self.bump(parser)?;
None
}
let (value, meta) = match self.expect_peek(parser)?.value {
TokenValue::Semicolon => (None, self.bump(parser)?.meta),
_ => {
// TODO: Implicit conversions
let mut stmt = ctx.stmt_ctx();
let expr = self.parse_expression(parser, ctx, &mut stmt, body)?;
self.expect(parser, TokenValue::Semicolon)?;
Some(ctx.lower_expect(stmt, parser, expr, false, body)?.0)
let (handle, meta) = ctx.lower_expect(stmt, parser, expr, false, body)?;
(Some(handle), meta)
}
};
ctx.emit_flush(body);
ctx.emit_start();
body.push(Statement::Return { value })
body.push(Statement::Return { value }, meta.as_span());
meta
}
TokenValue::Discard => {
self.bump(parser)?;
body.push(Statement::Kill);
self.expect(parser, TokenValue::Semicolon)?;
body.push(Statement::Kill, self.bump(parser)?.meta.as_span());
self.expect(parser, TokenValue::Semicolon)?.meta
}
TokenValue::If => {
self.bump(parser)?;
let mut meta = self.bump(parser)?.meta;
self.expect(parser, TokenValue::LeftParen)?;
let condition = {
let mut stmt = ctx.stmt_ctx();
let expr = self.parse_expression(parser, ctx, &mut stmt, body)?;
ctx.lower_expect(stmt, parser, expr, false, body)?.0
let (handle, more_meta) = ctx.lower_expect(stmt, parser, expr, false, body)?;
meta = meta.union(&more_meta);
handle
};
self.expect(parser, TokenValue::RightParen)?;
@@ -103,21 +109,30 @@ impl<'source> ParsingContext<'source> {
ctx.emit_start();
let mut accept = Block::new();
self.parse_statement(parser, ctx, &mut accept)?;
if let Some(more_meta) = self.parse_statement(parser, ctx, &mut accept)? {
meta = meta.union(&more_meta)
}
let mut reject = Block::new();
if self.bump_if(parser, TokenValue::Else).is_some() {
self.parse_statement(parser, ctx, &mut reject)?;
if let Some(more_meta) = self.parse_statement(parser, ctx, &mut reject)? {
meta = meta.union(&more_meta);
}
}
body.push(Statement::If {
condition,
accept,
reject,
});
body.push(
Statement::If {
condition,
accept,
reject,
},
meta.as_span(),
);
meta
}
TokenValue::Switch => {
self.bump(parser)?;
let start_meta = self.bump(parser)?.meta;
let end_meta;
self.expect(parser, TokenValue::LeftParen)?;
// TODO: Implicit conversions
@@ -177,7 +192,9 @@ impl<'source> ParsingContext<'source> {
TokenValue::Case
| TokenValue::Default
| TokenValue::RightBrace => break,
_ => self.parse_statement(parser, ctx, &mut body)?,
_ => {
self.parse_statement(parser, ctx, &mut body)?;
}
}
}
@@ -186,7 +203,7 @@ impl<'source> ParsingContext<'source> {
for (i, stmt) in body.iter().enumerate() {
if let Statement::Break = *stmt {
fall_through = false;
body.drain(i..);
body.cull(i..);
break;
}
}
@@ -214,19 +231,21 @@ impl<'source> ParsingContext<'source> {
loop {
match self.expect_peek(parser)?.value {
TokenValue::Case | TokenValue::RightBrace => break,
_ => self.parse_statement(parser, ctx, &mut default)?,
_ => {
self.parse_statement(parser, ctx, &mut default)?;
}
}
}
for (i, stmt) in default.iter().enumerate() {
if let Statement::Break = *stmt {
default.drain(i..);
default.cull(i..);
break;
}
}
}
TokenValue::RightBrace => {
self.bump(parser)?;
end_meta = self.bump(parser)?.meta;
break;
}
_ => {
@@ -246,51 +265,67 @@ impl<'source> ParsingContext<'source> {
}
}
body.push(Statement::Switch {
selector,
cases,
default,
});
let meta = start_meta.union(&end_meta);
body.push(
Statement::Switch {
selector,
cases,
default,
},
meta.as_span(),
);
meta
}
TokenValue::While => {
self.bump(parser)?;
let meta = self.bump(parser)?.meta;
let mut loop_body = Block::new();
let mut stmt = ctx.stmt_ctx();
self.expect(parser, TokenValue::LeftParen)?;
let root = self.parse_expression(parser, ctx, &mut stmt, &mut loop_body)?;
self.expect(parser, TokenValue::RightParen)?;
let meta = meta.union(&self.expect(parser, TokenValue::RightParen)?.meta);
let expr = ctx
.lower_expect(stmt, parser, root, false, &mut loop_body)?
.0;
let (expr, expr_meta) =
ctx.lower_expect(stmt, parser, root, false, &mut loop_body)?;
let condition = ctx.add_expression(
Expression::Unary {
op: UnaryOperator::Not,
expr,
},
expr_meta,
&mut loop_body,
);
ctx.emit_flush(&mut loop_body);
ctx.emit_start();
loop_body.push(Statement::If {
condition,
accept: vec![Statement::Break],
reject: Block::new(),
});
loop_body.push(
Statement::If {
condition,
accept: new_break(),
reject: Block::new(),
},
crate::Span::Unknown,
);
self.parse_statement(parser, ctx, &mut loop_body)?;
let mut meta = meta.union(&expr_meta);
body.push(Statement::Loop {
body: loop_body,
continuing: Block::new(),
})
if let Some(body_meta) = self.parse_statement(parser, ctx, &mut loop_body)? {
meta = meta.union(&body_meta);
}
body.push(
Statement::Loop {
body: loop_body,
continuing: Block::new(),
},
meta.as_span(),
);
meta
}
TokenValue::Do => {
self.bump(parser)?;
let start_meta = self.bump(parser)?.meta;
let mut loop_body = Block::new();
self.parse_statement(parser, ctx, &mut loop_body)?;
@@ -300,35 +335,44 @@ impl<'source> ParsingContext<'source> {
self.expect(parser, TokenValue::While)?;
self.expect(parser, TokenValue::LeftParen)?;
let root = self.parse_expression(parser, ctx, &mut stmt, &mut loop_body)?;
self.expect(parser, TokenValue::RightParen)?;
let end_meta = self.expect(parser, TokenValue::RightParen)?.meta;
let expr = ctx
.lower_expect(stmt, parser, root, false, &mut loop_body)?
.0;
let meta = start_meta.union(&end_meta);
let (expr, expr_meta) =
ctx.lower_expect(stmt, parser, root, false, &mut loop_body)?;
let condition = ctx.add_expression(
Expression::Unary {
op: UnaryOperator::Not,
expr,
},
expr_meta,
&mut loop_body,
);
ctx.emit_flush(&mut loop_body);
ctx.emit_start();
loop_body.push(Statement::If {
condition,
accept: vec![Statement::Break],
reject: Block::new(),
});
loop_body.push(
Statement::If {
condition,
accept: new_break(),
reject: Block::new(),
},
crate::Span::Unknown,
);
body.push(Statement::Loop {
body: loop_body,
continuing: Block::new(),
})
body.push(
Statement::Loop {
body: loop_body,
continuing: Block::new(),
},
meta.as_span(),
);
meta
}
TokenValue::For => {
self.bump(parser)?;
let meta = self.bump(parser)?.meta;
ctx.push_scope();
self.expect(parser, TokenValue::LeftParen)?;
@@ -347,54 +391,60 @@ impl<'source> ParsingContext<'source> {
let (mut block, mut continuing) = (Block::new(), Block::new());
if self.bump_if(parser, TokenValue::Semicolon).is_none() {
let expr = if self.peek_type_name(parser) || self.peek_type_qualifier(parser) {
let qualifiers = self.parse_type_qualifiers(parser)?;
let (ty, meta) = self.parse_type_non_void(parser)?;
let name = self.expect_ident(parser)?.0;
let (expr, expr_meta) =
if self.peek_type_name(parser) || self.peek_type_qualifier(parser) {
let qualifiers = self.parse_type_qualifiers(parser)?;
let (ty, meta) = self.parse_type_non_void(parser)?;
let name = self.expect_ident(parser)?.0;
self.expect(parser, TokenValue::Assign)?;
self.expect(parser, TokenValue::Assign)?;
let (value, end_meta) =
self.parse_initializer(parser, ty, ctx, &mut block)?;
let (value, end_meta) =
self.parse_initializer(parser, ty, ctx, &mut block)?;
let meta = meta.union(&end_meta);
let decl = VarDeclaration {
qualifiers: &qualifiers,
ty,
name: Some(name),
init: None,
meta: meta.union(&end_meta),
let decl = VarDeclaration {
qualifiers: &qualifiers,
ty,
name: Some(name),
init: None,
meta,
};
let pointer = parser.add_local_var(ctx, &mut block, decl)?;
ctx.emit_flush(&mut block);
ctx.emit_start();
block.push(Statement::Store { pointer, value }, meta.as_span());
(value, end_meta)
} else {
let mut stmt = ctx.stmt_ctx();
let root = self.parse_expression(parser, ctx, &mut stmt, &mut block)?;
ctx.lower_expect(stmt, parser, root, false, &mut block)?
};
let pointer = parser.add_local_var(ctx, &mut block, decl)?;
ctx.emit_flush(&mut block);
ctx.emit_start();
block.push(Statement::Store { pointer, value });
value
} else {
let mut stmt = ctx.stmt_ctx();
let root = self.parse_expression(parser, ctx, &mut stmt, &mut block)?;
ctx.lower_expect(stmt, parser, root, false, &mut block)?.0
};
let condition = ctx.add_expression(
Expression::Unary {
op: UnaryOperator::Not,
expr,
},
expr_meta,
&mut block,
);
ctx.emit_flush(&mut block);
ctx.emit_start();
block.push(Statement::If {
condition,
accept: vec![Statement::Break],
reject: Block::new(),
});
block.push(
Statement::If {
condition,
accept: new_break(),
reject: Block::new(),
},
crate::Span::Unknown,
);
self.expect(parser, TokenValue::Semicolon)?;
}
@@ -409,27 +459,36 @@ impl<'source> ParsingContext<'source> {
}
}
self.expect(parser, TokenValue::RightParen)?;
let mut meta = meta.union(&self.expect(parser, TokenValue::RightParen)?.meta);
self.parse_statement(parser, ctx, &mut block)?;
if let Some(stmt_meta) = self.parse_statement(parser, ctx, &mut block)? {
meta = meta.union(&stmt_meta);
}
body.push(Statement::Loop {
body: block,
continuing,
});
body.push(
Statement::Loop {
body: block,
continuing,
},
meta.as_span(),
);
ctx.remove_current_scope();
meta
}
TokenValue::LeftBrace => {
self.bump(parser)?;
let meta = self.bump(parser)?.meta;
let mut block = Block::new();
ctx.push_scope();
self.parse_compound_statement(parser, ctx, &mut block)?;
let meta = self.parse_compound_statement(meta, parser, ctx, &mut block)?;
ctx.remove_current_scope();
body.push(Statement::Block(block));
body.push(Statement::Block(block), meta.as_span());
meta
}
TokenValue::Plus
| TokenValue::Dash
@@ -444,32 +503,37 @@ impl<'source> ParsingContext<'source> {
let mut stmt = ctx.stmt_ctx();
let expr = self.parse_expression(parser, ctx, &mut stmt, body)?;
ctx.lower(stmt, parser, expr, false, body)?;
self.expect(parser, TokenValue::Semicolon)?;
self.expect(parser, TokenValue::Semicolon)?.meta
}
TokenValue::Semicolon => {
self.bump(parser)?;
}
_ => {}
}
TokenValue::Semicolon => self.bump(parser)?.meta,
_ => meta,
};
Ok(())
Ok(Some(meta.union(&meta_rest)))
}
pub fn parse_compound_statement(
&mut self,
mut meta: SourceMetadata,
parser: &mut Parser,
ctx: &mut Context,
body: &mut Block,
) -> Result<()> {
) -> Result<SourceMetadata> {
loop {
if self.bump_if(parser, TokenValue::RightBrace).is_some() {
if let Some(Token {
meta: brace_meta, ..
}) = self.bump_if(parser, TokenValue::RightBrace)
{
meta = meta.union(&brace_meta);
break;
}
self.parse_statement(parser, ctx, body)?;
if let Some(stmt_meta) = self.parse_statement(parser, ctx, body)? {
meta = meta.union(&stmt_meta);
}
}
Ok(())
Ok(meta)
}
pub fn parse_function_args(
@@ -490,12 +554,12 @@ impl<'source> ParsingContext<'source> {
continue;
}
TokenValue::Identifier(_) => {
let name = self.expect_ident(parser)?.0;
let name_meta = self.expect_ident(parser)?;
let size = self.parse_array_specifier(parser)?;
let ty = parser.maybe_array(ty, size);
let array_specifier = self.parse_array_specifier(parser)?;
let ty = parser.maybe_array(ty, name_meta.1, array_specifier);
context.add_function_arg(parser, body, Some(name), ty, qualifier);
context.add_function_arg(parser, body, Some(name_meta), ty, qualifier);
if self.bump_if(parser, TokenValue::Comma).is_some() {
continue;

View File

@@ -3,7 +3,7 @@ use crate::{
ast::{StorageQualifier, StructLayout, TypeQualifier},
error::ExpectedToken,
parser::ParsingContext,
token::{SourceMetadata, TokenValue},
token::{SourceMetadata, Token, TokenValue},
Error, ErrorKind, Parser, Result,
},
ArraySize, Handle, StorageClass, Type, TypeInner,
@@ -12,15 +12,20 @@ use crate::{
impl<'source> ParsingContext<'source> {
/// Parses an optional array_specifier returning `Ok(None)` if there is no
/// LeftBracket
pub fn parse_array_specifier(&mut self, parser: &mut Parser) -> Result<Option<ArraySize>> {
if self.bump_if(parser, TokenValue::LeftBracket).is_some() {
if self.bump_if(parser, TokenValue::RightBracket).is_some() {
return Ok(Some(ArraySize::Dynamic));
pub fn parse_array_specifier(
&mut self,
parser: &mut Parser,
) -> Result<Option<(ArraySize, SourceMetadata)>> {
if let Some(Token { meta, .. }) = self.bump_if(parser, TokenValue::LeftBracket) {
if let Some(Token { meta: end_meta, .. }) =
self.bump_if(parser, TokenValue::RightBracket)
{
return Ok(Some((ArraySize::Dynamic, meta.union(&end_meta))));
}
let (constant, _) = self.parse_constant_expression(parser)?;
self.expect(parser, TokenValue::RightBracket)?;
Ok(Some(ArraySize::Constant(constant)))
let end_meta = self.expect(parser, TokenValue::RightBracket)?.meta;
Ok(Some((ArraySize::Constant(constant), meta.union(&end_meta))))
} else {
Ok(None)
}
@@ -33,23 +38,32 @@ impl<'source> ParsingContext<'source> {
let token = self.bump(parser)?;
let handle = match token.value {
TokenValue::Void => None,
TokenValue::TypeName(ty) => Some(parser.module.types.fetch_or_append(ty)),
TokenValue::TypeName(ty) => Some(
parser
.module
.types
.fetch_or_append(ty, token.meta.as_span()),
),
TokenValue::Struct => {
let meta = token.meta;
let ty_name = self.expect_ident(parser)?.0;
self.expect(parser, TokenValue::LeftBrace)?;
let mut members = Vec::new();
let span =
self.parse_struct_declaration_list(parser, &mut members, StructLayout::Std140)?;
self.expect(parser, TokenValue::RightBrace)?;
let end_meta = self.expect(parser, TokenValue::RightBrace)?.meta;
let ty = parser.module.types.append(Type {
name: Some(ty_name.clone()),
inner: TypeInner::Struct {
top_level: false,
members,
span,
let ty = parser.module.types.append(
Type {
name: Some(ty_name.clone()),
inner: TypeInner::Struct {
top_level: false,
members,
span,
},
},
});
meta.union(&end_meta).as_span(),
);
parser.lookup_type.insert(ty_name, ty);
Some(ty)
}
@@ -77,8 +91,11 @@ impl<'source> ParsingContext<'source> {
}
};
let size = self.parse_array_specifier(parser)?;
Ok((handle.map(|ty| parser.maybe_array(ty, size)), token.meta))
let token_meta = token.meta;
let array_specifier = self.parse_array_specifier(parser)?;
let handle = handle.map(|ty| parser.maybe_array(ty, token_meta, array_specifier));
let meta = array_specifier.map_or(token_meta, |(_, meta)| meta.union(&token_meta));
Ok((handle, meta))
}
pub fn parse_type_non_void(

View File

@@ -56,6 +56,10 @@ impl SourceMetadata {
}
}
pub fn as_span(&self) -> crate::Span {
crate::Span::ByteRange(self.start..self.end)
}
pub(crate) fn none() -> Self {
SourceMetadata::default()
}

View File

@@ -257,18 +257,23 @@ impl Parser {
pub(crate) fn maybe_array(
&mut self,
base: Handle<Type>,
size: Option<ArraySize>,
meta: SourceMetadata,
array_specifier: Option<(ArraySize, SourceMetadata)>,
) -> Handle<Type> {
size.map(|size| {
self.module.types.fetch_or_append(Type {
name: None,
inner: TypeInner::Array {
base,
size,
stride: self.module.types[base].inner.span(&self.module.constants),
},
array_specifier
.map(|(size, size_meta)| {
self.module.types.fetch_or_append(
Type {
name: None,
inner: TypeInner::Array {
base,
size,
stride: self.module.types[base].inner.span(&self.module.constants),
},
},
meta.union(&size_meta).as_span(),
)
})
})
.unwrap_or(base)
.unwrap_or(base)
}
}

View File

@@ -42,6 +42,7 @@ impl Parser {
ctx: &mut Context,
body: &mut Block,
name: &str,
meta: SourceMetadata,
) -> Option<VariableReference> {
if let Some(local_var) = ctx.lookup_local_var(name) {
return Some(local_var);
@@ -54,15 +55,18 @@ impl Parser {
let ty = self
.module
.types
.fetch_or_append(Type { name: None, inner });
.fetch_or_append(Type { name: None, inner }, meta.as_span());
let handle = self.module.global_variables.append(GlobalVariable {
name: Some(name.into()),
class: StorageClass::Private,
binding: None,
ty,
init: None,
});
let handle = self.module.global_variables.append(
GlobalVariable {
name: Some(name.into()),
class: StorageClass::Private,
binding: None,
ty,
init: None,
},
meta.as_span(),
);
let idx = self.entry_args.len();
self.entry_args.push(EntryArg {
@@ -81,7 +85,7 @@ impl Parser {
},
));
let expr = ctx.add_expression(Expression::GlobalVariable(handle), body);
let expr = ctx.add_expression(Expression::GlobalVariable(handle), meta, body);
ctx.lookup_global_var_exps.insert(
name.into(),
VariableReference {
@@ -201,6 +205,7 @@ impl Parser {
base: expression,
index: index as u32,
},
meta,
body,
))
}
@@ -273,6 +278,7 @@ impl Parser {
base: expression,
index: pattern[0].index(),
},
meta,
body,
));
}
@@ -299,6 +305,7 @@ impl Parser {
Expression::Load {
pointer: expression,
},
meta,
body,
);
}
@@ -309,6 +316,7 @@ impl Parser {
vector: expression,
pattern,
},
meta,
body,
))
} else {
@@ -483,13 +491,16 @@ impl Parser {
})
});
let handle = self.module.global_variables.append(GlobalVariable {
name: name.clone(),
class: StorageClass::Private,
binding: None,
ty,
init,
});
let handle = self.module.global_variables.append(
GlobalVariable {
name: name.clone(),
class: StorageClass::Private,
binding: None,
ty,
init,
},
meta.as_span(),
);
let idx = self.entry_args.len();
self.entry_args.push(EntryArg {
@@ -548,16 +559,19 @@ impl Parser {
}
};
let handle = self.module.global_variables.append(GlobalVariable {
name: name.clone(),
class,
binding: binding.map(|binding| ResourceBinding {
group: set.unwrap_or(0),
binding,
}),
ty,
init,
});
let handle = self.module.global_variables.append(
GlobalVariable {
name: name.clone(),
class,
binding: binding.map(|binding| ResourceBinding {
group: set.unwrap_or(0),
binding,
}),
ty,
init,
},
meta.as_span(),
);
if let Some(name) = name {
let lookup = GlobalLookup {
@@ -628,12 +642,15 @@ impl Parser {
}
}
let handle = ctx.locals.append(LocalVariable {
name: name.clone(),
ty,
init,
});
let expr = ctx.add_expression(Expression::LocalVariable(handle), body);
let handle = ctx.locals.append(
LocalVariable {
name: name.clone(),
ty,
init,
},
meta.as_span(),
);
let expr = ctx.add_expression(Expression::LocalVariable(handle), meta, body);
if let Some(name) = name {
ctx.add_local_var(name, expr, mutable);

View File

@@ -29,10 +29,20 @@ impl Emitter {
self.start_len = Some(arena.len());
}
#[must_use]
fn finish(&mut self, arena: &Arena<crate::Expression>) -> Option<crate::Statement> {
fn finish(
&mut self,
arena: &Arena<crate::Expression>,
) -> Option<(crate::Statement, crate::span::Span)> {
let start_len = self.start_len.take().unwrap();
if start_len != arena.len() {
Some(crate::Statement::Emit(arena.range_from(start_len)))
#[allow(unused_mut)]
let mut span = crate::span::Span::Unknown;
let range = arena.range_from(start_len);
#[cfg(feature = "span")]
for handle in range.clone() {
span.subsume(arena.get_span(handle))
}
Some((crate::Statement::Emit(range), span))
} else {
None
}

View File

@@ -527,10 +527,13 @@ impl FlowGraph {
let variable = &lookup_expression[&variable_id];
let parent_node = &mut self.flow[self.block_to_node[&parent_id]];
parent_node.block.push(crate::Statement::Store {
pointer: phi.pointer,
value: variable.handle,
});
parent_node.block.push(
crate::Statement::Store {
pointer: phi.pointer,
value: variable.handle,
},
crate::Span::Unknown,
);
}
}
self.flow[node_index].phis = phis;
@@ -548,7 +551,7 @@ impl FlowGraph {
stop_nodes: std::collections::HashSet<BlockNodeIndex>,
) -> Result<crate::Block, Error> {
if stop_nodes.contains(&node_index) {
return Ok(vec![]);
return Ok(crate::Block::new());
}
if self.flow[node_index].visited {
@@ -647,21 +650,25 @@ impl FlowGraph {
|| edge == ControlFlowEdgeType::LoopBreak
{
// Do not add break if already has one as the last statement
if let Some(&crate::Statement::Break) = statements.last() {
if let Some(&crate::Statement::Break) = statements.as_ref().last() {
} else {
statements.push(crate::Statement::Break);
statements.push(crate::Statement::Break, crate::Span::Unknown);
}
}
}
}
result.push(crate::Statement::If {
condition,
accept,
reject,
});
result.push(
crate::Statement::If {
condition,
accept,
reject,
},
crate::Span::Unknown,
);
result.extend(self.convert_to_naga_traverse(merge_node_index, stop_nodes)?);
result
.extend_block(self.convert_to_naga_traverse(merge_node_index, stop_nodes)?);
Ok(result)
}
@@ -703,16 +710,20 @@ impl FlowGraph {
});
}
result.push(crate::Statement::Switch {
selector,
cases,
default: self.convert_to_naga_traverse(
self.block_to_node[&default_id],
stop_nodes_cases,
)?,
});
result.push(
crate::Statement::Switch {
selector,
cases,
default: self.convert_to_naga_traverse(
self.block_to_node[&default_id],
stop_nodes_cases,
)?,
},
crate::Span::Unknown,
);
result.extend(self.convert_to_naga_traverse(merge_node_index, stop_nodes)?);
result
.extend_block(self.convert_to_naga_traverse(merge_node_index, stop_nodes)?);
Ok(result)
}
@@ -745,25 +756,31 @@ impl FlowGraph {
let true_node_index = self.block_to_node[&true_id];
let false_node_index = self.block_to_node[&false_id];
body.push(crate::Statement::If {
condition,
accept: if true_node_index == merge_node_index {
vec![crate::Statement::Break]
} else {
self.convert_to_naga_traverse(
true_node_index,
stop_nodes_merge.clone(),
)?
body.push(
crate::Statement::If {
condition,
accept: if true_node_index == merge_node_index {
crate::Block::from_vec(vec![crate::Statement::Break])
} else {
self.convert_to_naga_traverse(
true_node_index,
stop_nodes_merge.clone(),
)?
},
reject: if false_node_index == merge_node_index {
crate::Block::from_vec(vec![crate::Statement::Break])
} else {
self.convert_to_naga_traverse(
false_node_index,
stop_nodes_merge,
)?
},
},
reject: if false_node_index == merge_node_index {
vec![crate::Statement::Break]
} else {
self.convert_to_naga_traverse(false_node_index, stop_nodes_merge)?
},
});
crate::Span::Unknown,
);
}
Terminator::Branch { target_id } => {
body.extend(self.convert_to_naga_traverse(
body.extend_block(self.convert_to_naga_traverse(
self.block_to_node[&target_id],
stop_nodes_merge,
)?)
@@ -771,8 +788,9 @@ impl FlowGraph {
_ => return Err(Error::InvalidTerminator),
};
let mut result = vec![crate::Statement::Loop { body, continuing }];
result.extend(self.convert_to_naga_traverse(merge_node_index, stop_nodes)?);
let mut result =
crate::Block::from_vec(vec![crate::Statement::Loop { body, continuing }]);
result.extend_block(self.convert_to_naga_traverse(merge_node_index, stop_nodes)?);
Ok(result)
}
@@ -795,27 +813,35 @@ impl FlowGraph {
if true_edge == ControlFlowEdgeType::LoopBreak
|| true_edge == ControlFlowEdgeType::IfBreak
{
result.push(crate::Statement::If {
condition,
accept: if true_edge == ControlFlowEdgeType::LoopBreak {
vec![crate::Statement::Break]
} else {
vec![]
result.push(
crate::Statement::If {
condition,
accept: if true_edge == ControlFlowEdgeType::LoopBreak {
crate::Block::from_vec(vec![crate::Statement::Break])
} else {
crate::Block::new()
},
reject: self
.convert_to_naga_traverse(false_node_id, stop_nodes)?,
},
reject: self.convert_to_naga_traverse(false_node_id, stop_nodes)?,
});
crate::Span::Unknown,
);
} else if false_edge == ControlFlowEdgeType::LoopBreak
|| false_edge == ControlFlowEdgeType::IfBreak
{
result.push(crate::Statement::If {
condition,
accept: self.convert_to_naga_traverse(true_node_id, stop_nodes)?,
reject: if false_edge == ControlFlowEdgeType::LoopBreak {
vec![crate::Statement::Break]
} else {
vec![]
result.push(
crate::Statement::If {
condition,
accept: self
.convert_to_naga_traverse(true_node_id, stop_nodes)?,
reject: if false_edge == ControlFlowEdgeType::LoopBreak {
crate::Block::from_vec(vec![crate::Statement::Break])
} else {
crate::Block::new()
},
},
});
crate::Span::Unknown,
);
} else {
return Err(Error::InvalidEdgeClassification);
}
@@ -827,7 +853,7 @@ impl FlowGraph {
self.flow[self.flow.find_edge(node_index, target_index).unwrap()];
if edge == ControlFlowEdgeType::LoopBreak {
result.push(crate::Statement::Break);
result.push(crate::Statement::Break, crate::Span::Unknown);
}
}
_ => return Err(Error::InvalidTerminator),
@@ -839,7 +865,7 @@ impl FlowGraph {
}
Some(ControlFlowNodeType::Kill) => {
let mut result: crate::Block = std::mem::take(&mut self.flow[node_index].block);
result.push(crate::Statement::Kill);
result.push(crate::Statement::Kill, crate::Span::Unknown);
Ok(result)
}
Some(ControlFlowNodeType::Return) => {
@@ -848,13 +874,13 @@ impl FlowGraph {
_ => return Err(Error::InvalidTerminator),
};
let mut result: crate::Block = std::mem::take(&mut self.flow[node_index].block);
result.push(crate::Statement::Return { value });
result.push(crate::Statement::Return { value }, crate::Span::Unknown);
Ok(result)
}
Some(ControlFlowNodeType::Merge) | None => match self.flow[node_index].terminator {
Terminator::Branch { target_id } => {
let mut result: crate::Block = std::mem::take(&mut self.flow[node_index].block);
result.extend(
let mut result = std::mem::take(&mut self.flow[node_index].block);
result.extend_block(
self.convert_to_naga_traverse(self.block_to_node[&target_id], stop_nodes)?,
);
Ok(result)

View File

@@ -1,6 +1,7 @@
use crate::arena::{Arena, Handle};
use super::{flow::*, Error, FunctionInfo, Instruction, LookupExpression, LookupHelper as _};
use crate::front::Emitter;
pub type BlockId = u32;
@@ -56,13 +57,16 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
from: spirv::Word,
to: spirv::Word,
) -> Handle<crate::Function> {
let dummy_handle = self.dummy_functions.append(crate::Function::default());
let dummy_handle = self
.dummy_functions
.append(crate::Function::default(), Default::default());
self.deferred_function_calls.push(to);
self.function_call_graph.add_edge(from, to, ());
dummy_handle
}
pub(super) fn parse_function(&mut self, module: &mut crate::Module) -> Result<(), Error> {
let start = self.data_offset;
self.lookup_expression.clear();
self.lookup_load_override.clear();
self.lookup_sampled_image.clear();
@@ -90,14 +94,16 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
})
},
local_variables: Arena::new(),
expressions: self.make_expression_storage(),
expressions: self
.make_expression_storage(&module.global_variables, &module.constants),
named_expressions: crate::FastHashMap::default(),
body: Vec::new(),
body: crate::Block::new(),
}
};
// read parameters
for i in 0..fun.arguments.capacity() {
let start = self.data_offset;
match self.next_inst()? {
Instruction {
op: spirv::Op::FunctionParameter,
@@ -105,9 +111,10 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
} => {
let type_id = self.next()?;
let id = self.next()?;
let handle = fun
.expressions
.append(crate::Expression::FunctionArgument(i as u32));
let handle = fun.expressions.append(
crate::Expression::FunctionArgument(i as u32),
self.span_from(start),
);
self.lookup_expression
.insert(id, LookupExpression { handle, type_id });
//Note: we redo the lookup in order to work around `self` borrowing
@@ -192,7 +199,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
fun.body = flow_graph.convert_to_naga()?;
// done
let fun_handle = module.functions.append(fun);
let fun_handle = module.functions.append(fun, self.span_from_with_op(start));
self.lookup_function.insert(fun_id, fun_handle);
self.function_info.push(function_info);
if let Some(ep) = self.lookup_entry_point.remove(&fun_id) {
@@ -204,41 +211,46 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
local_variables: Arena::new(),
expressions: Arena::new(),
named_expressions: crate::FastHashMap::default(),
body: Vec::new(),
body: crate::Block::new(),
};
// 1. copy the inputs from arguments to privates
for &v_id in ep.variable_ids.iter() {
let lvar = self.lookup_variable.lookup(v_id)?;
if let super::Variable::Input(ref arg) = lvar.inner {
let arg_expr =
function
.expressions
.append(crate::Expression::FunctionArgument(
function.arguments.len() as u32,
));
let span = module.global_variables.get_span(lvar.handle).clone();
let arg_expr = function.expressions.append(
crate::Expression::FunctionArgument(function.arguments.len() as u32),
span.clone(),
);
let load_expr = if arg.ty == module.global_variables[lvar.handle].ty {
arg_expr
} else {
// The only case where the type is different is if we need to treat
// unsigned integer as signed.
let old_len = function.expressions.len();
let handle = function.expressions.append(crate::Expression::As {
expr: arg_expr,
kind: crate::ScalarKind::Sint,
convert: Some(4),
});
function.body.push(crate::Statement::Emit(
function.expressions.range_from(old_len),
));
let mut emitter = Emitter::default();
emitter.start(&function.expressions);
let handle = function.expressions.append(
crate::Expression::As {
expr: arg_expr,
kind: crate::ScalarKind::Sint,
convert: Some(4),
},
span.clone(),
);
function.body.extend(emitter.finish(&function.expressions));
handle
};
function.body.push(crate::Statement::Store {
pointer: function
.expressions
.append(crate::Expression::GlobalVariable(lvar.handle)),
value: load_expr,
});
function.body.push(
crate::Statement::Store {
pointer: function.expressions.append(
crate::Expression::GlobalVariable(lvar.handle),
span.clone(),
),
value: load_expr,
},
span,
);
let mut arg = arg.clone();
if ep.stage == crate::ShaderStage::Fragment {
@@ -257,11 +269,14 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
// 2. call the wrapped function
let fake_id = !(module.entry_points.len() as u32); // doesn't matter, as long as it's not a collision
let dummy_handle = self.add_call(fake_id, fun_id);
function.body.push(crate::Statement::Call {
function: dummy_handle,
arguments: Vec::new(),
result: None,
});
function.body.push(
crate::Statement::Call {
function: dummy_handle,
arguments: Vec::new(),
result: None,
},
crate::Span::Unknown,
);
// 3. copy the outputs from privates to the result
let mut members = Vec::new();
@@ -269,9 +284,10 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
for &v_id in ep.variable_ids.iter() {
let lvar = self.lookup_variable.lookup(v_id)?;
if let super::Variable::Output(ref result) = lvar.inner {
let span = module.global_variables.get_span(lvar.handle).clone();
let expr_handle = function
.expressions
.append(crate::Expression::GlobalVariable(lvar.handle));
.append(crate::Expression::GlobalVariable(lvar.handle), span.clone());
match module.types[result.ty].inner {
crate::TypeInner::Struct {
members: ref sub_members,
@@ -288,6 +304,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
base: expr_handle,
index: index as u32,
},
span.clone(),
));
}
}
@@ -311,72 +328,94 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
Some(crate::Binding::BuiltIn(crate::BuiltIn::Position))
if self.options.adjust_coordinate_space =>
{
let old_len = function.expressions.len();
let mut emitter = Emitter::default();
emitter.start(&function.expressions);
let global_expr = components[member_index];
let access_expr =
function.expressions.append(crate::Expression::AccessIndex {
let span = function.expressions.get_span(global_expr).clone();
let access_expr = function.expressions.append(
crate::Expression::AccessIndex {
base: global_expr,
index: 1,
});
let load_expr = function.expressions.append(crate::Expression::Load {
pointer: access_expr,
});
let neg_expr = function.expressions.append(crate::Expression::Unary {
op: crate::UnaryOperator::Negate,
expr: load_expr,
});
function.body.push(crate::Statement::Emit(
function.expressions.range_from(old_len),
));
function.body.push(crate::Statement::Store {
pointer: access_expr,
value: neg_expr,
});
},
span.clone(),
);
let load_expr = function.expressions.append(
crate::Expression::Load {
pointer: access_expr,
},
span.clone(),
);
let neg_expr = function.expressions.append(
crate::Expression::Unary {
op: crate::UnaryOperator::Negate,
expr: load_expr,
},
span.clone(),
);
function.body.extend(emitter.finish(&function.expressions));
function.body.push(
crate::Statement::Store {
pointer: access_expr,
value: neg_expr,
},
span,
);
}
_ => {}
}
}
let old_len = function.expressions.len();
let mut emitter = Emitter::default();
emitter.start(&function.expressions);
for component in components.iter_mut() {
let load_expr = crate::Expression::Load {
pointer: *component,
};
*component = function.expressions.append(load_expr);
let span = function.expressions.get_span(*component).clone();
*component = function.expressions.append(load_expr, span);
}
match &members[..] {
[] => {}
[member] => {
function.body.push(crate::Statement::Emit(
function.expressions.range_from(old_len),
));
function.body.push(crate::Statement::Return {
value: components.first().cloned(),
});
function.body.extend(emitter.finish(&function.expressions));
let span = function.expressions.get_span(components[0]).clone();
function.body.push(
crate::Statement::Return {
value: components.first().cloned(),
},
span,
);
function.result = Some(crate::FunctionResult {
ty: member.ty,
binding: member.binding.clone(),
});
}
_ => {
let ty = module.types.append(crate::Type {
name: None,
inner: crate::TypeInner::Struct {
top_level: false,
members,
span: 0xFFFF, // shouldn't matter
let span = crate::Span::total_span(
components.iter().map(|h| function.expressions.get_span(*h)),
);
let ty = module.types.append(
crate::Type {
name: None,
inner: crate::TypeInner::Struct {
top_level: false,
members,
span: 0xFFFF, // shouldn't matter
},
},
});
span.clone(),
);
let result_expr = function
.expressions
.append(crate::Expression::Compose { ty, components });
function.body.push(crate::Statement::Emit(
function.expressions.range_from(old_len),
));
function.body.push(crate::Statement::Return {
value: Some(result_expr),
});
.append(crate::Expression::Compose { ty, components }, span.clone());
function.body.extend(emitter.finish(&function.expressions));
function.body.push(
crate::Statement::Return {
value: Some(result_expr),
},
span,
);
function.result = Some(crate::FunctionResult { ty, binding: None });
}
}

View File

@@ -89,59 +89,85 @@ fn extract_image_coordinates(
index: required_size.map_or(1, |size| size as u32),
};
let base_span = expressions.get_span(base).clone();
match extra_coordinate {
ExtraCoordinate::ArrayLayer => {
let extracted = match required_size {
None => expressions.append(crate::Expression::AccessIndex { base, index: 0 }),
None => expressions.append(
crate::Expression::AccessIndex { base, index: 0 },
base_span.clone(),
),
Some(size) => {
let mut components = Vec::with_capacity(size as usize);
for index in 0..size as u32 {
let comp =
expressions.append(crate::Expression::AccessIndex { base, index });
let comp = expressions.append(
crate::Expression::AccessIndex { base, index },
base_span.clone(),
);
components.push(comp);
}
expressions.append(crate::Expression::Compose {
ty: required_ty.unwrap(),
components,
})
expressions.append(
crate::Expression::Compose {
ty: required_ty.unwrap(),
components,
},
base_span.clone(),
)
}
};
let array_index_f32 = expressions.append(extra_expr);
let array_index = expressions.append(crate::Expression::As {
kind: crate::ScalarKind::Sint,
expr: array_index_f32,
convert: Some(4),
});
let array_index_f32 = expressions.append(extra_expr, base_span.clone());
let array_index = expressions.append(
crate::Expression::As {
kind: crate::ScalarKind::Sint,
expr: array_index_f32,
convert: Some(4),
},
base_span,
);
(extracted, Some(array_index))
}
ExtraCoordinate::Projection => {
let projection = expressions.append(extra_expr);
let projection = expressions.append(extra_expr, base_span.clone());
let divided = match required_size {
None => {
let temp =
expressions.append(crate::Expression::AccessIndex { base, index: 0 });
expressions.append(crate::Expression::Binary {
op: crate::BinaryOperator::Divide,
left: temp,
right: projection,
})
let temp = expressions.append(
crate::Expression::AccessIndex { base, index: 0 },
base_span.clone(),
);
expressions.append(
crate::Expression::Binary {
op: crate::BinaryOperator::Divide,
left: temp,
right: projection,
},
base_span,
)
}
Some(size) => {
let mut components = Vec::with_capacity(size as usize);
for index in 0..size as u32 {
let temp =
expressions.append(crate::Expression::AccessIndex { base, index });
let comp = expressions.append(crate::Expression::Binary {
op: crate::BinaryOperator::Divide,
left: temp,
right: projection,
});
let temp = expressions.append(
crate::Expression::AccessIndex { base, index },
base_span.clone(),
);
let comp = expressions.append(
crate::Expression::Binary {
op: crate::BinaryOperator::Divide,
left: temp,
right: projection,
},
base_span.clone(),
);
components.push(comp);
}
expressions.append(crate::Expression::Compose {
ty: required_ty.unwrap(),
components,
})
expressions.append(
crate::Expression::Compose {
ty: required_ty.unwrap(),
components,
},
base_span,
)
}
};
(divided, None)
@@ -157,7 +183,7 @@ fn extract_image_coordinates(
pattern: [Sc::X, Sc::Y, Sc::Z, Sc::W],
},
};
(expressions.append(cut_expr), None)
(expressions.append(cut_expr, base_span), None)
}
}
}
@@ -176,6 +202,7 @@ pub(super) fn patch_comparison_type(
log::debug!("Flipping comparison for {:?}", var);
let original_ty = &arena[var.ty];
let original_ty_span = arena.get_span(var.ty).clone();
let ty_inner = match original_ty.inner {
crate::TypeInner::Image {
class: crate::ImageClass::Sampled { multi, .. },
@@ -191,10 +218,13 @@ pub(super) fn patch_comparison_type(
};
let name = original_ty.name.clone();
var.ty = arena.append(crate::Type {
name,
inner: ty_inner,
});
var.ty = arena.append(
crate::Type {
name,
inner: ty_inner,
},
original_ty_span,
);
true
}
@@ -295,6 +325,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
arguments: &[FunctionArgument],
expressions: &mut Arena<crate::Expression>,
) -> Result<(), Error> {
let start = self.data_offset;
let result_type_id = self.next()?;
let result_id = self.next()?;
let image_id = self.next()?;
@@ -368,7 +399,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
self.lookup_expression.insert(
result_id,
LookupExpression {
handle: expressions.append(expr),
handle: expressions.append(expr, self.span_from_with_op(start)),
type_id: result_type_id,
},
);
@@ -386,6 +417,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
expressions: &mut Arena<crate::Expression>,
function_info: &mut FunctionInfo,
) -> Result<(), Error> {
let start = self.data_offset;
let result_type_id = self.next()?;
let result_id = self.next()?;
let sampled_image_id = self.next()?;
@@ -522,7 +554,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
self.lookup_expression.insert(
result_id,
LookupExpression {
handle: expressions.append(expr),
handle: expressions.append(expr, self.span_from_with_op(start)),
type_id: result_type_id,
},
);
@@ -534,6 +566,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
at_level: bool,
expressions: &mut Arena<crate::Expression>,
) -> Result<(), Error> {
let start = self.data_offset;
let result_type_id = self.next()?;
let result_id = self.next()?;
let image_id = self.next()?;
@@ -555,7 +588,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
self.lookup_expression.insert(
result_id,
LookupExpression {
handle: expressions.append(expr),
handle: expressions.append(expr, self.span_from_with_op(start)),
type_id: result_type_id,
},
);
@@ -567,6 +600,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
query: crate::ImageQuery,
expressions: &mut Arena<crate::Expression>,
) -> Result<(), Error> {
let start = self.data_offset;
let result_type_id = self.next()?;
let result_id = self.next()?;
let image_id = self.next()?;
@@ -580,7 +614,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
self.lookup_expression.insert(
result_id,
LookupExpression {
handle: expressions.append(expr),
handle: expressions.append(expr, self.span_from_with_op(start)),
type_id: result_type_id,
},
);

File diff suppressed because it is too large Load Diff

View File

@@ -15,19 +15,23 @@ fn make_scalar_inner(kind: crate::ScalarKind, width: crate::Bytes) -> crate::Con
pub fn generate_null_constant(
ty: Handle<crate::Type>,
type_arena: &mut Arena<crate::Type>,
type_arena: &Arena<crate::Type>,
constant_arena: &mut Arena<crate::Constant>,
span: crate::Span,
) -> Result<crate::ConstantInner, Error> {
let inner = match type_arena[ty].inner {
crate::TypeInner::Scalar { kind, width } => make_scalar_inner(kind, width),
crate::TypeInner::Vector { size, kind, width } => {
let mut components = Vec::with_capacity(size as usize);
for _ in 0..size as usize {
components.push(constant_arena.fetch_or_append(crate::Constant {
name: None,
specialization: None,
inner: make_scalar_inner(kind, width),
}));
components.push(constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner: make_scalar_inner(kind, width),
},
span.clone(),
));
}
crate::ConstantInner::Composite { ty, components }
}
@@ -36,20 +40,27 @@ pub fn generate_null_constant(
rows,
width,
} => {
let vector_ty = type_arena.fetch_or_append(crate::Type {
name: None,
inner: crate::TypeInner::Vector {
kind: crate::ScalarKind::Float,
size: rows,
width,
// If we successfully declared a matrix type, we have declared a vector type for it too.
let vector_ty = type_arena
.fetch_if(|t| {
t.inner
== crate::TypeInner::Vector {
kind: crate::ScalarKind::Float,
size: rows,
width,
}
})
.unwrap();
let vector_inner =
generate_null_constant(vector_ty, type_arena, constant_arena, span.clone())?;
let vector_handle = constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner: vector_inner,
},
});
let vector_inner = generate_null_constant(vector_ty, type_arena, constant_arena)?;
let vector_handle = constant_arena.fetch_or_append(crate::Constant {
name: None,
specialization: None,
inner: vector_inner,
});
span,
);
crate::ConstantInner::Composite {
ty,
components: vec![vector_handle; columns as usize],
@@ -60,12 +71,16 @@ pub fn generate_null_constant(
// copy out the types to avoid borrowing `members`
let member_tys = members.iter().map(|member| member.ty).collect::<Vec<_>>();
for member_ty in member_tys {
let inner = generate_null_constant(member_ty, type_arena, constant_arena)?;
components.push(constant_arena.fetch_or_append(crate::Constant {
name: None,
specialization: None,
inner,
}));
let inner =
generate_null_constant(member_ty, type_arena, constant_arena, span.clone())?;
components.push(constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner,
},
span.clone(),
));
}
crate::ConstantInner::Composite { ty, components }
}
@@ -77,12 +92,15 @@ pub fn generate_null_constant(
let size = constant_arena[handle]
.to_array_length()
.ok_or(Error::InvalidArraySize(handle))?;
let inner = generate_null_constant(base, type_arena, constant_arena)?;
let value = constant_arena.fetch_or_append(crate::Constant {
name: None,
specialization: None,
inner,
});
let inner = generate_null_constant(base, type_arena, constant_arena, span.clone())?;
let value = constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner,
},
span,
);
crate::ConstantInner::Composite {
ty,
components: vec![value; size as usize],
@@ -100,27 +118,34 @@ pub fn generate_null_constant(
pub fn generate_default_built_in(
built_in: Option<crate::BuiltIn>,
ty: Handle<crate::Type>,
type_arena: &mut Arena<crate::Type>,
type_arena: &Arena<crate::Type>,
constant_arena: &mut Arena<crate::Constant>,
span: crate::Span,
) -> Result<Handle<crate::Constant>, Error> {
let inner = match built_in {
Some(crate::BuiltIn::Position) => {
let zero = constant_arena.fetch_or_append(crate::Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
value: crate::ScalarValue::Float(0.0),
width: 4,
let zero = constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
value: crate::ScalarValue::Float(0.0),
width: 4,
},
},
});
let one = constant_arena.fetch_or_append(crate::Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
value: crate::ScalarValue::Float(1.0),
width: 4,
span.clone(),
);
let one = constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
value: crate::ScalarValue::Float(1.0),
width: 4,
},
},
});
span.clone(),
);
crate::ConstantInner::Composite {
ty,
components: vec![zero, zero, zero, one],
@@ -139,11 +164,14 @@ pub fn generate_default_built_in(
width: 4,
},
//Note: `crate::BuiltIn::ClipDistance` is intentionally left for the default path
_ => generate_null_constant(ty, type_arena, constant_arena)?,
_ => generate_null_constant(ty, type_arena, constant_arena, span.clone())?,
};
Ok(constant_arena.fetch_or_append(crate::Constant {
name: None,
specialization: None,
inner,
}))
Ok(constant_arena.fetch_or_append(
crate::Constant {
name: None,
specialization: None,
inner,
},
span,
))
}

View File

@@ -201,6 +201,10 @@ impl<'a> Lexer<'a> {
self.source.len() - self.input.len()
}
pub(super) fn span_from(&self, offset: usize) -> Span {
offset..self.current_byte_offset()
}
#[must_use]
pub(super) fn next(&mut self) -> TokenSpan<'a> {
let mut start_byte_offset = self.current_byte_offset();

File diff suppressed because it is too large Load Diff

View File

@@ -29,8 +29,8 @@ A Naga backend can generate code to evaluate an `Expression` however and
whenever it pleases, as long as it is certain to observe the side effects of all
previously executed `Statement`s.
Many `Statement` variants use the [`Block`] type, which is simply `Vec<Statement>`,
representing a series of statements executed in order. The body of an
Many `Statement` variants use the [`Block`] type, which is `Vec<Statement>`,
with optional span info, representing a series of statements executed in order. The body of an
`EntryPoint`s or `Function` is a `Block`, and `Statement` has a
[`Block`][Statement::Block] variant.
@@ -151,8 +151,10 @@ tree.
mod arena;
pub mod back;
mod block;
pub mod front;
pub mod proc;
mod span;
pub mod valid;
pub use crate::arena::{Arena, Handle, Range};
@@ -162,6 +164,7 @@ use std::{
hash::BuildHasherDefault,
};
pub use crate::span::Span;
#[cfg(feature = "deserialize")]
use serde::Deserialize;
#[cfg(feature = "serialize")]
@@ -1175,8 +1178,7 @@ pub enum Expression {
ArrayLength(Handle<Expression>),
}
/// A code block is just a vector of statements.
pub type Block = Vec<Statement>;
pub use block::Block;
/// A case for a switch statement.
// Clone is used only for error reporting and is not intended for end users

View File

@@ -41,6 +41,6 @@ pub fn ensure_block_returns(block: &mut crate::Block) {
| Some(&mut S::Call { .. })
| Some(&mut S::Atomic { .. })
| Some(&mut S::Barrier(_))
| None => block.push(S::Return { value: None }),
| None => block.push(S::Return { value: None }, Default::default()),
}
}

38
src/span.rs Normal file
View File

@@ -0,0 +1,38 @@
use std::ops::Range;
// A source code span, used for error reporting.
#[derive(Clone, Debug, PartialEq)]
pub enum Span {
// Span is unknown - no source information.
Unknown,
// Byte range.
ByteRange(Range<usize>),
}
impl Default for Span {
fn default() -> Self {
Self::Unknown
}
}
impl Span {
pub fn subsume(&mut self, other: &Self) {
match *self {
Self::Unknown => self.clone_from(other),
Self::ByteRange(ref mut self_range) => {
if let Self::ByteRange(ref other_range) = *other {
self_range.start = self_range.start.min(other_range.start);
self_range.end = self_range.end.max(other_range.end);
}
}
}
}
pub fn total_span<'a, T: Iterator<Item = &'a Self>>(from: T) -> Self {
let mut span: Self = Default::default();
for other in from {
span.subsume(other);
}
span
}
}

View File

@@ -857,59 +857,79 @@ fn uniform_control_flow() {
use crate::{Expression as E, Statement as S};
let mut constant_arena = Arena::new();
let constant = constant_arena.append(crate::Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
width: 4,
value: crate::ScalarValue::Uint(0),
let constant = constant_arena.append(
crate::Constant {
name: None,
specialization: None,
inner: crate::ConstantInner::Scalar {
width: 4,
value: crate::ScalarValue::Uint(0),
},
},
});
Default::default(),
);
let mut type_arena = Arena::new();
let ty = type_arena.append(crate::Type {
name: None,
inner: crate::TypeInner::Vector {
size: crate::VectorSize::Bi,
kind: crate::ScalarKind::Float,
width: 4,
let ty = type_arena.append(
crate::Type {
name: None,
inner: crate::TypeInner::Vector {
size: crate::VectorSize::Bi,
kind: crate::ScalarKind::Float,
width: 4,
},
},
});
Default::default(),
);
let mut global_var_arena = Arena::new();
let non_uniform_global = global_var_arena.append(crate::GlobalVariable {
name: None,
init: None,
ty,
class: crate::StorageClass::Handle,
binding: None,
});
let uniform_global = global_var_arena.append(crate::GlobalVariable {
name: None,
init: None,
ty,
binding: None,
class: crate::StorageClass::Uniform,
});
let non_uniform_global = global_var_arena.append(
crate::GlobalVariable {
name: None,
init: None,
ty,
class: crate::StorageClass::Handle,
binding: None,
},
Default::default(),
);
let uniform_global = global_var_arena.append(
crate::GlobalVariable {
name: None,
init: None,
ty,
binding: None,
class: crate::StorageClass::Uniform,
},
Default::default(),
);
let mut expressions = Arena::new();
// checks the uniform control flow
let constant_expr = expressions.append(E::Constant(constant));
let constant_expr = expressions.append(E::Constant(constant), Default::default());
// checks the non-uniform control flow
let derivative_expr = expressions.append(E::Derivative {
axis: crate::DerivativeAxis::X,
expr: constant_expr,
});
let derivative_expr = expressions.append(
E::Derivative {
axis: crate::DerivativeAxis::X,
expr: constant_expr,
},
Default::default(),
);
let emit_range_constant_derivative = expressions.range_from(0);
let non_uniform_global_expr = expressions.append(E::GlobalVariable(non_uniform_global));
let uniform_global_expr = expressions.append(E::GlobalVariable(uniform_global));
let non_uniform_global_expr =
expressions.append(E::GlobalVariable(non_uniform_global), Default::default());
let uniform_global_expr =
expressions.append(E::GlobalVariable(uniform_global), Default::default());
let emit_range_globals = expressions.range_from(2);
// checks the QUERY flag
let query_expr = expressions.append(E::ArrayLength(uniform_global_expr));
let query_expr = expressions.append(E::ArrayLength(uniform_global_expr), Default::default());
// checks the transitive WRITE flag
let access_expr = expressions.append(E::AccessIndex {
base: non_uniform_global_expr,
index: 1,
});
let access_expr = expressions.append(
E::AccessIndex {
base: non_uniform_global_expr,
index: 1,
},
Default::default(),
);
let emit_range_query_access_globals = expressions.range_from(2);
let mut info = FunctionInfo {
@@ -944,14 +964,15 @@ fn uniform_control_flow() {
let stmt_emit1 = S::Emit(emit_range_globals.clone());
let stmt_if_uniform = S::If {
condition: uniform_global_expr,
accept: Vec::new(),
accept: crate::Block::new(),
reject: vec![
S::Emit(emit_range_constant_derivative.clone()),
S::Store {
pointer: constant_expr,
value: derivative_expr,
},
],
]
.into(),
};
assert_eq!(
info.process_block(&[stmt_emit1, stmt_if_uniform], &[], None, &expressions),
@@ -975,8 +996,9 @@ fn uniform_control_flow() {
pointer: constant_expr,
value: derivative_expr,
},
],
reject: Vec::new(),
]
.into(),
reject: crate::Block::new(),
};
assert_eq!(
info.process_block(&[stmt_emit2, stmt_if_non_uniform], &[], None, &expressions),