diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index 54c5c7e583..222ba8e406 100644 --- a/src/back/glsl/mod.rs +++ b/src/back/glsl/mod.rs @@ -44,7 +44,7 @@ pub use features::Features; use crate::{ - proc::{EntryPointIndex, NameKey, Namer, TypeResolution, TypifyError}, + proc::{EntryPointIndex, NameKey, Namer, TypeResolution}, valid::{FunctionInfo, ModuleInfo}, Arena, ArraySize, BinaryOperator, Binding, BuiltIn, Bytes, ConservativeDepth, Constant, ConstantInner, DerivativeAxis, Expression, FastHashMap, Function, GlobalVariable, Handle, @@ -270,9 +270,6 @@ pub enum Error { /// A error occurred while writing to the output #[error("I/O error")] IoError(#[from] IoError), - /// The [`Module`](crate::Module) failed type resolution - #[error("Type error")] - Type(#[from] TypifyError), /// The specified [`Version`](Version) doesn't have all required [`Features`](super) /// /// Contains the missing [`Features`](Features) diff --git a/src/back/msl/mod.rs b/src/back/msl/mod.rs index b651a25d76..dd424eee87 100644 --- a/src/back/msl/mod.rs +++ b/src/back/msl/mod.rs @@ -23,7 +23,7 @@ For the result type, if it's a structure, we re-compose it with a temporary valu holding the result. !*/ -use crate::{arena::Handle, proc::TypifyError, valid::ModuleInfo, FastHashMap}; +use crate::{arena::Handle, valid::ModuleInfo, FastHashMap}; use std::{ fmt::{Error as FmtError, Write}, string::FromUtf8Error, @@ -67,8 +67,6 @@ pub enum Error { Format(#[from] FmtError), #[error(transparent)] Utf8(#[from] FromUtf8Error), - #[error(transparent)] - Type(#[from] TypifyError), #[error("bind target {0:?} is empty")] UnimplementedBindTarget(BindTarget), #[error("composing of {0:?} is not implemented yet")] diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index ab592495fb..78f914af58 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -1,9 +1,8 @@ -use super::{constants::ConstantSolver, error::ErrorKind}; +use super::{super::Typifier, constants::ConstantSolver, error::ErrorKind}; use crate::{ - proc::{ResolveContext, Typifier}, - Arena, BinaryOperator, Binding, Constant, Expression, FastHashMap, Function, FunctionArgument, - GlobalVariable, Handle, Interpolation, LocalVariable, Module, RelationalFunction, - ResourceBinding, ShaderStage, Statement, StorageClass, Type, UnaryOperator, + proc::ResolveContext, Arena, BinaryOperator, Binding, Constant, Expression, FastHashMap, + Function, FunctionArgument, GlobalVariable, Handle, Interpolation, LocalVariable, Module, + RelationalFunction, ResourceBinding, ShaderStage, Statement, StorageClass, Type, UnaryOperator, }; #[derive(Debug)] diff --git a/src/front/glsl/functions.rs b/src/front/glsl/functions.rs index 1c25b5d2af..e1492e84b8 100644 --- a/src/front/glsl/functions.rs +++ b/src/front/glsl/functions.rs @@ -1,7 +1,7 @@ +use super::super::Typifier; use crate::{ - proc::{ensure_block_returns, Typifier}, - BinaryOperator, Block, EntryPoint, Expression, Function, MathFunction, RelationalFunction, - SampleLevel, TypeInner, + proc::ensure_block_returns, BinaryOperator, Block, EntryPoint, Expression, Function, + MathFunction, RelationalFunction, SampleLevel, TypeInner, }; use super::{ast::*, error::ErrorKind}; diff --git a/src/front/mod.rs b/src/front/mod.rs index 4177bddcbb..aa39bc2595 100644 --- a/src/front/mod.rs +++ b/src/front/mod.rs @@ -7,6 +7,11 @@ pub mod spv; #[cfg(feature = "wgsl-in")] pub mod wgsl; +use crate::{ + arena::{Arena, Handle}, + proc::{ResolveContext, ResolveError, TypeResolution}, +}; + /// Helper class to emit expressions #[allow(dead_code)] #[derive(Default)] @@ -16,14 +21,14 @@ struct Emitter { #[allow(dead_code)] impl Emitter { - fn start(&mut self, arena: &crate::Arena) { + fn start(&mut self, arena: &Arena) { if self.start_len.is_some() { unreachable!("Emitting has already started!"); } self.start_len = Some(arena.len()); } #[must_use] - fn finish(&mut self, arena: &crate::Arena) -> Option { + fn finish(&mut self, arena: &Arena) -> Option { let start_len = self.start_len.take().unwrap(); if start_len != arena.len() { Some(crate::Statement::Emit(arena.range_from(start_len))) @@ -42,3 +47,42 @@ impl super::ConstantInner { } } } + +/// Helper processor that derives the types of all expressions. +#[derive(Debug)] +pub struct Typifier { + resolutions: Vec, +} + +impl Typifier { + pub fn new() -> Self { + Typifier { + resolutions: Vec::new(), + } + } + + pub fn get<'a>( + &'a self, + expr_handle: Handle, + types: &'a Arena, + ) -> &'a crate::TypeInner { + self.resolutions[expr_handle.index()].inner_with(types) + } + + pub fn grow( + &mut self, + expr_handle: Handle, + expressions: &Arena, + types: &mut Arena, + ctx: &ResolveContext, + ) -> Result<(), ResolveError> { + if self.resolutions.len() <= expr_handle.index() { + for (eh, expr) in expressions.iter().skip(self.resolutions.len()) { + let resolution = ctx.resolve(expr, types, |h| &self.resolutions[h.index()])?; + log::debug!("Resolving {:?} = {:?} : {:?}", eh, expr, resolution); + self.resolutions.push(resolution); + } + } + Ok(()) + } +} diff --git a/src/front/wgsl/mod.rs b/src/front/wgsl/mod.rs index e54fac72a2..8bae91cff4 100644 --- a/src/front/wgsl/mod.rs +++ b/src/front/wgsl/mod.rs @@ -9,7 +9,7 @@ mod tests; use crate::{ arena::{Arena, Handle}, - proc::{ensure_block_returns, ResolveContext, ResolveError, Typifier}, + proc::{ensure_block_returns, ResolveContext, ResolveError}, FastHashMap, }; @@ -199,7 +199,7 @@ impl<'a> StringValueLookup<'a> for FastHashMap<&'a str, Handle { lookup_ident: &'temp mut FastHashMap<&'input str, Handle>, - typifier: &'temp mut Typifier, + typifier: &'temp mut super::Typifier, variables: &'out mut Arena, expressions: &'out mut Arena, types: &'out mut Arena, @@ -255,7 +255,7 @@ struct SamplingContext { struct ExpressionContext<'input, 'temp, 'out> { lookup_ident: &'temp FastHashMap<&'input str, Handle>, - typifier: &'temp mut Typifier, + typifier: &'temp mut super::Typifier, expressions: &'out mut Arena, types: &'out mut Arena, constants: &'out mut Arena, @@ -2434,7 +2434,7 @@ impl Parser { }; // read body - let mut typifier = Typifier::new(); + let mut typifier = super::Typifier::new(); fun.body = self.parse_block( lexer, StatementContext { diff --git a/src/proc/mod.rs b/src/proc/mod.rs index 5e8a2550c4..baab6c3be2 100644 --- a/src/proc/mod.rs +++ b/src/proc/mod.rs @@ -8,7 +8,7 @@ mod typifier; pub use layouter::{Alignment, Layouter}; pub use namer::{EntryPointIndex, NameKey, Namer}; pub use terminator::ensure_block_returns; -pub use typifier::{ResolveContext, ResolveError, TypeResolution, Typifier, TypifyError}; +pub use typifier::{ResolveContext, ResolveError, TypeResolution}; impl From for super::ScalarKind { fn from(format: super::StorageFormat) -> Self { diff --git a/src/proc/typifier.rs b/src/proc/typifier.rs index f1a07a3746..0bf23993cf 100644 --- a/src/proc/typifier.rs +++ b/src/proc/typifier.rs @@ -62,12 +62,6 @@ impl Clone for TypeResolution { } } -/// Helper processor that derives the types of all expressions. -#[derive(Debug)] -pub struct Typifier { - resolutions: Vec, -} - #[derive(Clone, Debug, Error, PartialEq)] pub enum ResolveError { #[error("Index {index} is out of bounds for expression {expr:?}")] @@ -99,12 +93,6 @@ pub enum ResolveError { IncompatibleOperands(String), } -//TODO: remove this -#[repr(C)] // pack this tighter: 48 -> 40 bytes -#[derive(Clone, Debug, Error, PartialEq)] -#[error("Type resolution of {0:?} failed")] -pub struct TypifyError(Handle, #[source] ResolveError); - pub struct ResolveContext<'a> { pub constants: &'a Arena, pub global_vars: &'a Arena, @@ -113,34 +101,34 @@ pub struct ResolveContext<'a> { pub arguments: &'a [crate::FunctionArgument], } -impl TypeResolution { - pub fn new<'a>( +impl<'a> ResolveContext<'a> { + pub fn resolve( + &self, expr: &crate::Expression, types: &'a Arena, - ctx: &ResolveContext, - past: impl Fn(Handle) -> &'a Self, - ) -> Result { + past: impl Fn(Handle) -> &'a TypeResolution, + ) -> Result { use crate::TypeInner as Ti; Ok(match *expr { crate::Expression::Access { base, .. } => match *past(base).inner_with(types) { - Ti::Array { base, .. } => Self::Handle(base), + Ti::Array { base, .. } => TypeResolution::Handle(base), Ti::Vector { size: _, kind, width, - } => Self::Value(Ti::Scalar { kind, width }), + } => TypeResolution::Value(Ti::Scalar { kind, width }), Ti::ValuePointer { size: Some(_), kind, width, class, - } => Self::Value(Ti::ValuePointer { + } => TypeResolution::Value(Ti::ValuePointer { size: None, kind, width, class, }), - Ti::Pointer { base, class } => Self::Value(match types[base].inner { + Ti::Pointer { base, class } => TypeResolution::Value(match types[base].inner { Ti::Array { base, .. } => Ti::Pointer { base, class }, Ti::Vector { size: _, @@ -173,7 +161,7 @@ impl TypeResolution { if index >= size as u32 { return Err(ResolveError::OutOfBoundsIndex { expr: base, index }); } - Self::Value(Ti::Scalar { kind, width }) + TypeResolution::Value(Ti::Scalar { kind, width }) } Ti::Matrix { columns, @@ -183,13 +171,13 @@ impl TypeResolution { if index >= columns as u32 { return Err(ResolveError::OutOfBoundsIndex { expr: base, index }); } - Self::Value(crate::TypeInner::Vector { + TypeResolution::Value(crate::TypeInner::Vector { size: rows, kind: crate::ScalarKind::Float, width, }) } - Ti::Array { base, .. } => Self::Handle(base), + Ti::Array { base, .. } => TypeResolution::Handle(base), Ti::Struct { block: _, ref members, @@ -197,7 +185,7 @@ impl TypeResolution { let member = members .get(index as usize) .ok_or(ResolveError::OutOfBoundsIndex { expr: base, index })?; - Self::Handle(member.ty) + TypeResolution::Handle(member.ty) } Ti::ValuePointer { size: Some(size), @@ -208,7 +196,7 @@ impl TypeResolution { if index >= size as u32 { return Err(ResolveError::OutOfBoundsIndex { expr: base, index }); } - Self::Value(Ti::ValuePointer { + TypeResolution::Value(Ti::ValuePointer { size: None, kind, width, @@ -218,7 +206,7 @@ impl TypeResolution { Ti::Pointer { base: ty_base, class, - } => Self::Value(match types[ty_base].inner { + } => TypeResolution::Value(match types[ty_base].inner { Ti::Array { base, .. } => Ti::Pointer { base, class }, Ti::Vector { size, kind, width } => { if index >= size as u32 { @@ -274,43 +262,45 @@ impl TypeResolution { }); } }, - crate::Expression::Constant(h) => match ctx.constants[h].inner { - crate::ConstantInner::Scalar { width, ref value } => Self::Value(Ti::Scalar { - kind: value.scalar_kind(), - width, - }), - crate::ConstantInner::Composite { ty, components: _ } => Self::Handle(ty), + crate::Expression::Constant(h) => match self.constants[h].inner { + crate::ConstantInner::Scalar { width, ref value } => { + TypeResolution::Value(Ti::Scalar { + kind: value.scalar_kind(), + width, + }) + } + crate::ConstantInner::Composite { ty, components: _ } => TypeResolution::Handle(ty), }, - crate::Expression::Compose { ty, .. } => Self::Handle(ty), + crate::Expression::Compose { ty, .. } => TypeResolution::Handle(ty), crate::Expression::FunctionArgument(index) => { - Self::Handle(ctx.arguments[index as usize].ty) + TypeResolution::Handle(self.arguments[index as usize].ty) } crate::Expression::GlobalVariable(h) => { - let var = &ctx.global_vars[h]; + let var = &self.global_vars[h]; if var.class == crate::StorageClass::Handle { - Self::Handle(var.ty) + TypeResolution::Handle(var.ty) } else { - Self::Value(Ti::Pointer { + TypeResolution::Value(Ti::Pointer { base: var.ty, class: var.class, }) } } crate::Expression::LocalVariable(h) => { - let var = &ctx.local_vars[h]; - Self::Value(Ti::Pointer { + let var = &self.local_vars[h]; + TypeResolution::Value(Ti::Pointer { base: var.ty, class: crate::StorageClass::Function, }) } crate::Expression::Load { pointer } => match *past(pointer).inner_with(types) { - Ti::Pointer { base, class: _ } => Self::Handle(base), + Ti::Pointer { base, class: _ } => TypeResolution::Handle(base), Ti::ValuePointer { size, kind, width, class: _, - } => Self::Value(match size { + } => TypeResolution::Value(match size { Some(size) => Ti::Vector { size, kind, width }, None => Ti::Scalar { kind, width }, }), @@ -321,7 +311,7 @@ impl TypeResolution { }, crate::Expression::ImageSample { image, .. } | crate::Expression::ImageLoad { image, .. } => match *past(image).inner_with(types) { - Ti::Image { class, .. } => Self::Value(match class { + Ti::Image { class, .. } => TypeResolution::Value(match class { crate::ImageClass::Depth => Ti::Scalar { kind: crate::ScalarKind::Float, width: 4, @@ -342,7 +332,7 @@ impl TypeResolution { return Err(ResolveError::InvalidImage(image)); } }, - crate::Expression::ImageQuery { image, query } => Self::Value(match query { + crate::Expression::ImageQuery { image, query } => TypeResolution::Value(match query { crate::ImageQuery::Size { level: _ } => match *past(image).inner_with(types) { Ti::Image { dim, .. } => match dim { crate::ImageDimension::D1 => Ti::Scalar { @@ -395,7 +385,7 @@ impl TypeResolution { width, } = *ty_left { - Self::Value(Ti::Vector { + TypeResolution::Value(Ti::Vector { size: rows, kind: crate::ScalarKind::Float, width, @@ -406,7 +396,7 @@ impl TypeResolution { width, } = *ty_right { - Self::Value(Ti::Vector { + TypeResolution::Value(Ti::Vector { size: columns, kind: crate::ScalarKind::Float, width, @@ -438,7 +428,7 @@ impl TypeResolution { ))) } }; - Self::Value(inner) + TypeResolution::Value(inner) } crate::BinaryOperator::And | crate::BinaryOperator::ExclusiveOr @@ -448,7 +438,7 @@ impl TypeResolution { }, crate::Expression::Select { accept, .. } => past(accept).clone(), crate::Expression::Derivative { axis: _, expr } => past(expr).clone(), - crate::Expression::Relational { .. } => Self::Value(Ti::Scalar { + crate::Expression::Relational { .. } => TypeResolution::Value(Ti::Scalar { kind: crate::ScalarKind::Bool, width: 4, }), @@ -498,7 +488,7 @@ impl TypeResolution { kind, size: _, width, - } => Self::Value(Ti::Scalar { kind, width }), + } => TypeResolution::Value(Ti::Scalar { kind, width }), ref other => return Err(ResolveError::IncompatibleOperands( format!("{:?}({:?}, _)", fun, other) @@ -509,7 +499,7 @@ impl TypeResolution { format!("{:?}(_, None)", fun) ))?; match (res_arg.inner_with(types), past(arg1).inner_with(types)) { - (&Ti::Vector {kind: _, size: columns,width}, &Ti::Vector{ size: rows, .. }) => Self::Value(Ti::Matrix { columns, rows, width }), + (&Ti::Vector {kind: _, size: columns,width}, &Ti::Vector{ size: rows, .. }) => TypeResolution::Value(Ti::Matrix { columns, rows, width }), (left, right) => return Err(ResolveError::IncompatibleOperands( format!("{:?}({:?}, {:?})", fun, left, right) @@ -520,7 +510,7 @@ impl TypeResolution { Mf::Distance | Mf::Length => match *res_arg.inner_with(types) { Ti::Scalar {width,kind} | - Ti::Vector {width,kind,size:_} => Self::Value(Ti::Scalar { kind, width }), + Ti::Vector {width,kind,size:_} => TypeResolution::Value(Ti::Scalar { kind, width }), ref other => return Err(ResolveError::IncompatibleOperands( format!("{:?}({:?})", fun, other) )), @@ -541,7 +531,7 @@ impl TypeResolution { columns, rows, width, - } => Self::Value(Ti::Matrix { + } => TypeResolution::Value(Ti::Matrix { columns: rows, rows: columns, width, @@ -555,7 +545,7 @@ impl TypeResolution { columns, rows, width, - } if columns == rows => Self::Value(Ti::Matrix { + } if columns == rows => TypeResolution::Value(Ti::Matrix { columns, rows, width, @@ -568,7 +558,7 @@ impl TypeResolution { Ti::Matrix { width, .. - } => Self::Value(Ti::Scalar { kind: crate::ScalarKind::Float, width }), + } => TypeResolution::Value(Ti::Scalar { kind: crate::ScalarKind::Float, width }), ref other => return Err(ResolveError::IncompatibleOperands( format!("{:?}({:?})", fun, other) )), @@ -583,12 +573,12 @@ impl TypeResolution { kind, convert: _, } => match *past(expr).inner_with(types) { - Ti::Scalar { kind: _, width } => Self::Value(Ti::Scalar { kind, width }), + Ti::Scalar { kind: _, width } => TypeResolution::Value(Ti::Scalar { kind, width }), Ti::Vector { kind: _, size, width, - } => Self::Value(Ti::Vector { kind, size, width }), + } => TypeResolution::Value(Ti::Vector { kind, size, width }), ref other => { return Err(ResolveError::IncompatibleOperands(format!( "{:?} as {:?}", @@ -597,13 +587,13 @@ impl TypeResolution { } }, crate::Expression::Call(function) => { - let result = ctx.functions[function] + let result = self.functions[function] .result .as_ref() .ok_or(ResolveError::FunctionReturnsVoid)?; - Self::Handle(result.ty) + TypeResolution::Handle(result.ty) } - crate::Expression::ArrayLength(_) => Self::Value(Ti::Scalar { + crate::Expression::ArrayLength(_) => TypeResolution::Value(Ti::Scalar { kind: crate::ScalarKind::Uint, width: 4, }), @@ -611,89 +601,8 @@ impl TypeResolution { } } -impl Typifier { - pub fn new() -> Self { - Typifier { - resolutions: Vec::new(), - } - } - - pub fn clear(&mut self) { - self.resolutions.clear() - } - - //TODO: remove most of these - pub fn get<'a>( - &'a self, - expr_handle: Handle, - types: &'a Arena, - ) -> &'a crate::TypeInner { - match self.resolutions[expr_handle.index()] { - TypeResolution::Handle(ty_handle) => &types[ty_handle].inner, - TypeResolution::Value(ref inner) => inner, - } - } - - pub fn try_get<'a>( - &'a self, - expr_handle: Handle, - types: &'a Arena, - ) -> Option<&'a crate::TypeInner> { - let resolution = self.resolutions.get(expr_handle.index())?; - Some(match *resolution { - TypeResolution::Handle(ty_handle) => &types[ty_handle].inner, - TypeResolution::Value(ref inner) => inner, - }) - } - - pub fn get_handle( - &self, - expr_handle: Handle, - ) -> Result, &crate::TypeInner> { - match self.resolutions[expr_handle.index()] { - TypeResolution::Handle(ty_handle) => Ok(ty_handle), - TypeResolution::Value(ref inner) => Err(inner), - } - } - - pub fn grow( - &mut self, - expr_handle: Handle, - expressions: &Arena, - types: &mut Arena, - ctx: &ResolveContext, - ) -> Result<(), ResolveError> { - if self.resolutions.len() <= expr_handle.index() { - for (eh, expr) in expressions.iter().skip(self.resolutions.len()) { - let resolution = - TypeResolution::new(expr, types, ctx, |h| &self.resolutions[h.index()])?; - log::debug!("Resolving {:?} = {:?} : {:?}", eh, expr, resolution); - self.resolutions.push(resolution); - } - } - Ok(()) - } - - pub fn resolve_all( - &mut self, - expressions: &Arena, - types: &Arena, - ctx: &ResolveContext, - ) -> Result<(), TypifyError> { - self.clear(); - for (handle, expr) in expressions.iter() { - let resolution = - TypeResolution::new(expr, types, ctx, |h| &self.resolutions[h.index()]) - .map_err(|err| TypifyError(handle, err))?; - self.resolutions.push(resolution); - } - Ok(()) - } -} - #[test] fn test_error_size() { use std::mem::size_of; assert_eq!(size_of::(), 32); - assert_eq!(size_of::(), 40); } diff --git a/src/valid/analyzer.rs b/src/valid/analyzer.rs index bcb63316be..fba0df9857 100644 --- a/src/valid/analyzer.rs +++ b/src/valid/analyzer.rs @@ -499,9 +499,8 @@ impl FunctionInfo { }, }; - let ty = TypeResolution::new(expression, type_arena, resolve_context, |h| { - &self.expressions[h.index()].ty - })?; + let ty = + resolve_context.resolve(expression, type_arena, |h| &self.expressions[h.index()].ty)?; self.expressions[handle.index()] = ExpressionInfo { uniformity, ref_count: 0,