diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index 651ea5c6ab..54c5c7e583 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, ResolveContext, Typifier, TypifyError}, + proc::{EntryPointIndex, NameKey, Namer, TypeResolution, TypifyError}, valid::{FunctionInfo, ModuleInfo}, Arena, ArraySize, BinaryOperator, Binding, BuiltIn, Bytes, ConservativeDepth, Constant, ConstantInner, DerivativeAxis, Expression, FastHashMap, Function, GlobalVariable, Handle, @@ -185,18 +185,16 @@ enum FunctionType { } /// Helper structure that stores data needed when writing the function -struct FunctionCtx<'a, 'b> { +struct FunctionCtx<'a> { /// The current function being written func: FunctionType, /// Analysis about the function info: &'a FunctionInfo, /// The expression arena of the current function being written expressions: &'a Arena, - /// A typifier that has already resolved all expressions in the function being written - typifier: &'b Typifier, } -impl<'a, 'b> FunctionCtx<'a, 'b> { +impl<'a> FunctionCtx<'a> { /// Helper method that generates a [`NameKey`](crate::proc::NameKey) for a local in the current function fn name_key(&self, local: Handle) -> NameKey { match self.func { @@ -855,26 +853,11 @@ impl<'a, W: Write> Writer<'a, W> { info: &FunctionInfo, name: &str, ) -> BackendResult { - // Create a new typifier and resolve all types for the current function - let mut typifier = Typifier::new(); - typifier.resolve_all( - &func.expressions, - &self.module.types, - &ResolveContext { - constants: &self.module.constants, - global_vars: &self.module.global_variables, - local_vars: &func.local_variables, - functions: &self.module.functions, - arguments: &func.arguments, - }, - )?; - // Create a function context for the function being written let ctx = FunctionCtx { func: ty, info, expressions: &func.expressions, - typifier: &typifier, }; self.cached_expressions.clear(); @@ -1166,7 +1149,7 @@ impl<'a, W: Write> Writer<'a, W> { fn write_stmt( &mut self, sta: &Statement, - ctx: &FunctionCtx<'_, '_>, + ctx: &FunctionCtx<'_>, indent: usize, ) -> BackendResult { match *sta { @@ -1176,17 +1159,19 @@ impl<'a, W: Write> Writer<'a, W> { let min_ref_count = ctx.expressions[handle].bake_ref_count(); if min_ref_count <= ctx.info[handle].ref_count { write!(self.out, "{}", INDENT.repeat(indent))?; - match ctx.typifier.get_handle(handle) { - Ok(ty_handle) => match self.module.types[ty_handle].inner { - TypeInner::Struct { .. } => { - let ty_name = &self.names[&NameKey::Type(ty_handle)]; - write!(self.out, "{}", ty_name)?; + match ctx.info[handle].ty { + TypeResolution::Handle(ty_handle) => { + match self.module.types[ty_handle].inner { + TypeInner::Struct { .. } => { + let ty_name = &self.names[&NameKey::Type(ty_handle)]; + write!(self.out, "{}", ty_name)?; + } + _ => { + self.write_type(ty_handle)?; + } } - _ => { - self.write_type(ty_handle)?; - } - }, - Err(inner) => { + } + TypeResolution::Value(ref inner) => { self.write_value_type(inner)?; } } @@ -1413,7 +1398,7 @@ impl<'a, W: Write> Writer<'a, W> { } => { write!(self.out, "{}", INDENT.repeat(indent))?; // This will only panic if the module is invalid - let dim = match *ctx.typifier.get(image, &self.module.types) { + let dim = match *ctx.info[image].ty.inner_with(&self.module.types) { TypeInner::Image { dim, .. } => dim, _ => unreachable!(), }; @@ -1453,7 +1438,7 @@ impl<'a, W: Write> Writer<'a, W> { /// /// # Notes /// Doesn't add any newlines or leading/trailing spaces - fn write_expr(&mut self, expr: Handle, ctx: &FunctionCtx<'_, '_>) -> BackendResult { + fn write_expr(&mut self, expr: Handle, ctx: &FunctionCtx<'_>) -> BackendResult { if let Some(name) = self.cached_expressions.get(&expr) { write!(self.out, "{}", name)?; return Ok(()); @@ -1472,13 +1457,14 @@ impl<'a, W: Write> Writer<'a, W> { Expression::AccessIndex { base, index } => { self.write_expr(base, ctx)?; - let mut resolved = ctx.typifier.get(base, &self.module.types); + let base_ty_res = &ctx.info[base].ty; + let mut resolved = base_ty_res.inner_with(&self.module.types); let base_ty_handle = match *resolved { TypeInner::Pointer { base, class: _ } => { resolved = &self.module.types[base].inner; - Ok(base) + Some(base) } - _ => ctx.typifier.get_handle(base), + _ => base_ty_res.handle(), }; match *resolved { @@ -1576,7 +1562,7 @@ impl<'a, W: Write> Writer<'a, W> { // We need to get the coordinates vector size to later build a vector that's `size + 1` // if `depth_ref` is some, if it isn't a vector we panic as that's not a valid expression - let size = match *ctx.typifier.get(coordinate, &self.module.types) { + let size = match *ctx.info[coordinate].ty.inner_with(&self.module.types) { TypeInner::Vector { size, .. } => size, _ => unreachable!(), }; @@ -1652,7 +1638,7 @@ impl<'a, W: Write> Writer<'a, W> { index, } => { // This will only panic if the module is invalid - let (dim, class) = match *ctx.typifier.get(image, &self.module.types) { + let (dim, class) = match *ctx.info[image].ty.inner_with(&self.module.types) { TypeInner::Image { dim, arrayed: _, @@ -1685,7 +1671,7 @@ impl<'a, W: Write> Writer<'a, W> { // - textureSamples/imageSamples Expression::ImageQuery { image, query } => { // This will only panic if the module is invalid - let (dim, class) = match *ctx.typifier.get(image, &self.module.types) { + let (dim, class) = match *ctx.info[image].ty.inner_with(&self.module.types) { TypeInner::Image { dim, arrayed: _, @@ -1759,25 +1745,26 @@ impl<'a, W: Write> Writer<'a, W> { "({} ", match op { UnaryOperator::Negate => "-", - UnaryOperator::Not => match *ctx.typifier.get(expr, &self.module.types) { - TypeInner::Scalar { - kind: ScalarKind::Sint, - .. - } => "~", - TypeInner::Scalar { - kind: ScalarKind::Uint, - .. - } => "~", - TypeInner::Scalar { - kind: ScalarKind::Bool, - .. - } => "!", - ref other => - return Err(Error::Custom(format!( - "Cannot apply not to type {:?}", - other - ))), - }, + UnaryOperator::Not => + match *ctx.info[expr].ty.inner_with(&self.module.types) { + TypeInner::Scalar { + kind: ScalarKind::Sint, + .. + } => "~", + TypeInner::Scalar { + kind: ScalarKind::Uint, + .. + } => "~", + TypeInner::Scalar { + kind: ScalarKind::Bool, + .. + } => "!", + ref other => + return Err(Error::Custom(format!( + "Cannot apply not to type {:?}", + other + ))), + }, } )?; @@ -1793,8 +1780,8 @@ impl<'a, W: Write> Writer<'a, W> { // Holds `Some(function_name)` if the binary operation is // implemented as a function call let function = if let (&TypeInner::Vector { .. }, &TypeInner::Vector { .. }) = ( - ctx.typifier.get(left, &self.module.types), - ctx.typifier.get(right, &self.module.types), + ctx.info[left].ty.inner_with(&self.module.types), + ctx.info[right].ty.inner_with(&self.module.types), ) { match op { BinaryOperator::Less => Some("lessThan"), @@ -1979,7 +1966,7 @@ impl<'a, W: Write> Writer<'a, W> { kind, convert, } => { - let inner = ctx.typifier.get(expr, &self.module.types); + let inner = ctx.info[expr].ty.inner_with(&self.module.types); if convert { // this is similar to `write_type`, but with the target kind match *inner { diff --git a/src/back/msl/writer.rs b/src/back/msl/writer.rs index f9c8e7eb1d..f6246da9c5 100644 --- a/src/back/msl/writer.rs +++ b/src/back/msl/writer.rs @@ -1,7 +1,7 @@ use super::{keywords::RESERVED, Error, LocationMode, Options, TranslationInfo}; use crate::{ arena::Handle, - proc::{EntryPointIndex, NameKey, Namer, ResolveContext, Typifier}, + proc::{EntryPointIndex, NameKey, Namer, TypeResolution}, valid::{FunctionInfo, GlobalUse, ModuleInfo}, FastHashMap, }; @@ -68,7 +68,6 @@ pub struct Writer { out: W, names: FastHashMap, named_expressions: BitSet, - typifier: Typifier, namer: Namer, #[cfg(test)] put_expression_stack_pointers: crate::FastHashSet<*const ()>, @@ -138,13 +137,19 @@ enum FunctionOrigin { struct ExpressionContext<'a> { function: &'a crate::Function, origin: FunctionOrigin, + info: &'a FunctionInfo, module: &'a crate::Module, - mod_info: &'a ModuleInfo, +} + +impl<'a> ExpressionContext<'a> { + fn resolve_type(&self, handle: Handle) -> &'a crate::TypeInner { + self.info[handle].ty.inner_with(&self.module.types) + } } struct StatementContext<'a> { expression: ExpressionContext<'a>, - fun_info: &'a FunctionInfo, + mod_info: &'a ModuleInfo, result_struct: Option<&'a str>, } @@ -155,7 +160,6 @@ impl Writer { out, names: FastHashMap::default(), named_expressions: BitSet::new(), - typifier: Typifier::new(), namer: Namer::default(), #[cfg(test)] put_expression_stack_pointers: Default::default(), @@ -226,13 +230,14 @@ impl Writer { } crate::Expression::AccessIndex { base, index } => { self.put_expression(base, context)?; - let mut resolved = self.typifier.get(base, &context.module.types); + let base_res = &context.info[base].ty; + let mut resolved = base_res.inner_with(&context.module.types); let base_ty_handle = match *resolved { crate::TypeInner::Pointer { base, class: _ } => { resolved = &context.module.types[base].inner; - Ok(base) + Some(base) } - _ => self.typifier.get_handle(base), + _ => base_res.handle(), }; match *resolved { crate::TypeInner::Struct { .. } => { @@ -410,7 +415,7 @@ impl Writer { crate::ImageQuery::Size { level } => { //Note: MSL only has separate width/height/depth queries, // so compose the result of them. - let dim = match *self.typifier.get(image, &context.module.types) { + let dim = match *context.resolve_type(image) { crate::TypeInner::Image { dim, .. } => dim, ref other => unreachable!("Unexpected type {:?}", other), }; @@ -488,9 +493,8 @@ impl Writer { crate::BinaryOperator::ShiftLeft => "<<", crate::BinaryOperator::ShiftRight => ">>", }; - let kind = self - .typifier - .get(left, &context.module.types) + let kind = context + .resolve_type(left) .scalar_kind() .ok_or(Error::UnsupportedBinaryOp(op))?; if op == crate::BinaryOperator::Modulo && kind == crate::ScalarKind::Float { @@ -615,7 +619,7 @@ impl Writer { convert, } => { let scalar = scalar_kind_string(kind); - let size = match *self.typifier.get(expr, &context.module.types) { + let size = match *context.resolve_type(expr) { crate::TypeInner::Scalar { .. } => "", crate::TypeInner::Vector { size, .. } => vector_size_string(size), _ => return Err(Error::Validation), @@ -627,37 +631,39 @@ impl Writer { } // has to be a named expression crate::Expression::Call(_) => unreachable!(), - crate::Expression::ArrayLength(expr) => { - match *self.typifier.get(expr, &context.module.types) { - crate::TypeInner::Array { - size: crate::ArraySize::Constant(const_handle), - .. - } => { - let size_str = &self.names[&NameKey::Constant(const_handle)]; - write!(self.out, "{}", size_str)?; - } - crate::TypeInner::Array { .. } => { - return Err(Error::FeatureNotImplemented( - "dynamic array size".to_string(), - )) - } - _ => return Err(Error::Validation), + crate::Expression::ArrayLength(expr) => match *context.resolve_type(expr) { + crate::TypeInner::Array { + size: crate::ArraySize::Constant(const_handle), + .. + } => { + let size_str = &self.names[&NameKey::Constant(const_handle)]; + write!(self.out, "{}", size_str)?; } - } + crate::TypeInner::Array { .. } => { + return Err(Error::FeatureNotImplemented( + "dynamic array size".to_string(), + )) + } + _ => return Err(Error::Validation), + }, } Ok(()) } - fn start_baking_expression(&mut self, handle: Handle) -> Result<(), Error> { - match self.typifier.get_handle(handle) { - Ok(ty_handle) => { + fn start_baking_expression( + &mut self, + handle: Handle, + context: &ExpressionContext, + ) -> Result<(), Error> { + match context.info[handle].ty { + TypeResolution::Handle(ty_handle) => { let ty_name = &self.names[&NameKey::Type(ty_handle)]; write!(self.out, "{}", ty_name)?; } - Err(&crate::TypeInner::Scalar { kind, .. }) => { + TypeResolution::Value(crate::TypeInner::Scalar { kind, .. }) => { write!(self.out, "{}", scalar_kind_string(kind))?; } - Err(&crate::TypeInner::Vector { size, kind, .. }) => { + TypeResolution::Value(crate::TypeInner::Vector { size, kind, .. }) => { write!( self.out, "{}::{}{}", @@ -666,7 +672,7 @@ impl Writer { vector_size_string(size) )?; } - Err(other) => { + TypeResolution::Value(ref other) => { log::error!("Type {:?} isn't a known local", other); return Err(Error::FeatureNotImplemented("weird local type".to_string())); } @@ -690,9 +696,9 @@ impl Writer { for handle in range.clone() { let min_ref_count = context.expression.function.expressions[handle].bake_ref_count(); - if min_ref_count <= context.fun_info[handle].ref_count { + if min_ref_count <= context.expression.info[handle].ref_count { write!(self.out, "{}", level)?; - self.start_baking_expression(handle)?; + self.start_baking_expression(handle, &context.expression)?; self.put_expression(handle, &context.expression)?; writeln!(self.out, ";")?; self.named_expressions.insert(handle.index()); @@ -843,7 +849,7 @@ impl Writer { } => { write!(self.out, "{}", level)?; if let Some(expr) = result { - self.start_baking_expression(expr)?; + self.start_baking_expression(expr, &context.expression)?; self.named_expressions.insert(expr.index()); } let fun_name = &self.names[&NameKey::Function(function)]; @@ -857,7 +863,7 @@ impl Writer { } // follow-up with any global resources used let mut separate = !arguments.is_empty(); - let fun_info = &context.expression.mod_info[function]; + let fun_info = &context.mod_info[function]; for (handle, var) in context.expression.module.global_variables.iter() { if !fun_info[handle].is_empty() && var.class.needs_pass_through() { let name = &self.names[&NameKey::GlobalVariable(handle)]; @@ -1109,18 +1115,6 @@ impl Writer { ) -> Result { let mut pass_through_globals = Vec::new(); for (fun_handle, fun) in module.functions.iter() { - self.typifier.resolve_all( - &fun.expressions, - &module.types, - &ResolveContext { - constants: &module.constants, - global_vars: &module.global_variables, - local_vars: &fun.local_variables, - functions: &module.functions, - arguments: &fun.arguments, - }, - )?; - let fun_info = &mod_info[fun_handle]; pass_through_globals.clear(); for (handle, var) in module.global_variables.iter() { @@ -1176,10 +1170,10 @@ impl Writer { expression: ExpressionContext { function: fun, origin: FunctionOrigin::Handle(fun_handle), + info: fun_info, module, - mod_info, }, - fun_info, + mod_info, result_struct: None, }; self.named_expressions.clear(); @@ -1215,18 +1209,6 @@ impl Writer { } } - self.typifier.resolve_all( - &fun.expressions, - &module.types, - &ResolveContext { - constants: &module.constants, - global_vars: &module.global_variables, - local_vars: &fun.local_variables, - functions: &module.functions, - arguments: &fun.arguments, - }, - )?; - let fun_name = &self.names[&NameKey::EntryPoint(ep_index as _)]; info.entry_point_names.push(Ok(fun_name.clone())); @@ -1468,10 +1450,10 @@ impl Writer { expression: ExpressionContext { function: fun, origin: FunctionOrigin::EntryPoint(ep_index as _), + info: fun_info, module, - mod_info, }, - fun_info, + mod_info, result_struct: Some(&stage_out_name), }; self.named_expressions.clear(); diff --git a/src/back/spv/writer.rs b/src/back/spv/writer.rs index 912a840a1d..5e065e1cad 100644 --- a/src/back/spv/writer.rs +++ b/src/back/spv/writer.rs @@ -2,7 +2,7 @@ use super::{Instruction, LogicalLayout, Options, PhysicalLayout, WriterFlags}; use crate::{ arena::{Arena, Handle}, - proc::{Layouter, ResolveContext, Typifier, TypifyError}, + proc::{Layouter, TypeResolution}, valid::{FunctionInfo, ModuleInfo}, }; use spirv::Word; @@ -19,8 +19,6 @@ pub enum Error { MissingCapabilities(Vec), #[error("unimplemented {0}")] FeatureNotImplemented(&'static str), - #[error(transparent)] - Resolve(#[from] TypifyError), } struct Block { @@ -263,7 +261,6 @@ pub struct Writer { struct_type_handles: crate::FastHashMap, crate::StorageAccess>, gl450_ext_inst_id: Word, layouter: Layouter, - typifier: Typifier, temp_chain: Vec, } @@ -295,7 +292,6 @@ impl Writer { struct_type_handles: crate::FastHashMap::default(), gl450_ext_inst_id, layouter: Layouter::default(), - typifier: Typifier::new(), temp_chain: Vec::new(), }) } @@ -378,18 +374,6 @@ impl Writer { ) -> Result { let mut function = Function::default(); - self.typifier.resolve_all( - &ir_function.expressions, - &ir_module.types, - &ResolveContext { - constants: &ir_module.constants, - global_vars: &ir_module.global_variables, - local_vars: &ir_function.local_variables, - functions: &ir_module.functions, - arguments: &ir_function.arguments, - }, - )?; - for (handle, variable) in ir_function.local_variables.iter() { let id = self.generate_id(); @@ -559,6 +543,7 @@ impl Writer { self.cache_expression_value( ir_module, ir_function, + info, handle, &mut prelude, &mut function, @@ -573,6 +558,7 @@ impl Writer { &ir_function.body, ir_module, ir_function, + info, &mut function, None, LoopContext::default(), @@ -1209,6 +1195,7 @@ impl Writer { fn write_texture_coordinates( &mut self, ir_module: &crate::Module, + fun_info: &FunctionInfo, coordinates: Handle, array_index: Option>, block: &mut Block, @@ -1227,7 +1214,7 @@ impl Writer { )?; let mut constituent_ids = [0u32; 4]; - let size = match *self.typifier.get(coordinates, &ir_module.types) { + let size = match *fun_info[coordinates].ty.inner_with(&ir_module.types) { crate::TypeInner::Scalar { .. } => { constituent_ids[0] = coordinate_id; crate::VectorSize::Bi @@ -1291,13 +1278,16 @@ impl Writer { &mut self, ir_module: &'a crate::Module, ir_function: &crate::Function, + fun_info: &FunctionInfo, expr_handle: Handle, block: &mut Block, function: &mut Function, ) -> Result<(), Error> { - let result_lookup_ty = match self.typifier.get_handle(expr_handle) { - Ok(ty_handle) => LookupType::Handle(ty_handle), - Err(inner) => LookupType::Local(self.physical_layout.make_local(inner).unwrap()), + let result_lookup_ty = match fun_info[expr_handle].ty { + TypeResolution::Handle(ty_handle) => LookupType::Handle(ty_handle), + TypeResolution::Value(ref inner) => { + LookupType::Local(self.physical_layout.make_local(inner).unwrap()) + } }; let result_type_id = self.get_type_id(&ir_module.types, result_lookup_ty)?; @@ -1313,7 +1303,7 @@ impl Writer { 0 } else { let index_id = self.cached[index]; - match *self.typifier.get(base, &ir_module.types) { + match *fun_info[base].ty.inner_with(&ir_module.types) { crate::TypeInner::Vector { .. } => { let id = self.generate_id(); let base_id = self.cached[base]; @@ -1343,7 +1333,7 @@ impl Writer { if base_is_var { 0 } else { - match *self.typifier.get(base, &ir_module.types) { + match *fun_info[base].ty.inner_with(&ir_module.types) { crate::TypeInner::Vector { .. } | crate::TypeInner::Matrix { .. } | crate::TypeInner::Array { .. } @@ -1382,7 +1372,7 @@ impl Writer { crate::Expression::Unary { op, expr } => { let id = self.generate_id(); let expr_id = self.cached[expr]; - let expr_ty_inner = self.typifier.get(expr, &ir_module.types); + let expr_ty_inner = fun_info[expr].ty.inner_with(&ir_module.types); let spirv_op = match op { crate::UnaryOperator::Negate => match expr_ty_inner.scalar_kind() { @@ -1407,8 +1397,8 @@ impl Writer { let left_id = self.cached[left]; let right_id = self.cached[right]; - let left_ty_inner = self.typifier.get(left, &ir_module.types); - let right_ty_inner = self.typifier.get(right, &ir_module.types); + let left_ty_inner = fun_info[left].ty.inner_with(&ir_module.types); + let right_ty_inner = fun_info[right].ty.inner_with(&ir_module.types); let left_dimension = get_dimension(left_ty_inner); let right_dimension = get_dimension(right_ty_inner); @@ -1543,7 +1533,7 @@ impl Writer { } let arg0_id = self.cached[arg]; - let arg_scalar_kind = self.typifier.get(arg, &ir_module.types).scalar_kind(); + let arg_scalar_kind = fun_info[arg].ty.inner_with(&ir_module.types).scalar_kind(); let arg1_id = match arg1 { Some(handle) => self.cached[handle], None => 0, @@ -1672,6 +1662,7 @@ impl Writer { let (pointer_id, _) = self.write_expression_pointer( ir_module, ir_function, + fun_info, pointer, block, function, @@ -1694,9 +1685,9 @@ impl Writer { convert, } => { let expr_id = self.cached[expr]; - let expr_kind = self - .typifier - .get(expr, &ir_module.types) + let expr_kind = fun_info[expr] + .ty + .inner_with(&ir_module.types) .scalar_kind() .unwrap(); @@ -1722,12 +1713,17 @@ impl Writer { index, } => { let image_id = self.get_expression_global(ir_function, image); - let coordinate_id = - self.write_texture_coordinates(ir_module, coordinate, array_index, block)?; + let coordinate_id = self.write_texture_coordinates( + ir_module, + fun_info, + coordinate, + array_index, + block, + )?; let id = self.generate_id(); - let image_ty = self.typifier.get(image, &ir_module.types); + let image_ty = fun_info[image].ty.inner_with(&ir_module.types); let mut instruction = match *image_ty { crate::TypeInner::Image { class: crate::ImageClass::Storage { .. }, @@ -1738,7 +1734,7 @@ impl Writer { if let Some(index) = index { let index_id = self.cached[index]; - let image_ops = match *self.typifier.get(image, &ir_module.types) { + let image_ops = match *fun_info[image].ty.inner_with(&ir_module.types) { crate::TypeInner::Image { class: crate::ImageClass::Sampled { multi: true, .. }, .. @@ -1764,7 +1760,7 @@ impl Writer { use super::instructions::SampleLod; // image let image_id = self.get_expression_global(ir_function, image); - let image_type = self.typifier.get_handle(image).unwrap(); + let image_type = fun_info[image].ty.handle().unwrap(); // OpTypeSampledImage let sampled_image_type_id = self.get_type_id( @@ -1773,8 +1769,13 @@ impl Writer { )?; let sampler_id = self.get_expression_global(ir_function, sampler); - let coordinate_id = - self.write_texture_coordinates(ir_module, coordinate, array_index, block)?; + let coordinate_id = self.write_texture_coordinates( + ir_module, + fun_info, + coordinate, + array_index, + block, + )?; let sampled_image_id = self.generate_id(); block.body.push(Instruction::sampled_image( @@ -1921,13 +1922,16 @@ impl Writer { &mut self, ir_module: &'a crate::Module, ir_function: &crate::Function, + fun_info: &FunctionInfo, mut expr_handle: Handle, block: &mut Block, function: &mut Function, ) -> Result<(Word, spirv::StorageClass), Error> { - let result_lookup_ty = match self.typifier.get_handle(expr_handle) { - Ok(ty_handle) => LookupType::Handle(ty_handle), - Err(inner) => LookupType::Local(self.physical_layout.make_local(inner).unwrap()), + let result_lookup_ty = match fun_info[expr_handle].ty { + TypeResolution::Handle(ty_handle) => LookupType::Handle(ty_handle), + TypeResolution::Value(ref inner) => { + LookupType::Local(self.physical_layout.make_local(inner).unwrap()) + } }; let result_type_id = self.get_type_id(&ir_module.types, result_lookup_ty)?; @@ -1998,6 +2002,7 @@ impl Writer { } } + //TODO: put most of these into a `BlockContext` structure! #[allow(clippy::too_many_arguments)] fn write_block( &mut self, @@ -2005,6 +2010,7 @@ impl Writer { statements: &[crate::Statement], ir_module: &crate::Module, ir_function: &crate::Function, + fun_info: &FunctionInfo, function: &mut Function, exit_id: Option, loop_context: LoopContext, @@ -2021,6 +2027,7 @@ impl Writer { self.cache_expression_value( ir_module, ir_function, + fun_info, handle, &mut block, function, @@ -2037,6 +2044,7 @@ impl Writer { block_statements, ir_module, ir_function, + fun_info, function, Some(merge_id), loop_context, @@ -2083,6 +2091,7 @@ impl Writer { accept, ir_module, ir_function, + fun_info, function, Some(merge_id), loop_context, @@ -2094,6 +2103,7 @@ impl Writer { reject, ir_module, ir_function, + fun_info, function, Some(merge_id), loop_context, @@ -2143,6 +2153,7 @@ impl Writer { &case.body, ir_module, ir_function, + fun_info, function, Some(case_finish_id), LoopContext::default(), @@ -2154,6 +2165,7 @@ impl Writer { default, ir_module, ir_function, + fun_info, function, Some(merge_id), LoopContext::default(), @@ -2187,6 +2199,7 @@ impl Writer { body, ir_module, ir_function, + fun_info, function, Some(continuing_id), LoopContext { @@ -2200,6 +2213,7 @@ impl Writer { continuing, ir_module, ir_function, + fun_info, function, Some(preamble_id), LoopContext { @@ -2263,6 +2277,7 @@ impl Writer { let (pointer_id, _) = self.write_expression_pointer( ir_module, ir_function, + fun_info, pointer, &mut block, function, @@ -2282,6 +2297,7 @@ impl Writer { let image_id = self.get_expression_global(ir_function, image); let coordinate_id = self.write_texture_coordinates( ir_module, + fun_info, coordinate, array_index, &mut block,