diff --git a/Cargo.toml b/Cargo.toml index e27d1705b1..0c169d9a91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ spv-out = ["spirv"] wgsl-in = ["codespan-reporting"] wgsl-out = [] hlsl-out = [] +span = ["codespan-reporting"] [dev-dependencies] diff = "0.1" diff --git a/src/arena.rs b/src/arena.rs index bd3a3d7762..4827433da0 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -5,6 +5,8 @@ use std::{cmp::Ordering, fmt, hash, marker::PhantomData, num::NonZeroU32, ops}; /// the same size and representation as `Handle`. 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 Iterator for Range { /// 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 Iterator for Range { pub struct Arena { /// Values of this arena. data: Vec, + #[cfg(feature = "span")] + #[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(skip))] + span_info: Vec, } impl Default for Arena { @@ -148,7 +152,11 @@ impl fmt::Debug for Arena { impl Arena { /// 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 Arena { } /// Adds a new value to the arena, returning a typed handle. - pub fn append(&mut self, value: T) -> Handle { + pub fn append(&mut self, value: T, span: Span) -> Handle { + #[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 Arena { /// returns a handle pointing to /// an existing element if the check succeeds, or adds a new /// element otherwise. - pub fn fetch_if_or_append bool>(&mut self, value: T, fun: F) -> Handle { + pub fn fetch_if_or_append bool>( + &mut self, + value: T, + span: Span, + fun: F, + ) -> Handle { 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 + pub fn fetch_or_append(&mut self, value: T, span: Span) -> Handle 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) -> 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) -> &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 Arena { pub fn clear(&mut self) { self.data.clear() } + + pub fn get_span(&self, handle: Handle) -> &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 +where + T: serde::Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + 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 ops::Index> for Arena { @@ -254,6 +304,12 @@ impl ops::Index> for Arena { } } +impl ops::IndexMut> for Arena { + fn index_mut(&mut self, handle: Handle) -> &mut T { + &mut self.data[handle.index()] + } +} + impl ops::Index> for Arena { type Output = [T]; fn index(&self, range: Range) -> &[T] { @@ -268,8 +324,8 @@ mod tests { #[test] fn append_non_unique() { let mut arena: Arena = 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 = 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 = 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 = 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]); } diff --git a/src/back/msl/writer.rs b/src/back/msl/writer.rs index fa9ec02bf7..465992d82a 100644 --- a/src/back/msl/writer.rs +++ b/src/back/msl/writer.rs @@ -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) diff --git a/src/back/spv/block.rs b/src/back/spv/block.rs index ece8bdc721..daaf243b86 100644 --- a/src/back/spv/block.rs +++ b/src/back/spv/block.rs @@ -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) } diff --git a/src/block.rs b/src/block.rs new file mode 100644 index 0000000000..d7bcaed63b --- /dev/null +++ b/src/block.rs @@ -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, + #[cfg(feature = "span")] + #[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(skip))] + span_info: Vec, +} + +impl Block { + pub fn new() -> Self { + Self { + body: Vec::new(), + #[cfg(feature = "span")] + span_info: Vec::new(), + } + } + + pub fn from_vec(body: Vec) -> 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 + Clone>(&mut self, range: R) { + #[cfg(feature = "span")] + self.span_info.drain(range.clone()); + self.body.drain(range); + } + + pub fn splice + 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)> { + #[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(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Ok(Self::from_vec(Vec::deserialize(deserializer)?)) + } +} + +impl From> for Block { + fn from(body: Vec) -> Self { + Self::from_vec(body) + } +} diff --git a/src/front/glsl/constants.rs b/src/front/glsl/constants.rs index ac0f7bef69..0ac7f69d2c 100644 --- a/src/front/glsl/constants.rs +++ b/src/front/glsl/constants.rs @@ -64,6 +64,7 @@ impl<'a> ConstantSolver<'a> { &mut self, expr: Handle, ) -> Result, 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::>()?; - 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, kind: ScalarKind, target_width: crate::Bytes, + span: crate::Span, ) -> Result, ConstantSolvingError> { fn inner_cast(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, + span: crate::Span, ) -> Result, 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, right: Handle, + span: crate::Span, ) -> Result, 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, diff --git a/src/front/glsl/context.rs b/src/front/glsl/context.rs index 8b30a6a2bc..1b8d7835c1 100644 --- a/src/front/glsl/context.rs +++ b/src/front/glsl/context.rs @@ -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 { - if expr.needs_pre_emit() { + pub fn add_expression( + &mut self, + expr: Expression, + meta: SourceMetadata, + body: &mut Block, + ) -> Handle { + 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 { @@ -191,13 +205,13 @@ impl Context { &mut self, parser: &mut Parser, body: &mut Block, - name: Option, + name_meta: Option<(String, SourceMetadata)>, ty: Handle, 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, + meta: SourceMetadata, body: &mut Block, ) -> Handle { self.add_expression( @@ -840,6 +911,7 @@ impl Context { vector, pattern: crate::SwizzleComponent::XYZW, }, + meta, body, ) } diff --git a/src/front/glsl/functions.rs b/src/front/glsl/functions.rs index 7e3326bfbd..8d5a1b780b 100644 --- a/src/front/glsl/functions.rs +++ b/src/front/glsl/functions.rs @@ -23,7 +23,12 @@ struct CoordComponents { } impl Parser { - fn add_constant_value(&mut self, scalar_kind: ScalarKind, value: u64) -> Handle { + fn add_constant_value( + &mut self, + scalar_kind: ScalarKind, + value: u64, + meta: SourceMetadata, + ) -> Handle { 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, - mut global_init_body: Block, + global_init_body: Block, mut expressions: Arena, ) { 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 { diff --git a/src/front/glsl/offset.rs b/src/front/glsl/offset.rs index 698aeab35f..cb3f0b75d8 100644 --- a/src/front/glsl/offset.rs +++ b/src/front/glsl/offset.rs @@ -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) } diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index a5ee5f409c..a43396df60 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -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), } diff --git a/src/front/glsl/parser/declarations.rs b/src/front/glsl/parser/declarations.rs index d6fbd7c706..806e98e357 100644 --- a/src/front/glsl/parser/declarations.rs +++ b/src/front/glsl/parser/declarations.rs @@ -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 { + ) -> Result> { //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 { + meta: SourceMetadata, + ) -> Result { 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)?; diff --git a/src/front/glsl/parser/expressions.rs b/src/front/glsl/parser/expressions.rs index 59eacb9a4e..02184e9bd8 100644 --- a/src/front/glsl/parser/expressions.rs +++ b/src/front/glsl/parser/expressions.rs @@ -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))?, }) diff --git a/src/front/glsl/parser/functions.rs b/src/front/glsl/parser/functions.rs index efc72803bf..af1568fcd4 100644 --- a/src/front/glsl/parser/functions.rs +++ b/src/front/glsl/parser/functions.rs @@ -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> { // 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 { 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; diff --git a/src/front/glsl/parser/types.rs b/src/front/glsl/parser/types.rs index a575f5cb8d..0d1e0441f1 100644 --- a/src/front/glsl/parser/types.rs +++ b/src/front/glsl/parser/types.rs @@ -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> { - 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> { + 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( diff --git a/src/front/glsl/token.rs b/src/front/glsl/token.rs index cd35391af3..0aa6a6d709 100644 --- a/src/front/glsl/token.rs +++ b/src/front/glsl/token.rs @@ -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() } diff --git a/src/front/glsl/types.rs b/src/front/glsl/types.rs index 7c8200caf4..fe591f65b6 100644 --- a/src/front/glsl/types.rs +++ b/src/front/glsl/types.rs @@ -257,18 +257,23 @@ impl Parser { pub(crate) fn maybe_array( &mut self, base: Handle, - size: Option, + meta: SourceMetadata, + array_specifier: Option<(ArraySize, SourceMetadata)>, ) -> Handle { - 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) } } diff --git a/src/front/glsl/variables.rs b/src/front/glsl/variables.rs index aa1a60b85f..65d586f893 100644 --- a/src/front/glsl/variables.rs +++ b/src/front/glsl/variables.rs @@ -42,6 +42,7 @@ impl Parser { ctx: &mut Context, body: &mut Block, name: &str, + meta: SourceMetadata, ) -> Option { 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); diff --git a/src/front/mod.rs b/src/front/mod.rs index 4bd1294cea..c9d71d2987 100644 --- a/src/front/mod.rs +++ b/src/front/mod.rs @@ -29,10 +29,20 @@ impl Emitter { self.start_len = Some(arena.len()); } #[must_use] - fn finish(&mut self, arena: &Arena) -> Option { + fn finish( + &mut self, + arena: &Arena, + ) -> 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 } diff --git a/src/front/spv/flow.rs b/src/front/spv/flow.rs index c7c8b82af6..4362c5d235 100644 --- a/src/front/spv/flow.rs +++ b/src/front/spv/flow.rs @@ -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, ) -> Result { 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) diff --git a/src/front/spv/function.rs b/src/front/spv/function.rs index 401c14a602..81a4a5f885 100644 --- a/src/front/spv/function.rs +++ b/src/front/spv/function.rs @@ -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> super::Parser { from: spirv::Word, to: spirv::Word, ) -> Handle { - 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> super::Parser { }) }, 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> super::Parser { } => { 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> super::Parser { 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> super::Parser { 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> super::Parser { // 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> super::Parser { 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> super::Parser { base: expr_handle, index: index as u32, }, + span.clone(), )); } } @@ -311,72 +328,94 @@ impl> super::Parser { 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 }); } } diff --git a/src/front/spv/image.rs b/src/front/spv/image.rs index d7fe88cc3e..72c10c1231 100644 --- a/src/front/spv/image.rs +++ b/src/front/spv/image.rs @@ -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> super::Parser { arguments: &[FunctionArgument], expressions: &mut Arena, ) -> 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> super::Parser { 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> super::Parser { expressions: &mut Arena, 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> super::Parser { 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> super::Parser { at_level: bool, expressions: &mut Arena, ) -> 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> super::Parser { 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> super::Parser { query: crate::ImageQuery, expressions: &mut Arena, ) -> 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> super::Parser { 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, }, ); diff --git a/src/front/spv/mod.rs b/src/front/spv/mod.rs index 438c4f4a10..c214ad8bd5 100644 --- a/src/front/spv/mod.rs +++ b/src/front/spv/mod.rs @@ -378,6 +378,7 @@ struct FunctionInfo { pub struct Parser { data: I, + data_offset: usize, state: ModuleState, layouter: Layouter, temp_bytes: Vec, @@ -417,6 +418,7 @@ impl> Parser { pub fn new(data: I, options: &Options) -> Self { Parser { data, + data_offset: 0, state: ModuleState::Empty, layouter: Layouter::default(), temp_bytes: Vec::new(), @@ -446,8 +448,21 @@ impl> Parser { } } + fn span_from(&self, from: usize) -> crate::Span { + crate::Span::ByteRange(from..self.data_offset) + } + + fn span_from_with_op(&self, from: usize) -> crate::Span { + crate::Span::ByteRange((from - 4)..self.data_offset) + } + fn next(&mut self) -> Result { - self.data.next().ok_or(Error::IncompleteData) + if let Some(res) = self.data.next() { + self.data_offset += 4; + Ok(res) + } else { + Err(Error::IncompleteData) + } } fn next_inst(&mut self) -> Result { @@ -566,6 +581,7 @@ impl> Parser { expressions: &mut Arena, op: crate::UnaryOperator, ) -> Result<(), Error> { + let start = self.data_offset; let result_type_id = self.next()?; let result_id = self.next()?; let p_id = self.next()?; @@ -579,7 +595,7 @@ impl> Parser { 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, }, ); @@ -591,6 +607,7 @@ impl> Parser { expressions: &mut Arena, op: crate::BinaryOperator, ) -> Result<(), Error> { + let start = self.data_offset; let result_type_id = self.next()?; let result_id = self.next()?; let p1_id = self.next()?; @@ -607,7 +624,7 @@ impl> Parser { 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, }, ); @@ -623,10 +640,12 @@ impl> Parser { op: crate::BinaryOperator, types: &Arena, ) -> Result<(), Error> { + let start = self.data_offset; let result_type_id = self.next()?; let result_id = self.next()?; let p1_id = self.next()?; let p2_id = self.next()?; + let span = self.span_from_with_op(start); let p1_lexp = self.lookup_expression.lookup(p1_id)?; let p2_lexp = self.lookup_expression.lookup(p2_id)?; @@ -638,27 +657,33 @@ impl> Parser { left: if p1_lexp.type_id == result_type_id { p1_lexp.handle } else { - expressions.append(crate::Expression::As { - expr: p1_lexp.handle, - kind, - convert: None, - }) + expressions.append( + crate::Expression::As { + expr: p1_lexp.handle, + kind, + convert: None, + }, + span.clone(), + ) }, right: if p2_lexp.type_id == result_type_id { p2_lexp.handle } else { - expressions.append(crate::Expression::As { - expr: p2_lexp.handle, - kind, - convert: None, - }) + expressions.append( + crate::Expression::As { + expr: p2_lexp.handle, + kind, + convert: None, + }, + span.clone(), + ) }, }; self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(expr), + handle: expressions.append(expr, span), type_id: result_type_id, }, ); @@ -670,19 +695,25 @@ impl> Parser { expressions: &mut Arena, op: crate::BinaryOperator, ) -> Result<(), Error> { + let start = self.data_offset; let result_type_id = self.next()?; let result_id = self.next()?; let p1_id = self.next()?; let p2_id = self.next()?; + let span = self.span_from_with_op(start); + let p1_lexp = self.lookup_expression.lookup(p1_id)?; let p2_lexp = self.lookup_expression.lookup(p2_id)?; // convert the shift to Uint - let p2_handle = expressions.append(crate::Expression::As { - expr: p2_lexp.handle, - kind: crate::ScalarKind::Uint, - convert: None, - }); + let p2_handle = expressions.append( + crate::Expression::As { + expr: p2_lexp.handle, + kind: crate::ScalarKind::Uint, + convert: None, + }, + span.clone(), + ); let expr = crate::Expression::Binary { op, @@ -692,7 +723,7 @@ impl> Parser { self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(expr), + handle: expressions.append(expr, span), type_id: result_type_id, }, ); @@ -704,6 +735,7 @@ impl> Parser { expressions: &mut Arena, axis: crate::DerivativeAxis, ) -> Result<(), Error> { + let start = self.data_offset; let result_type_id = self.next()?; let result_id = self.next()?; let arg_id = self.next()?; @@ -717,13 +749,14 @@ impl> Parser { 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, }, ); Ok(()) } + #[allow(clippy::too_many_arguments)] fn insert_composite( &self, root_expr: Handle, @@ -732,11 +765,13 @@ impl> Parser { selections: &[spirv::Word], type_arena: &Arena, expressions: &mut Arena, + span: crate::Span, ) -> Result, Error> { let selection = match selections.first() { Some(&index) => index, None => return Ok(object_expr), }; + let root_span = expressions.get_span(root_expr).clone(); let root_lookup = self.lookup_type.lookup(root_type_id)?; let (count, child_type_id) = match type_arena[root_lookup.handle].inner { crate::TypeInner::Struct { ref members, .. } => { @@ -759,10 +794,17 @@ impl> Parser { let mut components = Vec::with_capacity(count); for index in 0..count as u32 { - let expr = expressions.append(crate::Expression::AccessIndex { - base: root_expr, - index, - }); + let expr = expressions.append( + crate::Expression::AccessIndex { + base: root_expr, + index, + }, + if index == selection { + span.clone() + } else { + root_span.clone() + }, + ); components.push(expr); } components[selection as usize] = self.insert_composite( @@ -772,12 +814,16 @@ impl> Parser { &selections[1..], type_arena, expressions, + span.clone(), )?; - Ok(expressions.append(crate::Expression::Compose { - ty: root_lookup.handle, - components, - })) + Ok(expressions.append( + crate::Expression::Compose { + ty: root_lookup.handle, + components, + }, + span, + )) } #[allow(clippy::too_many_arguments)] @@ -793,14 +839,16 @@ impl> Parser { arguments: &[crate::FunctionArgument], function_info: &mut FunctionInfo, ) -> Result { - let mut block = Vec::new(); + let mut block = crate::Block::new(); let mut phis = Vec::new(); let mut emitter = super::Emitter::default(); emitter.start(expressions); let mut merge = None; let terminator = loop { use spirv::Op; + let start = self.data_offset; let inst = self.next_inst()?; + let span = crate::Span::ByteRange(start..(start + 4 * (inst.wc as usize))); log::debug!("\t\t{:?} [{}]", inst.op, inst.wc); match inst.op { @@ -812,9 +860,15 @@ impl> Parser { } Op::Undef => { inst.expect(3)?; - let _result_type_id = self.next()?; - let _result_id = self.next()?; - //TODO? + let (type_id, id, handle) = + self.parse_null_constant(inst, type_arena, const_arena)?; + self.lookup_expression.insert( + id, + LookupExpression { + handle: expressions.append(crate::Expression::Constant(handle), span), + type_id, + }, + ); } Op::Variable => { inst.expect_at_least(4)?; @@ -840,20 +894,23 @@ impl> Parser { log::debug!("\t\t\tid={} name={}", result_id, name); } let lookup_ty = self.lookup_type.lookup(result_type_id)?; - let var_handle = local_arena.append(crate::LocalVariable { - name, - ty: match type_arena[lookup_ty.handle].inner { - crate::TypeInner::Pointer { base, .. } => base, - _ => lookup_ty.handle, + let var_handle = local_arena.append( + crate::LocalVariable { + name, + ty: match type_arena[lookup_ty.handle].inner { + crate::TypeInner::Pointer { base, .. } => base, + _ => lookup_ty.handle, + }, + init, }, - init, - }); + span.clone(), + ); self.lookup_expression.insert( result_id, LookupExpression { handle: expressions - .append(crate::Expression::LocalVariable(var_handle)), + .append(crate::Expression::LocalVariable(var_handle), span), type_id: result_type_id, }, ); @@ -867,12 +924,16 @@ impl> Parser { let result_id = self.next()?; let name = format!("phi_{}", result_id); - let var_handle = local_arena.append(crate::LocalVariable { - name: Some(name), - ty: self.lookup_type.lookup(result_type_id)?.handle, - init: None, - }); - let pointer = expressions.append(crate::Expression::LocalVariable(var_handle)); + let var_handle = local_arena.append( + crate::LocalVariable { + name: Some(name), + ty: self.lookup_type.lookup(result_type_id)?.handle, + init: None, + }, + self.span_from(start), + ); + let pointer = expressions + .append(crate::Expression::LocalVariable(var_handle), span.clone()); let in_count = (inst.wc - 3) / 2; let mut phi = PhiInstruction { @@ -894,7 +955,7 @@ impl> Parser { self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(crate::Expression::Load { pointer }), + handle: expressions.append(crate::Expression::Load { pointer }, span), type_id: result_type_id, }, ); @@ -948,11 +1009,13 @@ impl> Parser { .lookup_member .get(&(type_lookup.handle, index)) .ok_or(Error::InvalidAccessType(acex.type_id))?; - let base_handle = - expressions.append(crate::Expression::AccessIndex { + let base_handle = expressions.append( + crate::Expression::AccessIndex { base: acex.base_handle, index, - }); + }, + span.clone(), + ); AccessExpression { base_handle, type_id: lookup_member.type_id, @@ -963,17 +1026,21 @@ impl> Parser { Some(match type_arena[sub_type_lookup.handle].inner { // load it transposed, to match column major expectations crate::TypeInner::Matrix { .. } => { - let loaded = - expressions.append(crate::Expression::Load { + let loaded = expressions.append( + crate::Expression::Load { pointer: base_handle, - }); - let transposed = - expressions.append(crate::Expression::Math { + }, + span.clone(), + ); + let transposed = expressions.append( + crate::Expression::Math { fun: crate::MathFunction::Transpose, arg: loaded, arg1: None, arg2: None, - }); + }, + span.clone(), + ); LookupLoadOverride::Loaded(transposed) } _ => LookupLoadOverride::Pending, @@ -990,11 +1057,13 @@ impl> Parser { let index = index_maybe.ok_or_else(|| { Error::InvalidAccess(index_expr_data.clone()) })?; - let sub_handle = - expressions.append(crate::Expression::AccessIndex { + let sub_handle = expressions.append( + crate::Expression::AccessIndex { base: load_expr, index, - }); + }, + span.clone(), + ); Some(LookupLoadOverride::Loaded(sub_handle)) } _ => None, @@ -1010,7 +1079,7 @@ impl> Parser { }, }; AccessExpression { - base_handle: expressions.append(sub_expr), + base_handle: expressions.append(sub_expr, span.clone()), type_id: type_lookup .base_id .ok_or(Error::InvalidAccessType(acex.type_id))?, @@ -1019,10 +1088,13 @@ impl> Parser { } // This must be a vector or an array. _ => { - let base_handle = expressions.append(crate::Expression::Access { - base: acex.base_handle, - index: index_expr.handle, - }); + let base_handle = expressions.append( + crate::Expression::Access { + base: acex.base_handle, + index: index_expr.handle, + }, + span.clone(), + ); let load_override = match acex.load_override { // If there is a load override in place, then we always end up // with a side-loaded value here. @@ -1031,23 +1103,31 @@ impl> Parser { // We must be indexing into the array of row-major matrices. // Let's load the result of indexing and transpose it. LookupLoadOverride::Pending => { - let loaded = - expressions.append(crate::Expression::Load { + let loaded = expressions.append( + crate::Expression::Load { pointer: base_handle, - }); - expressions.append(crate::Expression::Math { - fun: crate::MathFunction::Transpose, - arg: loaded, - arg1: None, - arg2: None, - }) + }, + span.clone(), + ); + expressions.append( + crate::Expression::Math { + fun: crate::MathFunction::Transpose, + arg: loaded, + arg1: None, + arg2: None, + }, + span.clone(), + ) } // We are indexing inside a row-major matrix. LookupLoadOverride::Loaded(load_expr) => expressions - .append(crate::Expression::Access { - base: load_expr, - index: index_expr.handle, - }), + .append( + crate::Expression::Access { + base: load_expr, + index: index_expr.handle, + }, + span.clone(), + ), }; Some(LookupLoadOverride::Loaded(sub_expr)) } @@ -1090,25 +1170,37 @@ impl> Parser { _ => return Err(Error::InvalidVectorType(root_type_lookup.handle)), }; - let mut handle = expressions.append(crate::Expression::Access { - base: root_lexp.handle, - index: self.index_constant_expressions[0], - }); - for &index_expr in self.index_constant_expressions[1..num_components].iter() { - let access_expr = expressions.append(crate::Expression::Access { + let mut handle = expressions.append( + crate::Expression::Access { base: root_lexp.handle, - index: index_expr, - }); - let cond = expressions.append(crate::Expression::Binary { - op: crate::BinaryOperator::Equal, - left: index_expr, - right: index_lexp.handle, - }); - handle = expressions.append(crate::Expression::Select { - condition: cond, - accept: access_expr, - reject: handle, - }); + index: self.index_constant_expressions[0], + }, + span.clone(), + ); + for &index_expr in self.index_constant_expressions[1..num_components].iter() { + let access_expr = expressions.append( + crate::Expression::Access { + base: root_lexp.handle, + index: index_expr, + }, + span.clone(), + ); + let cond = expressions.append( + crate::Expression::Binary { + op: crate::BinaryOperator::Equal, + left: index_expr, + right: index_lexp.handle, + }, + span.clone(), + ); + handle = expressions.append( + crate::Expression::Select { + condition: cond, + accept: access_expr, + reject: handle, + }, + span.clone(), + ); } self.lookup_expression.insert( @@ -1139,26 +1231,38 @@ impl> Parser { }; let mut components = Vec::with_capacity(num_components); for &index_expr in self.index_constant_expressions[..num_components].iter() { - let access_expr = expressions.append(crate::Expression::Access { - base: root_lexp.handle, - index: index_expr, - }); - let cond = expressions.append(crate::Expression::Binary { - op: crate::BinaryOperator::Equal, - left: index_expr, - right: index_lexp.handle, - }); - let handle = expressions.append(crate::Expression::Select { - condition: cond, - accept: object_lexp.handle, - reject: access_expr, - }); + let access_expr = expressions.append( + crate::Expression::Access { + base: root_lexp.handle, + index: index_expr, + }, + span.clone(), + ); + let cond = expressions.append( + crate::Expression::Binary { + op: crate::BinaryOperator::Equal, + left: index_expr, + right: index_lexp.handle, + }, + span.clone(), + ); + let handle = expressions.append( + crate::Expression::Select { + condition: cond, + accept: object_lexp.handle, + reject: access_expr, + }, + span.clone(), + ); components.push(handle); } - let handle = expressions.append(crate::Expression::Compose { - ty: root_type_lookup.handle, - components, - }); + let handle = expressions.append( + crate::Expression::Compose { + ty: root_type_lookup.handle, + components, + }, + span.clone(), + ); self.lookup_expression.insert( id, @@ -1198,10 +1302,13 @@ impl> Parser { } }; lexp = LookupExpression { - handle: expressions.append(crate::Expression::AccessIndex { - base: lexp.handle, - index, - }), + handle: expressions.append( + crate::Expression::AccessIndex { + base: lexp.handle, + index, + }, + span.clone(), + ), type_id, }; } @@ -1235,6 +1342,7 @@ impl> Parser { &selections, type_arena, expressions, + span, )?; self.lookup_expression.insert( @@ -1272,7 +1380,7 @@ impl> Parser { self.lookup_expression.insert( id, LookupExpression { - handle: expressions.append(expr), + handle: expressions.append(expr, span), type_id: result_type_id, }, ); @@ -1297,9 +1405,12 @@ impl> Parser { _ => match self.lookup_load_override.get(&pointer_id) { Some(&LookupLoadOverride::Loaded(handle)) => handle, //Note: we aren't handling `LookupLoadOverride::Pending` properly here - _ => expressions.append(crate::Expression::Load { - pointer: base_lexp.handle, - }), + _ => expressions.append( + crate::Expression::Load { + pointer: base_lexp.handle, + }, + span, + ), }, }; @@ -1323,10 +1434,13 @@ impl> Parser { } let base_expr = self.lookup_expression.lookup(pointer_id)?; let value_expr = self.lookup_expression.lookup(value_id)?; - block.push(crate::Statement::Store { - pointer: base_expr.handle, - value: value_expr.handle, - }); + block.push( + crate::Statement::Store { + pointer: base_expr.handle, + value: value_expr.handle, + }, + span, + ); emitter.start(expressions); } // Arithmetic Instructions +, -, *, /, % @@ -1394,7 +1508,7 @@ impl> Parser { self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(expr), + handle: expressions.append(expr, span), type_id: result_type_id, }, ); @@ -1417,7 +1531,7 @@ impl> Parser { self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(expr), + handle: expressions.append(expr, span), type_id: result_type_id, }, ); @@ -1440,7 +1554,7 @@ impl> Parser { self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(expr), + handle: expressions.append(expr, span), type_id: result_type_id, }, ); @@ -1495,7 +1609,7 @@ impl> Parser { arguments, expressions, )?; - block.push(stmt); + block.push(stmt, span); emitter.start(expressions); } Op::ImageFetch | Op::ImageRead => { @@ -1603,7 +1717,7 @@ impl> Parser { self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(expr), + handle: expressions.append(expr, span), type_id: result_type_id, }, ); @@ -1681,7 +1795,7 @@ impl> Parser { } else { return Err(Error::InvalidAccessIndex(index)); }; - components.push(expressions.append(expr)); + components.push(expressions.append(expr, span.clone())); } crate::Expression::Compose { ty: self.lookup_type.lookup(result_type_id)?.handle, @@ -1692,7 +1806,7 @@ impl> Parser { self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(expr), + handle: expressions.append(expr, span), type_id: result_type_id, }, ); @@ -1705,7 +1819,7 @@ impl> Parser { | Op::FConvert | Op::UConvert | Op::SConvert => { - inst.expect_at_least(4)?; + inst.expect(4)?; let result_type_id = self.next()?; let result_id = self.next()?; let value_id = self.next()?; @@ -1731,7 +1845,7 @@ impl> Parser { self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(expr), + handle: expressions.append(expr, span), type_id: result_type_id, }, ); @@ -1756,8 +1870,8 @@ impl> Parser { let result = if self.lookup_void_type == Some(result_type_id) { None } else { - let expr_handle = - expressions.append(crate::Expression::CallResult(function)); + let expr_handle = expressions + .append(crate::Expression::CallResult(function), span.clone()); self.lookup_expression.insert( result_id, LookupExpression { @@ -1767,11 +1881,14 @@ impl> Parser { ); Some(expr_handle) }; - block.push(crate::Statement::Call { - function, - arguments, - result, - }); + block.push( + crate::Statement::Call { + function, + arguments, + result, + }, + span, + ); emitter.start(expressions); } Op::ExtInst => { @@ -1797,30 +1914,38 @@ impl> Parser { self.lookup_expression.lookup(arg_id)?.handle }; - let constant_handle = const_arena.fetch_or_append(crate::Constant { - name: None, - specialization: None, - inner: crate::ConstantInner::Scalar { - width: 4, - value: crate::ScalarValue::Float(match gl_op { - Glo::Radians => std::f64::consts::PI / 180.0, - Glo::Degrees => 180.0 / std::f64::consts::PI, - _ => unreachable!(), - }), + let constant_handle = const_arena.fetch_or_append( + crate::Constant { + name: None, + specialization: None, + inner: crate::ConstantInner::Scalar { + width: 4, + value: crate::ScalarValue::Float(match gl_op { + Glo::Radians => std::f64::consts::PI / 180.0, + Glo::Degrees => 180.0 / std::f64::consts::PI, + _ => unreachable!(), + }), + }, }, - }); + Default::default(), + ); - let expr_handle = - expressions.append(crate::Expression::Constant(constant_handle)); + let expr_handle = expressions.append( + crate::Expression::Constant(constant_handle), + Default::default(), + ); self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(crate::Expression::Binary { - op: crate::BinaryOperator::Multiply, - left: arg, - right: expr_handle, - }), + handle: expressions.append( + crate::Expression::Binary { + op: crate::BinaryOperator::Multiply, + left: arg, + right: expr_handle, + }, + span, + ), type_id: result_type_id, }, ); @@ -1900,7 +2025,7 @@ impl> Parser { self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(expr), + handle: expressions.append(expr, span), type_id: result_type_id, }, ); @@ -1962,7 +2087,7 @@ impl> Parser { self.lookup_expression.insert( result_id, LookupExpression { - handle: expressions.append(expr), + handle: expressions.append(expr, span), type_id: result_type_id, }, ); @@ -2020,11 +2145,14 @@ impl> Parser { width: _, } => { // IR expects a signed integer, so do a bitcast - expressions.append(crate::Expression::As { - kind: crate::ScalarKind::Sint, - expr: selector_lexp.handle, - convert: None, - }) + expressions.append( + crate::Expression::As { + kind: crate::ScalarKind::Sint, + expr: selector_lexp.handle, + convert: None, + }, + span, + ) } crate::TypeInner::Scalar { kind: crate::ScalarKind::Sint, @@ -2093,12 +2221,16 @@ impl> Parser { let structure_ptr = self.lookup_expression.lookup(structure_id)?; - let member_ptr = expressions.append(crate::Expression::AccessIndex { - base: structure_ptr.handle, - index: member_index, - }); + let member_ptr = expressions.append( + crate::Expression::AccessIndex { + base: structure_ptr.handle, + index: member_index, + }, + span.clone(), + ); - let length = expressions.append(crate::Expression::ArrayLength(member_ptr)); + let length = + expressions.append(crate::Expression::ArrayLength(member_ptr), span); self.lookup_expression.insert( result_id, @@ -2125,15 +2257,21 @@ impl> Parser { let source = self.lookup_expression.lookup(source_id)?; // This operation is practically the same as loading and then storing, I think. - let value_expr = expressions.append(crate::Expression::Load { - pointer: source.handle, - }); + let value_expr = expressions.append( + crate::Expression::Load { + pointer: source.handle, + }, + span.clone(), + ); block.extend(emitter.finish(expressions)); - block.push(crate::Statement::Store { - pointer: target.handle, - value: value_expr, - }); + block.push( + crate::Statement::Store { + pointer: target.handle, + value: value_expr, + }, + span, + ); emitter.start(expressions); } @@ -2172,7 +2310,7 @@ impl> Parser { .bits() != 0, ); - block.push(crate::Statement::Barrier(flags)); + block.push(crate::Statement::Barrier(flags), span); } else { log::warn!("Unsupported barrier execution scope: {}", exec_scope); } @@ -2195,7 +2333,11 @@ impl> Parser { }) } - fn make_expression_storage(&mut self) -> Arena { + fn make_expression_storage( + &mut self, + globals: &Arena, + constants: &Arena, + ) -> Arena { let mut expressions = Arena::new(); #[allow(clippy::panic)] { @@ -2203,7 +2345,8 @@ impl> Parser { } // register global variables for (&id, var) in self.lookup_variable.iter() { - let handle = expressions.append(crate::Expression::GlobalVariable(var.handle)); + let span = globals.get_span(var.handle).clone(); + let handle = expressions.append(crate::Expression::GlobalVariable(var.handle), span); self.lookup_expression.insert( id, LookupExpression { @@ -2215,12 +2358,14 @@ impl> Parser { // register special constants self.index_constant_expressions.clear(); for &con_handle in self.index_constants.iter() { - let handle = expressions.append(crate::Expression::Constant(con_handle)); + let span = constants.get_span(con_handle).clone(); + let handle = expressions.append(crate::Expression::Constant(con_handle), span); self.index_constant_expressions.push(handle); } // register constants for (&id, con) in self.lookup_constant.iter() { - let handle = expressions.append(crate::Expression::Constant(con.handle)); + let span = constants.get_span(con.handle).clone(); + let handle = expressions.append(crate::Expression::Constant(con.handle), span); self.lookup_expression.insert( id, LookupExpression { @@ -2268,7 +2413,7 @@ impl> Parser { if let [S::Break] = reject[..] { // uplift "accept" into the parent let extracted = mem::take(accept); - statements.splice(i + 1..i + 1, extracted.into_iter()); + statements.splice(i + 1..i + 1, extracted); } else { self.patch_statements(reject, expressions, function)?; self.patch_statements(accept, expressions, function)?; @@ -2282,7 +2427,7 @@ impl> Parser { if cases.is_empty() { // uplift "default" into the parent let extracted = mem::take(default); - statements.splice(i + 1..i + 1, extracted.into_iter()); + statements.splice(i + 1..i + 1, extracted); } else { for case in cases.iter_mut() { self.patch_statements(&mut case.body, expressions, function)?; @@ -2382,14 +2527,17 @@ impl> Parser { // register indexing constants self.index_constants.clear(); for i in 0..4 { - let handle = module.constants.append(crate::Constant { - name: None, - specialization: None, - inner: crate::ConstantInner::Scalar { - width: 4, - value: crate::ScalarValue::Sint(i), + let handle = module.constants.append( + crate::Constant { + name: None, + specialization: None, + inner: crate::ConstantInner::Scalar { + width: 4, + value: crate::ScalarValue::Sint(i), + }, }, - }); + Default::default(), + ); self.index_constants.push(handle); } @@ -2439,7 +2587,9 @@ impl> Parser { Op::TypeSampler => self.parse_type_sampler(inst, &mut module), Op::Constant | Op::SpecConstant => self.parse_constant(inst, &mut module), Op::ConstantComposite => self.parse_composite_constant(inst, &mut module), - Op::ConstantNull | Op::Undef => self.parse_null_constant(inst, &mut module), + Op::ConstantNull | Op::Undef => self + .parse_null_constant(inst, &module.types, &mut module.constants) + .map(|_| ()), Op::ConstantTrue => self.parse_bool_constant(inst, true, &mut module), Op::ConstantFalse => self.parse_bool_constant(inst, false, &mut module), Op::Variable => self.parse_global_variable(inst, &mut module), @@ -2457,7 +2607,7 @@ impl> Parser { let mut nodes = petgraph::algo::toposort(&self.function_call_graph, None) .map_err(|cycle| Error::FunctionCallCycle(cycle.node_id()))?; nodes.reverse(); // we need dominated first - let mut functions = mem::take(&mut module.functions).into_inner(); + let mut functions = mem::take(&mut module.functions); for fun_id in nodes { if fun_id > !(functions.len() as u32) { // skip all the fake IDs registered for the entry points @@ -2465,9 +2615,11 @@ impl> Parser { } let handle = self.lookup_function.get_mut(&fun_id).unwrap(); // take out the function from the old array - let fun = mem::take(&mut functions[handle.index()]); + let fun = mem::take(&mut functions[*handle]); // add it to the newly formed arena, and adjust the lookup - *handle = module.functions.append(fun); + *handle = module + .functions + .append(fun, functions.get_span(*handle).clone()); } } // patch all the functions @@ -2734,6 +2886,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(2)?; let id = self.next()?; @@ -2744,10 +2897,13 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor.remove(&id).and_then(|dec| dec.name), - inner, - }), + handle: module.types.append( + crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }, + self.span_from_with_op(start), + ), base_id: None, }, ); @@ -2759,6 +2915,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(4)?; let id = self.next()?; @@ -2775,10 +2932,13 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor.remove(&id).and_then(|dec| dec.name), - inner, - }), + handle: module.types.append( + crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }, + self.span_from_with_op(start), + ), base_id: None, }, ); @@ -2790,6 +2950,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(3)?; let id = self.next()?; @@ -2801,10 +2962,13 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor.remove(&id).and_then(|dec| dec.name), - inner, - }), + handle: module.types.append( + crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }, + self.span_from_with_op(start), + ), base_id: None, }, ); @@ -2816,6 +2980,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(4)?; let id = self.next()?; @@ -2834,10 +2999,13 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor.remove(&id).and_then(|dec| dec.name), - inner, - }), + handle: module.types.append( + crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }, + self.span_from_with_op(start), + ), base_id: Some(type_id), }, ); @@ -2849,6 +3017,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(4)?; let id = self.next()?; @@ -2869,10 +3038,13 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append(crate::Type { - name: decor.and_then(|dec| dec.name), - inner, - }), + handle: module.types.append( + crate::Type { + name: decor.and_then(|dec| dec.name), + inner, + }, + self.span_from_with_op(start), + ), base_id: Some(vector_type_id), }, ); @@ -2900,6 +3072,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(4)?; let id = self.next()?; @@ -2929,13 +3102,16 @@ impl> Parser { base_lookup_ty.clone() } else { LookupType { - handle: module.types.append(crate::Type { - name: decor.and_then(|dec| dec.name), - inner: crate::TypeInner::Pointer { - base: base_lookup_ty.handle, - class, + handle: module.types.append( + crate::Type { + name: decor.and_then(|dec| dec.name), + inner: crate::TypeInner::Pointer { + base: base_lookup_ty.handle, + class, + }, }, - }), + self.span_from_with_op(start), + ), base_id: Some(type_id), } }; @@ -2948,6 +3124,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(4)?; let id = self.next()?; @@ -2968,10 +3145,13 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append(crate::Type { - name: decor.name, - inner, - }), + handle: module.types.append( + crate::Type { + name: decor.name, + inner, + }, + self.span_from_with_op(start), + ), base_id: Some(type_id), }, ); @@ -2983,6 +3163,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(3)?; let id = self.next()?; @@ -3001,10 +3182,13 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append(crate::Type { - name: decor.name, - inner, - }), + handle: module.types.append( + crate::Type { + name: decor.name, + inner, + }, + self.span_from_with_op(start), + ), base_id: Some(type_id), }, ); @@ -3016,6 +3200,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect_at_least(2)?; let id = self.next()?; @@ -3103,10 +3288,13 @@ impl> Parser { members, }; - let ty_handle = module.types.append(crate::Type { - name: parent_decor.and_then(|dec| dec.name), - inner, - }); + let ty_handle = module.types.append( + crate::Type { + name: parent_decor.and_then(|dec| dec.name), + inner, + }, + self.span_from_with_op(start), + ); if block_decor == Some(Block { buffer: true }) { self.lookup_storage_buffer_types @@ -3131,6 +3319,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(9)?; @@ -3147,17 +3336,20 @@ impl> Parser { let decor = self.future_decor.remove(&id).unwrap_or_default(); // ensure there is a type for texture coordinate without extra components - module.types.fetch_or_append(crate::Type { - name: None, - inner: { - let kind = crate::ScalarKind::Float; - let width = 4; - match dim.required_coordinate_size() { - None => crate::TypeInner::Scalar { kind, width }, - Some(size) => crate::TypeInner::Vector { size, kind, width }, - } + module.types.fetch_or_append( + crate::Type { + name: None, + inner: { + let kind = crate::ScalarKind::Float; + let width = 4; + match dim.required_coordinate_size() { + None => crate::TypeInner::Scalar { kind, width }, + Some(size) => crate::TypeInner::Vector { size, kind, width }, + } + }, }, - }); + Default::default(), + ); let base_handle = self.lookup_type.lookup(sample_type_id)?.handle; let kind = module.types[base_handle] @@ -3181,10 +3373,13 @@ impl> Parser { arrayed: is_array, }; - let handle = module.types.append(crate::Type { - name: decor.name, - inner, - }); + let handle = module.types.append( + crate::Type { + name: decor.name, + inner, + }, + self.span_from_with_op(start), + ); self.lookup_type.insert( id, @@ -3216,14 +3411,18 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(2)?; let id = self.next()?; let decor = self.future_decor.remove(&id).unwrap_or_default(); - let handle = module.types.append(crate::Type { - name: decor.name, - inner: crate::TypeInner::Sampler { comparison: false }, - }); + let handle = module.types.append( + crate::Type { + name: decor.name, + inner: crate::TypeInner::Sampler { comparison: false }, + }, + self.span_from_with_op(start), + ); self.lookup_type.insert( id, LookupType { @@ -3239,6 +3438,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect_at_least(4)?; let type_id = self.next()?; @@ -3308,11 +3508,14 @@ impl> Parser { self.lookup_constant.insert( id, LookupConstant { - handle: module.constants.append(crate::Constant { - specialization: decor.specialization, - name: decor.name, - inner, - }), + handle: module.constants.append( + crate::Constant { + specialization: decor.specialization, + name: decor.name, + inner, + }, + self.span_from_with_op(start), + ), type_id, }, ); @@ -3324,6 +3527,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect_at_least(3)?; let type_id = self.next()?; @@ -3341,11 +3545,14 @@ impl> Parser { self.lookup_constant.insert( id, LookupConstant { - handle: module.constants.append(crate::Constant { - name: self.future_decor.remove(&id).and_then(|dec| dec.name), - specialization: None, - inner: crate::ConstantInner::Composite { ty, components }, - }), + handle: module.constants.append( + crate::Constant { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + specialization: None, + inner: crate::ConstantInner::Composite { ty, components }, + }, + self.span_from_with_op(start), + ), type_id, }, ); @@ -3355,29 +3562,30 @@ impl> Parser { fn parse_null_constant( &mut self, inst: Instruction, - module: &mut crate::Module, - ) -> Result<(), Error> { + types: &Arena, + constants: &mut Arena, + ) -> Result<(u32, u32, Handle), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(3)?; let type_id = self.next()?; let id = self.next()?; + let span = self.span_from_with_op(start); let type_lookup = self.lookup_type.lookup(type_id)?; let ty = type_lookup.handle; - let inner = null::generate_null_constant(ty, &mut module.types, &mut module.constants)?; - - self.lookup_constant.insert( - id, - LookupConstant { - handle: module.constants.append(crate::Constant { - name: self.future_decor.remove(&id).and_then(|dec| dec.name), - specialization: None, //TODO - inner, - }), - type_id, + let inner = null::generate_null_constant(ty, types, constants, span.clone())?; + let handle = constants.append( + crate::Constant { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + specialization: None, //TODO + inner, }, + span, ); - Ok(()) + self.lookup_constant + .insert(id, LookupConstant { handle, type_id }); + Ok((type_id, id, handle)) } fn parse_bool_constant( @@ -3386,6 +3594,7 @@ impl> Parser { value: bool, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect(3)?; let type_id = self.next()?; @@ -3394,11 +3603,14 @@ impl> Parser { self.lookup_constant.insert( id, LookupConstant { - handle: module.constants.append(crate::Constant { - name: self.future_decor.remove(&id).and_then(|dec| dec.name), - specialization: None, //TODO - inner: crate::ConstantInner::boolean(value), - }), + handle: module.constants.append( + crate::Constant { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + specialization: None, //TODO + inner: crate::ConstantInner::boolean(value), + }, + self.span_from_with_op(start), + ), type_id, }, ); @@ -3410,6 +3622,7 @@ impl> Parser { inst: Instruction, module: &mut crate::Module, ) -> Result<(), Error> { + let start = self.data_offset; self.switch(ModuleState::Type, inst.op)?; inst.expect_at_least(4)?; let type_id = self.next()?; @@ -3423,6 +3636,7 @@ impl> Parser { } else { None }; + let span = self.span_from_with_op(start); let mut dec = self.future_decor.remove(&id).unwrap_or_default(); let original_ty = self.lookup_type.lookup(type_id)?.handle; @@ -3496,7 +3710,7 @@ impl> Parser { ) { unsigned_ty = module .types - .fetch_or_append(crate::Type { name: None, inner }); + .fetch_or_append(crate::Type { name: None, inner }, Default::default()); } } @@ -3522,8 +3736,9 @@ impl> Parser { match null::generate_default_built_in( Some(built_in), effective_ty, - &mut module.types, + &module.types, &mut module.constants, + span.clone(), ) { Ok(handle) => Some(handle), Err(e) => { @@ -3552,19 +3767,23 @@ impl> Parser { let handle = null::generate_default_built_in( built_in, member_ty, - &mut module.types, + &module.types, &mut module.constants, + span.clone(), )?; components.push(handle); } - Some(module.constants.append(crate::Constant { - name: None, - specialization: None, - inner: crate::ConstantInner::Composite { - ty: effective_ty, - components, + Some(module.constants.append( + crate::Constant { + name: None, + specialization: None, + inner: crate::ConstantInner::Composite { + ty: effective_ty, + components, + }, }, - })) + span.clone(), + )) } _ => None, }, @@ -3585,7 +3804,7 @@ impl> Parser { } }; - let handle = module.global_variables.append(var); + let handle = module.global_variables.append(var, span); if module.types[effective_ty].inner.can_comparison_sample() { log::debug!("\t\ttracking {:?} for sampling properties", handle); self.handle_sampling diff --git a/src/front/spv/null.rs b/src/front/spv/null.rs index 1fc2b30430..8dfe55e897 100644 --- a/src/front/spv/null.rs +++ b/src/front/spv/null.rs @@ -15,19 +15,23 @@ fn make_scalar_inner(kind: crate::ScalarKind, width: crate::Bytes) -> crate::Con pub fn generate_null_constant( ty: Handle, - type_arena: &mut Arena, + type_arena: &Arena, constant_arena: &mut Arena, + span: crate::Span, ) -> Result { 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::>(); 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, ty: Handle, - type_arena: &mut Arena, + type_arena: &Arena, constant_arena: &mut Arena, + span: crate::Span, ) -> Result, 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, + )) } diff --git a/src/front/wgsl/lexer.rs b/src/front/wgsl/lexer.rs index 9c62855243..39545ea732 100644 --- a/src/front/wgsl/lexer.rs +++ b/src/front/wgsl/lexer.rs @@ -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(); diff --git a/src/front/wgsl/mod.rs b/src/front/wgsl/mod.rs index 4990db0d00..4146747733 100644 --- a/src/front/wgsl/mod.rs +++ b/src/front/wgsl/mod.rs @@ -12,6 +12,7 @@ use crate::{ proc::{ ensure_block_returns, Alignment, Layouter, ResolveContext, ResolveError, TypeResolution, }, + span::Span as NagaSpan, ConstantInner, FastHashMap, ScalarValue, }; @@ -28,7 +29,6 @@ use std::{ borrow::Cow, convert::TryFrom, io::{self, Write}, - iter, num::{NonZeroU32, ParseFloatError, ParseIntError}, ops, }; @@ -504,31 +504,40 @@ mod type_inner_tests { fn to_wgsl() { let mut types = crate::Arena::new(); let mut constants = crate::Arena::new(); - let c = constants.append(crate::Constant { - name: Some("C".to_string()), - specialization: None, - inner: crate::ConstantInner::Scalar { - width: 4, - value: crate::ScalarValue::Uint(32), + let c = constants.append( + crate::Constant { + name: Some("C".to_string()), + specialization: None, + inner: crate::ConstantInner::Scalar { + width: 4, + value: crate::ScalarValue::Uint(32), + }, }, - }); + Default::default(), + ); - let mytype1 = types.append(crate::Type { - name: Some("MyType1".to_string()), - inner: crate::TypeInner::Struct { - top_level: true, - members: vec![], - span: 0, + let mytype1 = types.append( + crate::Type { + name: Some("MyType1".to_string()), + inner: crate::TypeInner::Struct { + top_level: true, + members: vec![], + span: 0, + }, }, - }); - let mytype2 = types.append(crate::Type { - name: Some("MyType2".to_string()), - inner: crate::TypeInner::Struct { - top_level: true, - members: vec![], - span: 0, + Default::default(), + ); + let mytype2 = types.append( + crate::Type { + name: Some("MyType2".to_string()), + inner: crate::TypeInner::Struct { + top_level: true, + members: vec![], + span: 0, + }, }, - }); + Default::default(), + ); let array = crate::TypeInner::Array { base: mytype1, @@ -741,13 +750,16 @@ impl<'a> ExpressionContext<'a, '_, '_> { ExpressionContext<'a, '_, '_>, ) -> Result, Error<'a>>, ) -> Result, Error<'a>> { + let start = lexer.current_byte_offset(); let mut left = parser(lexer, self.reborrow())?; while let Some(op) = classifier(lexer.peek().0) { let _ = lexer.next(); let right = parser(lexer, self.reborrow())?; - left = self - .expressions - .append(crate::Expression::Binary { op, left, right }); + let end = lexer.current_byte_offset(); + left = self.expressions.append( + crate::Expression::Binary { op, left, right }, + NagaSpan::ByteRange(start..end), + ); } Ok(left) } @@ -761,10 +773,12 @@ impl<'a> ExpressionContext<'a, '_, '_> { ExpressionContext<'a, '_, '_>, ) -> Result, Error<'a>>, ) -> Result, Error<'a>> { + let start = lexer.current_byte_offset(); let mut left = parser(lexer, self.reborrow())?; while let Some(op) = classifier(lexer.peek().0) { let _ = lexer.next(); let mut right = parser(lexer, self.reborrow())?; + let end = lexer.current_byte_offset(); // insert splats, if needed by the non-'*' operations if op != crate::BinaryOperator::Multiply { let left_size = match *self.resolve_type(left)? { @@ -773,21 +787,24 @@ impl<'a> ExpressionContext<'a, '_, '_> { }; match (left_size, self.resolve_type(right)?) { (Some(size), &crate::TypeInner::Scalar { .. }) => { - right = self - .expressions - .append(crate::Expression::Splat { size, value: right }); + right = self.expressions.append( + crate::Expression::Splat { size, value: right }, + self.expressions.get_span(right).clone(), + ); } (None, &crate::TypeInner::Vector { size, .. }) => { - left = self - .expressions - .append(crate::Expression::Splat { size, value: left }); + left = self.expressions.append( + crate::Expression::Splat { size, value: left }, + self.expressions.get_span(left).clone(), + ); } _ => {} } } - left = self - .expressions - .append(crate::Expression::Binary { op, left, right }); + left = self.expressions.append( + crate::Expression::Binary { op, left, right }, + NagaSpan::ByteRange(start..end), + ); } Ok(left) } @@ -796,9 +813,13 @@ impl<'a> ExpressionContext<'a, '_, '_> { /// /// This is useful for `CallResult` and `AtomicResult` expressions, which should not be covered by /// `Emit` statements. - fn interrupt_emitter(&mut self, expression: crate::Expression) -> Handle { + fn interrupt_emitter( + &mut self, + expression: crate::Expression, + span: NagaSpan, + ) -> Handle { self.block.extend(self.emitter.finish(self.expressions)); - let result = self.expressions.append(expression); + let result = self.expressions.append(expression, span); self.emitter.start(self.expressions); result } @@ -954,6 +975,7 @@ impl BindingParser { struct ParsedVariable<'a> { name: &'a str, + name_span: Span, class: Option, ty: Handle, init: Option>, @@ -1034,7 +1056,7 @@ impl std::error::Error for ParseError { } pub struct Parser { - scopes: Vec, + scopes: Vec<(Scope, usize)>, lookup_type: FastHashMap>, layouter: Layouter, } @@ -1048,6 +1070,20 @@ impl Parser { } } + fn push_scope(&mut self, scope: Scope, lexer: &Lexer<'_>) { + self.scopes.push((scope, lexer.current_byte_offset())); + } + + fn pop_scope(&mut self, lexer: &Lexer<'_>) -> Span { + let (_, initial) = self.scopes.pop().unwrap(); + lexer.span_from(initial) + } + + fn peek_scope(&mut self, lexer: &Lexer<'_>) -> Span { + let &(_, initial) = self.scopes.last().unwrap(); + lexer.span_from(initial) + } + fn get_constant_inner<'a>( word: &'a str, ty: char, @@ -1108,6 +1144,7 @@ impl Parser { } } + /// Expects name to be peeked from lexer, does not consume if returns None. fn parse_local_function_call<'a>( &mut self, lexer: &mut Lexer<'a>, @@ -1124,6 +1161,7 @@ impl Parser { let count = ctx.functions[fun_handle].arguments.len(); let mut arguments = Vec::with_capacity(count); + let _ = lexer.next(); lexer.open_arguments()?; while arguments.len() != count { if !arguments.is_empty() { @@ -1159,33 +1197,42 @@ impl Parser { _ => return Err(Error::InvalidAtomicOperandType(value_span)), }; - let result = ctx.interrupt_emitter(expression); - ctx.block.push(crate::Statement::Atomic { - pointer, - fun, - value, - result, - }); + let result = ctx.interrupt_emitter(expression, NagaSpan::ByteRange(value_span.clone())); + ctx.block.push( + crate::Statement::Atomic { + pointer, + fun, + value, + result, + }, + NagaSpan::ByteRange(value_span), + ); Ok(result) } + /// Expects [`Scope::PrimaryExpr`] or [`Scope::SingularExpr`] on top; does not pop it. + /// Expects `word` to be peeked (still in lexer), doesn't consume if returning None. fn parse_function_call_inner<'a>( &mut self, lexer: &mut Lexer<'a>, name: &'a str, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result>, Error<'a>> { + assert!(self.scopes.last().is_some()); let expr = if let Some(fun) = conv::map_relational_fun(name) { + let _ = lexer.next(); lexer.open_arguments()?; let argument = self.parse_general_expression(lexer, ctx.reborrow())?; lexer.close_arguments()?; crate::Expression::Relational { fun, argument } } else if let Some(axis) = conv::map_derivative_axis(name) { + let _ = lexer.next(); lexer.open_arguments()?; let expr = self.parse_general_expression(lexer, ctx.reborrow())?; lexer.close_arguments()?; crate::Expression::Derivative { axis, expr } } else if let Some(fun) = conv::map_standard_fun(name) { + let _ = lexer.next(); lexer.open_arguments()?; let arg_count = fun.argument_count(); let arg = self.parse_general_expression(lexer, ctx.reborrow())?; @@ -1211,6 +1258,7 @@ impl Parser { } else { match name { "select" => { + let _ = lexer.next(); lexer.open_arguments()?; let reject = self.parse_general_expression(lexer, ctx.reborrow())?; lexer.expect(Token::Separator(','))?; @@ -1225,6 +1273,7 @@ impl Parser { } } "arrayLength" => { + let _ = lexer.next(); lexer.open_arguments()?; let array = self.parse_singular_expression(lexer, ctx.reborrow())?; lexer.close_arguments()?; @@ -1232,12 +1281,14 @@ impl Parser { } // atomics "atomicLoad" => { + let _ = lexer.next(); lexer.open_arguments()?; let pointer = self.parse_atomic_pointer(lexer, ctx.reborrow())?; lexer.close_arguments()?; crate::Expression::Load { pointer } } "atomicAdd" => { + let _ = lexer.next(); let handle = self.parse_atomic_helper( lexer, crate::AtomicFunction::Add, @@ -1246,6 +1297,7 @@ impl Parser { return Ok(Some(handle)); } "atomicAnd" => { + let _ = lexer.next(); let handle = self.parse_atomic_helper( lexer, crate::AtomicFunction::And, @@ -1254,6 +1306,7 @@ impl Parser { return Ok(Some(handle)); } "atomicOr" => { + let _ = lexer.next(); let handle = self.parse_atomic_helper( lexer, crate::AtomicFunction::InclusiveOr, @@ -1262,6 +1315,7 @@ impl Parser { return Ok(Some(handle)); } "atomicXor" => { + let _ = lexer.next(); let handle = self.parse_atomic_helper( lexer, crate::AtomicFunction::ExclusiveOr, @@ -1270,16 +1324,19 @@ impl Parser { return Ok(Some(handle)); } "atomicMin" => { + let _ = lexer.next(); let handle = self.parse_atomic_helper(lexer, crate::AtomicFunction::Min, ctx)?; return Ok(Some(handle)); } "atomicMax" => { + let _ = lexer.next(); let handle = self.parse_atomic_helper(lexer, crate::AtomicFunction::Max, ctx)?; return Ok(Some(handle)); } "atomicExchange" => { + let _ = lexer.next(); let handle = self.parse_atomic_helper( lexer, crate::AtomicFunction::Exchange { compare: None }, @@ -1288,6 +1345,7 @@ impl Parser { return Ok(Some(handle)); } "atomicCompareExchangeWeak" => { + let _ = lexer.next(); lexer.open_arguments()?; let pointer = self.parse_singular_expression(lexer, ctx.reborrow())?; lexer.expect(Token::Separator(','))?; @@ -1309,17 +1367,23 @@ impl Parser { _ => return Err(Error::InvalidAtomicOperandType(value_span)), }; - let result = ctx.interrupt_emitter(expression); - ctx.block.push(crate::Statement::Atomic { - pointer, - fun: crate::AtomicFunction::Exchange { compare: Some(cmp) }, - value, - result, - }); + let span = self.peek_scope(lexer); + let result = + ctx.interrupt_emitter(expression, NagaSpan::ByteRange(span.clone())); + ctx.block.push( + crate::Statement::Atomic { + pointer, + fun: crate::AtomicFunction::Exchange { compare: Some(cmp) }, + value, + result, + }, + NagaSpan::ByteRange(span), + ); return Ok(Some(result)); } // texture sampling "textureSample" => { + let _ = lexer.next(); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; lexer.expect(Token::Separator(','))?; @@ -1350,6 +1414,7 @@ impl Parser { } } "textureSampleLevel" => { + let _ = lexer.next(); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; lexer.expect(Token::Separator(','))?; @@ -1382,6 +1447,7 @@ impl Parser { } } "textureSampleBias" => { + let _ = lexer.next(); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; lexer.expect(Token::Separator(','))?; @@ -1414,6 +1480,7 @@ impl Parser { } } "textureSampleGrad" => { + let _ = lexer.next(); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; lexer.expect(Token::Separator(','))?; @@ -1448,6 +1515,7 @@ impl Parser { } } "textureSampleCompare" => { + let _ = lexer.next(); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; lexer.expect(Token::Separator(','))?; @@ -1480,6 +1548,7 @@ impl Parser { } } "textureSampleCompareLevel" => { + let _ = lexer.next(); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; lexer.expect(Token::Separator(','))?; @@ -1512,6 +1581,7 @@ impl Parser { } } "textureLoad" => { + let _ = lexer.next(); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; let image = ctx.lookup_ident.lookup(image_name, image_span.clone())?; @@ -1544,6 +1614,7 @@ impl Parser { } } "textureDimensions" => { + let _ = lexer.next(); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; let image = ctx.lookup_ident.lookup(image_name, image_span)?; @@ -1560,6 +1631,7 @@ impl Parser { } } "textureNumLevels" => { + let _ = lexer.next(); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; let image = ctx.lookup_ident.lookup(image_name, image_span)?; @@ -1570,6 +1642,7 @@ impl Parser { } } "textureNumLayers" => { + let _ = lexer.next(); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; let image = ctx.lookup_ident.lookup(image_name, image_span)?; @@ -1580,6 +1653,7 @@ impl Parser { } } "textureNumSamples" => { + let _ = lexer.next(); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; let image = ctx.lookup_ident.lookup(image_name, image_span)?; @@ -1594,14 +1668,19 @@ impl Parser { let handle = match self.parse_local_function_call(lexer, name, ctx.reborrow())? { Some((function, arguments)) => { - let result = Some( - ctx.interrupt_emitter(crate::Expression::CallResult(function)), + let span = self.peek_scope(lexer); + let result = Some(ctx.interrupt_emitter( + crate::Expression::CallResult(function), + NagaSpan::ByteRange(span.clone()), + )); + ctx.block.push( + crate::Statement::Call { + function, + arguments, + result, + }, + NagaSpan::ByteRange(span), ); - ctx.block.push(crate::Statement::Call { - function, - arguments, - result, - }); result } None => None, @@ -1610,15 +1689,23 @@ impl Parser { } } }; - Ok(Some(ctx.expressions.append(expr))) + let span = self.peek_scope(lexer); + Ok(Some( + ctx.expressions.append(expr, NagaSpan::ByteRange(span)), + )) } + /// Expects [`Scope::PrimaryExpr`] scope on top; if returning Some(_), pops it. fn parse_construction<'a>( &mut self, lexer: &mut Lexer<'a>, type_name: &'a str, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result>, Error<'a>> { + assert_eq!( + self.scopes.last().map(|&(ref scope, _)| scope.clone()), + Some(Scope::PrimaryExpr) + ); let ty_resolution = match self.lookup_type.get(type_name) { Some(&handle) => TypeResolution::Handle(handle), None => match self.parse_type_decl_impl( @@ -1695,15 +1782,18 @@ impl Parser { } else { let ty = match ty_resolution { TypeResolution::Handle(handle) => handle, - TypeResolution::Value(inner) => { - ctx.types.fetch_or_append(crate::Type { name: None, inner }) - } + TypeResolution::Value(inner) => ctx + .types + .fetch_or_append(crate::Type { name: None, inner }, Default::default()), }; components.push(last_component); crate::Expression::Compose { ty, components } }; - Ok(Some(ctx.expressions.append(expr))) + let span = self.pop_scope(lexer); + Ok(Some( + ctx.expressions.append(expr, NagaSpan::ByteRange(span)), + )) } fn parse_const_expression_impl<'a>( @@ -1714,7 +1804,7 @@ impl Parser { type_arena: &mut Arena, const_arena: &mut Arena, ) -> Result, Error<'a>> { - self.scopes.push(Scope::ConstantExpr); + self.push_scope(Scope::ConstantExpr, lexer); let inner = match first_token_span { (Token::Word("true"), _) => crate::ConstantInner::boolean(true), (Token::Word("false"), _) => crate::ConstantInner::boolean(false), @@ -1726,7 +1816,7 @@ impl Parser { for (handle, var) in const_arena.iter() { match var.name { Some(ref string) if string == name => { - self.scopes.pop(); + self.pop_scope(lexer); return Ok(handle); } _ => {} @@ -1757,21 +1847,29 @@ impl Parser { other => return Err(Error::Unexpected(other, ExpectedToken::Constant)), }; + // Only set span if it's a named constant. Otherwise, the enclosing Expression should have + // the span. + let span = self.pop_scope(lexer); let handle = if let Some(name) = register_name { - const_arena.append(crate::Constant { - name: Some(name.to_string()), - specialization: None, - inner, - }) + const_arena.append( + crate::Constant { + name: Some(name.to_string()), + specialization: None, + inner, + }, + NagaSpan::ByteRange(span), + ) } else { - const_arena.fetch_or_append(crate::Constant { - name: None, - specialization: None, - inner, - }) + const_arena.fetch_or_append( + crate::Constant { + name: None, + specialization: None, + inner, + }, + Default::default(), + ) }; - self.scopes.pop(); Ok(handle) } @@ -1789,43 +1887,56 @@ impl Parser { lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result, Error<'a>> { - self.scopes.push(Scope::PrimaryExpr); - let handle = match lexer.next() { + // Will be popped inside match, possibly inside parse_function_call_inner or parse_construction + self.push_scope(Scope::PrimaryExpr, lexer); + let handle = match lexer.peek() { (Token::Paren('('), _) => { - let expr = self.parse_general_expression(lexer, ctx)?; + let _ = lexer.next(); + let expr = self.parse_general_expression(lexer, ctx.reborrow())?; lexer.expect(Token::Paren(')'))?; + self.pop_scope(lexer); expr } token @ (Token::Word("true"), _) | token @ (Token::Word("false"), _) | token @ (Token::Number { .. }, _) => { + let _ = lexer.next(); let const_handle = self.parse_const_expression_impl(token, lexer, None, ctx.types, ctx.constants)?; - // pause the emitter while generating this expression, since it's pre-emitted - ctx.interrupt_emitter(crate::Expression::Constant(const_handle)) + let span = self.pop_scope(lexer); + ctx.interrupt_emitter( + crate::Expression::Constant(const_handle), + NagaSpan::ByteRange(span), + ) } (Token::Word(word), span) => { if let Some(&expr) = ctx.lookup_ident.get(word) { + let _ = lexer.next(); + self.pop_scope(lexer); expr } else if let Some(expr) = self.parse_function_call_inner(lexer, word, ctx.reborrow())? { //TODO: resolve the duplicate call in `parse_singular_expression` - expr - } else if let Some(expr) = self.parse_construction(lexer, word, ctx.reborrow())? { + self.pop_scope(lexer); expr } else { - return Err(Error::UnknownIdent(span, word)); + let _ = lexer.next(); + if let Some(expr) = self.parse_construction(lexer, word, ctx.reborrow())? { + expr + } else { + return Err(Error::UnknownIdent(span, word)); + } } } other => return Err(Error::Unexpected(other, ExpectedToken::PrimaryExpression)), }; - self.scopes.pop(); Ok(handle) } fn parse_postfix<'a>( &mut self, + span_start: usize, lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, mut handle: Handle, @@ -1851,7 +1962,9 @@ impl Parser { }; if now { let expression = crate::Expression::Load { pointer: handle }; - handle = ctx.expressions.append(expression); + handle = ctx + .expressions + .append(expression, NagaSpan::ByteRange(lexer.span_from(span_start))); needs_deref = false; } } @@ -1943,14 +2056,17 @@ impl Parser { // after we reached for the value, load it return Ok(if needs_deref { let expression = crate::Expression::Load { pointer: handle }; - ctx.expressions.append(expression) + ctx.expressions + .append(expression, ctx.expressions.get_span(handle).clone()) } else { handle }); } }; - handle = ctx.expressions.append(expression); + handle = ctx + .expressions + .append(expression, NagaSpan::ByteRange(lexer.span_from(span_start))); } } @@ -1959,47 +2075,54 @@ impl Parser { lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result, Error<'a>> { - self.scopes.push(Scope::SingularExpr); + let start = lexer.current_byte_offset(); + self.push_scope(Scope::SingularExpr, lexer); //TODO: refactor this to avoid backing up - let backup = lexer.clone(); - let (allow_deref, handle) = match lexer.next().0 { + let (allow_deref, handle) = match lexer.peek().0 { Token::Operation('-') => { + let _ = lexer.next(); let expr = crate::Expression::Unary { op: crate::UnaryOperator::Negate, expr: self.parse_singular_expression(lexer, ctx.reborrow())?, }; - (true, ctx.expressions.append(expr)) + let span = self.peek_scope(lexer); + ( + true, + ctx.expressions.append(expr, NagaSpan::ByteRange(span)), + ) } Token::Operation('!') | Token::Operation('~') => { + let _ = lexer.next(); let expr = crate::Expression::Unary { op: crate::UnaryOperator::Not, expr: self.parse_singular_expression(lexer, ctx.reborrow())?, }; - (true, ctx.expressions.append(expr)) + let span = self.peek_scope(lexer); + ( + true, + ctx.expressions.append(expr, NagaSpan::ByteRange(span)), + ) } Token::Operation('&') => { + let _ = lexer.next(); let handle = self.parse_primary_expression(lexer, ctx.reborrow())?; (false, handle) } Token::Word(word) => { let handle = match self.parse_function_call_inner(lexer, word, ctx.reborrow())? { Some(handle) => handle, - None => { - *lexer = backup; - self.parse_primary_expression(lexer, ctx.reborrow())? - } + None => self.parse_primary_expression(lexer, ctx.reborrow())?, }; (true, handle) } _ => { - *lexer = backup; let handle = self.parse_primary_expression(lexer, ctx.reborrow())?; (true, handle) } }; - let post_handle = self.parse_postfix(lexer, ctx, handle, allow_deref)?; - self.scopes.pop(); + let post_handle = self.parse_postfix(start, lexer, ctx.reborrow(), handle, allow_deref)?; + self.pop_scope(lexer); Ok(post_handle) } @@ -2086,7 +2209,7 @@ impl Parser { lexer: &mut Lexer<'a>, mut context: ExpressionContext<'a, '_, '_>, ) -> Result, Error<'a>> { - self.scopes.push(Scope::GeneralExpr); + self.push_scope(Scope::GeneralExpr, lexer); // logical_or_expression let handle = context.parse_binary_op( lexer, @@ -2142,7 +2265,7 @@ impl Parser { ) }, )?; - self.scopes.pop(); + self.pop_scope(lexer); Ok(handle) } @@ -2164,7 +2287,7 @@ impl Parser { type_arena: &mut Arena, const_arena: &mut Arena, ) -> Result, Error<'a>> { - self.scopes.push(Scope::VariableDecl); + self.push_scope(Scope::VariableDecl, lexer); let mut class = None; if lexer.skip(Token::Paren('<')) { @@ -2200,9 +2323,10 @@ impl Parser { None }; lexer.expect(Token::Separator(';'))?; - self.scopes.pop(); + let name_span = self.pop_scope(lexer); Ok(ParsedVariable { name, + name_span, class, ty, init, @@ -2222,10 +2346,9 @@ impl Parser { lexer.expect(Token::Paren('{'))?; loop { let (mut size, mut align) = (None, None); - let bind_start = lexer.current_byte_offset(); + self.push_scope(Scope::Attribute, lexer); let mut bind_parser = BindingParser::default(); if lexer.skip(Token::DoubleParen('[')) { - self.scopes.push(Scope::Attribute); let mut ready = true; loop { match lexer.next() { @@ -2269,10 +2392,9 @@ impl Parser { } } } - self.scopes.pop(); } - let bind_end = lexer.current_byte_offset(); + let bind_span = self.pop_scope(lexer); let name = match lexer.next() { (Token::Word(word), _) => word, @@ -2295,7 +2417,7 @@ impl Parser { members.push(crate::StructMember { name: Some(name.to_owned()), ty, - binding: bind_parser.finish(bind_start..bind_end)?, + binding: bind_parser.finish(bind_span)?, offset: range.start, }); } @@ -2625,10 +2747,16 @@ impl Parser { Some(&handle) => handle, None => { match self.parse_type_decl_impl(lexer, attribute, name, type_arena, const_arena)? { - Some(inner) => type_arena.fetch_or_append(crate::Type { - name: debug_name.map(|s| s.to_string()), - inner, - }), + Some(inner) => { + let span = name_span.start..lexer.current_byte_offset(); + type_arena.fetch_or_append( + crate::Type { + name: debug_name.map(|s| s.to_string()), + inner, + }, + NagaSpan::ByteRange(span), + ) + } None => return Err(Error::UnknownType(name_span)), } } @@ -2642,11 +2770,11 @@ impl Parser { type_arena: &mut Arena, const_arena: &mut Arena, ) -> Result<(Handle, crate::StorageAccess), Error<'a>> { - self.scopes.push(Scope::TypeDecl); + self.push_scope(Scope::TypeDecl, lexer); let mut attribute = TypeAttributes::default(); if lexer.skip(Token::DoubleParen('[')) { - self.scopes.push(Scope::Attribute); + self.push_scope(Scope::Attribute, lexer); loop { match lexer.next() { (Token::Word("stride"), _) => { @@ -2660,7 +2788,7 @@ impl Parser { other => return Err(Error::Unexpected(other, ExpectedToken::TypeAttribute)), } } - self.scopes.pop(); + self.pop_scope(lexer); } let storage_access = crate::StorageAccess::default(); @@ -2674,11 +2802,15 @@ impl Parser { type_arena, const_arena, )?; - self.scopes.pop(); + self.pop_scope(lexer); + // Only set span if it's the first occurrence of the type. + // Type spans therefore should only be used for errors in type declarations; + // use variable spans/expression spans/etc. otherwise Ok((handle, storage_access)) } /// Parse a statement that is either an assignment or a function call. + /// Expects `ident` to still be in the lexer. fn parse_statement_restricted<'a, 'out>( &mut self, lexer: &mut Lexer<'a>, @@ -2686,10 +2818,13 @@ impl Parser { ident_span: Span, mut context: ExpressionContext<'a, '_, 'out>, ) -> Result<(), Error<'a>> { + let span_start = ident_span.start; context.emitter.start(context.expressions); let stmt = match context.lookup_ident.get(ident) { Some(&expr) => { - let left = self.parse_postfix(lexer, context.reborrow(), expr, false)?; + let _ = lexer.next(); + let left = + self.parse_postfix(span_start, lexer, context.reborrow(), expr, false)?; lexer.expect(Token::Operation('='))?; let value = self.parse_general_expression(lexer, context.reborrow())?; crate::Statement::Store { @@ -2708,10 +2843,13 @@ impl Parser { } } }; + let span_end = lexer.current_byte_offset(); context .block .extend(context.emitter.finish(context.expressions)); - context.block.push(stmt); + context + .block + .push(stmt, NagaSpan::ByteRange(span_start..span_end)); Ok(()) } @@ -2722,11 +2860,17 @@ impl Parser { block: &'out mut crate::Block, is_uniform_control_flow: bool, ) -> Result<(), Error<'a>> { - let (word, word_span) = match lexer.next() { - (Token::Separator(';'), _) => return Ok(()), + self.push_scope(Scope::Statement, lexer); + let (word, word_span) = match lexer.peek() { + (Token::Separator(';'), _) => { + let _ = lexer.next(); + self.pop_scope(lexer); + return Ok(()); + } (Token::Paren('{'), _) => { - self.scopes.push(Scope::Block); - let mut statements = Vec::new(); + self.push_scope(Scope::Block, lexer); + let _ = lexer.next(); + let mut statements = crate::Block::new(); while !lexer.skip(Token::Paren('}')) { self.parse_statement( lexer, @@ -2735,18 +2879,21 @@ impl Parser { is_uniform_control_flow, )?; } - self.scopes.pop(); - block.push(crate::Statement::Block(statements)); + self.pop_scope(lexer); + let span = self.pop_scope(lexer); + block.push( + crate::Statement::Block(statements), + NagaSpan::ByteRange(span), + ); return Ok(()); } (Token::Word(word), span) => (word, span), other => return Err(Error::Unexpected(other, ExpectedToken::Statement)), }; - - self.scopes.push(Scope::Statement); let mut emitter = super::Emitter::default(); - match word { + let statement = match word { "let" => { + let _ = lexer.next(); emitter.start(context.expressions); let (name, name_span) = lexer.next_ident_with_span()?; let given_ty = if lexer.skip(Token::Separator(':')) { @@ -2781,8 +2928,10 @@ impl Parser { context .named_expressions .insert(expr_id, String::from(name)); + None } "var" => { + let _ = lexer.next(); enum Init { Empty, Constant(Handle), @@ -2830,9 +2979,10 @@ impl Parser { // register the type, if needed match context.typifier[value].clone() { TypeResolution::Handle(ty) => ty, - TypeResolution::Value(inner) => context - .types - .fetch_or_append(crate::Type { name: None, inner }), + TypeResolution::Value(inner) => context.types.fetch_or_append( + crate::Type { name: None, inner }, + Default::default(), + ), } } }; @@ -2855,28 +3005,35 @@ impl Parser { }; lexer.expect(Token::Separator(';'))?; - let var_id = context.variables.append(crate::LocalVariable { - name: Some(name.to_owned()), - ty, - init: match init { - Init::Constant(value) => Some(value), - _ => None, + let var_id = context.variables.append( + crate::LocalVariable { + name: Some(name.to_owned()), + ty, + init: match init { + Init::Constant(value) => Some(value), + _ => None, + }, }, - }); + NagaSpan::ByteRange(name_span), + ); + // Doesn't make sense to assign a span to cached lookup let expr_id = context .expressions - .append(crate::Expression::LocalVariable(var_id)); + .append(crate::Expression::LocalVariable(var_id), Default::default()); context.lookup_ident.insert(name, expr_id); if let Init::Variable(value) = init { - block.push(crate::Statement::Store { + Some(crate::Statement::Store { pointer: expr_id, value, - }); + }) + } else { + None } } "return" => { + let _ = lexer.next(); let value = if lexer.peek().0 != Token::Separator(';') { emitter.start(context.expressions); let handle = self.parse_general_expression( @@ -2889,56 +3046,64 @@ impl Parser { None }; lexer.expect(Token::Separator(';'))?; - block.push(crate::Statement::Return { value }); + Some(crate::Statement::Return { value }) } "if" => { - emitter.start(context.expressions); + let _ = lexer.next(); lexer.expect(Token::Paren('('))?; + emitter.start(context.expressions); let condition = self .parse_general_expression(lexer, context.as_expression(block, &mut emitter))?; - lexer.expect(Token::Paren(')'))?; block.extend(emitter.finish(context.expressions)); + lexer.expect(Token::Paren(')'))?; let accept = self.parse_block(lexer, context.reborrow(), false)?; let mut elsif_stack = Vec::new(); + let mut elseif_span_start = lexer.current_byte_offset(); while lexer.skip(Token::Word("elseif")) { let mut sub_emitter = super::Emitter::default(); - sub_emitter.start(context.expressions); + lexer.expect(Token::Paren('('))?; + sub_emitter.start(context.expressions); let other_condition = self.parse_general_expression( lexer, context.as_expression(block, &mut sub_emitter), )?; - lexer.expect(Token::Paren(')'))?; let other_emit = sub_emitter.finish(context.expressions); + lexer.expect(Token::Paren(')'))?; let other_block = self.parse_block(lexer, context.reborrow(), false)?; - elsif_stack.push((other_condition, other_emit, other_block)); + elsif_stack.push((elseif_span_start, other_condition, other_emit, other_block)); + elseif_span_start = lexer.current_byte_offset(); } let mut reject = if lexer.skip(Token::Word("else")) { self.parse_block(lexer, context.reborrow(), false)? } else { - Vec::new() + crate::Block::new() }; + let span_end = lexer.current_byte_offset(); // reverse-fold the else-if blocks //Note: we may consider uplifting this to the IR - for (other_cond, other_emit, other_block) in elsif_stack.drain(..).rev() { - reject = other_emit - .into_iter() - .chain(iter::once(crate::Statement::If { - condition: other_cond, - accept: other_block, - reject, - })) - .collect(); + for (other_span_start, other_cond, other_emit, other_block) in + elsif_stack.into_iter().rev() + { + let sub_stmt = crate::Statement::If { + condition: other_cond, + accept: other_block, + reject, + }; + reject = crate::Block::new(); + reject.extend(other_emit); + reject.push(sub_stmt, NagaSpan::ByteRange(other_span_start..span_end)) } - block.push(crate::Statement::If { + Some(crate::Statement::If { condition, accept, reject, - }); + }) } "switch" => { + let _ = lexer.next(); emitter.start(context.expressions); lexer.expect(Token::Paren('('))?; let selector = self @@ -2947,7 +3112,7 @@ impl Parser { block.extend(emitter.finish(context.expressions)); lexer.expect(Token::Paren('{'))?; let mut cases = Vec::new(); - let mut default = Vec::new(); + let mut default = crate::Block::new(); loop { // cases + default @@ -2966,12 +3131,12 @@ impl Parser { } cases.push(crate::SwitchCase { value, - body: Vec::new(), + body: crate::Block::new(), fall_through: true, }); }; - let mut body = Vec::new(); + let mut body = crate::Block::new(); lexer.expect(Token::Paren('{'))?; let fall_through = loop { // default statements @@ -3001,15 +3166,16 @@ impl Parser { } } - block.push(crate::Statement::Switch { + Some(crate::Statement::Switch { selector, cases, default, - }); + }) } "loop" => { - let mut body = Vec::new(); - let mut continuing = Vec::new(); + let _ = lexer.next(); + let mut body = crate::Block::new(); + let mut continuing = crate::Block::new(); lexer.expect(Token::Paren('{'))?; loop { @@ -3024,9 +3190,10 @@ impl Parser { self.parse_statement(lexer, context.reborrow(), &mut body, false)?; } - block.push(crate::Statement::Loop { body, continuing }); + Some(crate::Statement::Loop { body, continuing }) } "for" => { + let _ = lexer.next(); lexer.expect(Token::Paren('('))?; if !lexer.skip(Token::Separator(';')) { let num_statements = block.len(); @@ -3047,27 +3214,34 @@ impl Parser { } }; - let mut body = Vec::new(); + let mut body = crate::Block::new(); if !lexer.skip(Token::Separator(';')) { - emitter.start(context.expressions); - let condition = self.parse_general_expression( - lexer, - context.as_expression(&mut body, &mut emitter), - )?; - lexer.expect(Token::Separator(';'))?; - body.extend(emitter.finish(context.expressions)); - body.push(crate::Statement::If { - condition, - accept: Vec::new(), - reject: vec![crate::Statement::Break], - }); + let (condition, span) = lexer.capture_span(|lexer| { + emitter.start(context.expressions); + let condition = self.parse_general_expression( + lexer, + context.as_expression(&mut body, &mut emitter), + )?; + lexer.expect(Token::Separator(';'))?; + body.extend(emitter.finish(context.expressions)); + Ok(condition) + })?; + let mut reject = crate::Block::new(); + reject.push(crate::Statement::Break, NagaSpan::Unknown); + body.push( + crate::Statement::If { + condition, + accept: crate::Block::new(), + reject, + }, + NagaSpan::ByteRange(span), + ); }; - let mut continuing = Vec::new(); - if let Token::Word(ident) = lexer.peek().0 { + let mut continuing = crate::Block::new(); + if let (Token::Word(ident), ident_span) = lexer.peek() { // manually parse the next statement here instead of calling parse_statement // because the statement is not terminated with a semicolon - let (_, ident_span) = lexer.next(); self.parse_statement_restricted( lexer, ident, @@ -3082,31 +3256,44 @@ impl Parser { self.parse_statement(lexer, context.reborrow(), &mut body, false)?; } - block.push(crate::Statement::Loop { body, continuing }); + Some(crate::Statement::Loop { body, continuing }) + } + "break" => { + let _ = lexer.next(); + Some(crate::Statement::Break) + } + "continue" => { + let _ = lexer.next(); + Some(crate::Statement::Continue) + } + "discard" => { + let _ = lexer.next(); + Some(crate::Statement::Kill) } - "break" => block.push(crate::Statement::Break), - "continue" => block.push(crate::Statement::Continue), - "discard" => block.push(crate::Statement::Kill), "storageBarrier" => { + let _ = lexer.next(); lexer.expect(Token::Paren('('))?; lexer.expect(Token::Paren(')'))?; - block.push(crate::Statement::Barrier(crate::Barrier::STORAGE)); + Some(crate::Statement::Barrier(crate::Barrier::STORAGE)) } "workgroupBarrier" => { + let _ = lexer.next(); lexer.expect(Token::Paren('('))?; lexer.expect(Token::Paren(')'))?; - block.push(crate::Statement::Barrier(crate::Barrier::WORK_GROUP)); + Some(crate::Statement::Barrier(crate::Barrier::WORK_GROUP)) } "atomicStore" => { + let _ = lexer.next(); lexer.open_arguments()?; let mut expression_ctx = context.as_expression(block, &mut emitter); let pointer = self.parse_atomic_pointer(lexer, expression_ctx.reborrow())?; lexer.expect(Token::Separator(','))?; let value = self.parse_general_expression(lexer, expression_ctx)?; lexer.close_arguments()?; - block.push(crate::Statement::Store { pointer, value }); + Some(crate::Statement::Store { pointer, value }) } "textureStore" => { + let _ = lexer.next(); emitter.start(context.expressions); lexer.open_arguments()?; let (image_name, image_span) = lexer.next_ident_with_span()?; @@ -3134,12 +3321,12 @@ impl Parser { .parse_general_expression(lexer, context.as_expression(block, &mut emitter))?; lexer.close_arguments()?; block.extend(emitter.finish(context.expressions)); - block.push(crate::Statement::ImageStore { + Some(crate::Statement::ImageStore { image, coordinate, array_index, value, - }); + }) } // assignment or a function call ident => { @@ -3150,9 +3337,13 @@ impl Parser { context.as_expression(block, &mut emitter), )?; lexer.expect(Token::Separator(';'))?; + None } + }; + let span = self.pop_scope(lexer); + if let Some(statement) = statement { + block.push(statement, NagaSpan::ByteRange(span)); } - self.scopes.pop(); Ok(()) } @@ -3161,10 +3352,10 @@ impl Parser { lexer: &mut Lexer<'a>, mut context: StatementContext<'a, '_, '_>, is_uniform_control_flow: bool, - ) -> Result, Error<'a>> { - self.scopes.push(Scope::Block); + ) -> Result> { + self.push_scope(Scope::Block, lexer); lexer.expect(Token::Paren('{'))?; - let mut block = Vec::new(); + let mut block = crate::Block::new(); while !lexer.skip(Token::Paren('}')) { self.parse_statement( lexer, @@ -3173,7 +3364,7 @@ impl Parser { is_uniform_control_flow, )?; } - self.scopes.pop(); + self.pop_scope(lexer); Ok(block) } @@ -3181,14 +3372,14 @@ impl Parser { &mut self, lexer: &mut Lexer<'a>, ) -> Result, Error<'a>> { - let start = lexer.current_byte_offset(); + self.push_scope(Scope::Attribute, lexer); if !lexer.skip(Token::DoubleParen('[')) { + self.pop_scope(lexer); return Ok(None); } let mut bind_parser = BindingParser::default(); - self.scopes.push(Scope::Attribute); loop { let (word, span) = lexer.next_ident_with_span()?; bind_parser.parse(lexer, word, span)?; @@ -3201,10 +3392,8 @@ impl Parser { } } - let end = lexer.current_byte_offset(); - - self.scopes.pop(); - bind_parser.finish(start..end) + let span = self.pop_scope(lexer); + bind_parser.finish(span) } fn parse_function_decl<'a>( @@ -3213,14 +3402,21 @@ impl Parser { module: &mut crate::Module, lookup_global_expression: &FastHashMap<&'a str, crate::Expression>, ) -> Result<(crate::Function, &'a str), Error<'a>> { - self.scopes.push(Scope::FunctionDecl); + self.push_scope(Scope::FunctionDecl, lexer); // read function name let mut lookup_ident = FastHashMap::default(); let fun_name = lexer.next_ident()?; // populate initial expressions let mut expressions = Arena::new(); for (&name, expression) in lookup_global_expression.iter() { - let expr_handle = expressions.append(expression.clone()); + let span = match *expression { + crate::Expression::GlobalVariable(handle) => { + module.global_variables.get_span(handle).clone() + } + crate::Expression::Constant(handle) => module.constants.get_span(handle).clone(), + _ => unreachable!(), + }; + let expr_handle = expressions.append(expression.clone(), span); lookup_ident.insert(name, expr_handle); } // read parameter list @@ -3235,11 +3431,13 @@ impl Parser { )); } let binding = self.parse_varying_binding(lexer)?; - let (param_name, _param_name_span, param_type, _access) = + let (param_name, param_name_span, param_type, _access) = self.parse_variable_ident_decl(lexer, &mut module.types, &mut module.constants)?; let param_index = arguments.len() as u32; - let expression_token = - expressions.append(crate::Expression::FunctionArgument(param_index)); + let expression_token = expressions.append( + crate::Expression::FunctionArgument(param_index), + NagaSpan::ByteRange(param_name_span), + ); lookup_ident.insert(param_name, expression_token); arguments.push(crate::FunctionArgument { name: Some(param_name.to_string()), @@ -3265,7 +3463,7 @@ impl Parser { local_variables: Arena::new(), expressions, named_expressions: crate::NamedExpressions::default(), - body: Vec::new(), + body: crate::Block::new(), }; // read body @@ -3290,7 +3488,7 @@ impl Parser { // fixup the IR ensure_block_returns(&mut fun.body); // done - self.scopes.pop(); + self.pop_scope(lexer); // Set named expressions after block parsing ends fun.named_expressions = named_expressions; @@ -3314,7 +3512,7 @@ impl Parser { if lexer.skip(Token::DoubleParen('[')) { let (mut bind_index, mut bind_group) = (None, None); - self.scopes.push(Scope::Attribute); + self.push_scope(Scope::Attribute, lexer); loop { match lexer.next_ident_with_span()? { ("binding", _) => { @@ -3386,24 +3584,29 @@ impl Parser { binding: index, }); } - self.scopes.pop(); + self.pop_scope(lexer); } // read items + let start = lexer.current_byte_offset(); match lexer.next() { (Token::Separator(';'), _) => {} (Token::Word("struct"), _) => { let name = lexer.next_ident()?; let (members, span) = self.parse_struct_body(lexer, &mut module.types, &mut module.constants)?; - let ty = module.types.fetch_or_append(crate::Type { - name: Some(name.to_string()), - inner: crate::TypeInner::Struct { - top_level: is_block, - members, - span, + let type_span = lexer.span_from(start); + let ty = module.types.fetch_or_append( + crate::Type { + name: Some(name.to_string()), + inner: crate::TypeInner::Struct { + top_level: is_block, + members, + span, + }, }, - }); + NagaSpan::ByteRange(type_span), + ); self.lookup_type.insert(name.to_owned(), ty); lexer.expect(Token::Separator(';'))?; } @@ -3472,13 +3675,16 @@ impl Parser { _ => crate::StorageClass::Private, }, }; - let var_handle = module.global_variables.append(crate::GlobalVariable { - name: Some(pvar.name.to_owned()), - class, - binding: binding.take(), - ty: pvar.ty, - init: pvar.init, - }); + let var_handle = module.global_variables.append( + crate::GlobalVariable { + name: Some(pvar.name.to_owned()), + class, + binding: binding.take(), + ty: pvar.ty, + init: pvar.init, + }, + NagaSpan::ByteRange(pvar.name_span), + ); lookup_global_expression .insert(pvar.name, crate::Expression::GlobalVariable(var_handle)); } @@ -3494,7 +3700,9 @@ impl Parser { function, }), None => { - module.functions.append(function); + module + .functions + .append(function, NagaSpan::ByteRange(lexer.span_from(start))); } } } diff --git a/src/lib.rs b/src/lib.rs index bd5a7c1d03..ce3cc5d349 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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`, -representing a series of statements executed in order. The body of an +Many `Statement` variants use the [`Block`] type, which is `Vec`, +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), } -/// A code block is just a vector of statements. -pub type Block = Vec; +pub use block::Block; /// A case for a switch statement. // Clone is used only for error reporting and is not intended for end users diff --git a/src/proc/terminator.rs b/src/proc/terminator.rs index 0f8b302cda..e35c2d9f9b 100644 --- a/src/proc/terminator.rs +++ b/src/proc/terminator.rs @@ -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()), } } diff --git a/src/span.rs b/src/span.rs new file mode 100644 index 0000000000..dbd24c8d1e --- /dev/null +++ b/src/span.rs @@ -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), +} + +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>(from: T) -> Self { + let mut span: Self = Default::default(); + for other in from { + span.subsume(other); + } + span + } +} diff --git a/src/valid/analyzer.rs b/src/valid/analyzer.rs index 543e25034e..0f917df7cd 100644 --- a/src/valid/analyzer.rs +++ b/src/valid/analyzer.rs @@ -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),