diff --git a/src/context.rs b/src/context.rs index e1211f3..e5aa3c8 100644 --- a/src/context.rs +++ b/src/context.rs @@ -888,7 +888,6 @@ interners! { crate::AttrSetDef, crate::TypeDef, crate::ConstDef, - crate::DataInstFormDef, } // FIXME(eddyb) consider a more uniform naming scheme than the combination @@ -897,7 +896,6 @@ interners! { AttrSet default(crate::AttrSetDef::default()) => crate::AttrSetDef, Type => crate::TypeDef, Const => crate::ConstDef, - DataInstForm => crate::DataInstFormDef, } impl InternInCx for I::Def diff --git a/src/func_at.rs b/src/func_at.rs index dec61e5..70d0424 100644 --- a/src/func_at.rs +++ b/src/func_at.rs @@ -116,7 +116,7 @@ impl FuncAt<'_, Value> { Value::NodeOutput { node, output_idx } => { self.at(node).def().outputs[output_idx as usize].ty } - Value::DataInstOutput(inst) => cx[self.at(inst).def().form].output_type.unwrap(), + Value::DataInstOutput(inst) => self.at(inst).def().output_type.unwrap(), } } } diff --git a/src/lib.rs b/src/lib.rs index 97b0cee..7b83ec3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -934,26 +934,10 @@ pub use context::DataInst; pub struct DataInstDef { pub attrs: AttrSet, - pub form: DataInstForm, + pub kind: DataInstKind, // FIXME(eddyb) change the inline size of this to fit most instructions. pub inputs: SmallVec<[Value; 2]>, -} - -/// Interned handle for a [`DataInstFormDef`](crate::DataInstFormDef) -/// (a "form", or "template", for [`DataInstDef`](crate::DataInstDef)s). -pub use context::DataInstForm; - -/// "Form" (or "template") definition for [`DataInstFormDef`]s, which includes -/// most of their common *static* information (notably excluding `attrs`, as -/// they vary more often due to handling diagnostics, debuginfo, refinement etc.). -// -// FIXME(eddyb) now that this is interned, try to find all the code that was -// working around needing to borrow `DataInstKind`, just because it was owned -// by a `FuncDefBody` (instead of interned in the `Context`). -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct DataInstFormDef { - pub kind: DataInstKind, pub output_type: Option, } diff --git a/src/passes/legalize.rs b/src/passes/legalize.rs index 57e9690..79d9bcf 100644 --- a/src/passes/legalize.rs +++ b/src/passes/legalize.rs @@ -1,7 +1,5 @@ use crate::visit::{InnerVisit, Visitor}; -use crate::{ - AttrSet, Const, Context, DataInstForm, DeclDef, Func, FxIndexSet, GlobalVar, Module, Type, cfg, -}; +use crate::{AttrSet, Const, Context, DeclDef, Func, FxIndexSet, GlobalVar, Module, Type, cfg}; /// Apply the [`cfg::Structurizer`] algorithm to all function definitions in `module`. pub fn structurize_func_cfgs(module: &mut Module) { @@ -14,7 +12,6 @@ pub fn structurize_func_cfgs(module: &mut Module) { seen_types: FxIndexSet::default(), seen_consts: FxIndexSet::default(), - seen_data_inst_forms: FxIndexSet::default(), seen_global_vars: FxIndexSet::default(), seen_funcs: FxIndexSet::default(), }; @@ -37,7 +34,6 @@ struct ReachableUseCollector<'a> { // FIXME(eddyb) build some automation to avoid ever repeating these. seen_types: FxIndexSet, seen_consts: FxIndexSet, - seen_data_inst_forms: FxIndexSet, seen_global_vars: FxIndexSet, seen_funcs: FxIndexSet, } @@ -57,11 +53,6 @@ impl Visitor<'_> for ReachableUseCollector<'_> { self.visit_const_def(&self.cx[ct]); } } - fn visit_data_inst_form_use(&mut self, data_inst_form: DataInstForm) { - if self.seen_data_inst_forms.insert(data_inst_form) { - self.visit_data_inst_form_def(&self.cx[data_inst_form]); - } - } fn visit_global_var_use(&mut self, gv: GlobalVar) { if self.seen_global_vars.insert(gv) { diff --git a/src/passes/link.rs b/src/passes/link.rs index d2bdd69..68c56b3 100644 --- a/src/passes/link.rs +++ b/src/passes/link.rs @@ -1,8 +1,8 @@ use crate::transform::{InnerTransform, Transformed, Transformer}; use crate::visit::{InnerVisit, Visitor}; use crate::{ - AttrSet, Const, Context, DataInstForm, DeclDef, ExportKey, Exportee, Func, FxIndexSet, - GlobalVar, Import, Module, Type, + AttrSet, Const, Context, DeclDef, ExportKey, Exportee, Func, FxIndexSet, GlobalVar, Import, + Module, Type, }; use rustc_hash::{FxHashMap, FxHashSet}; use std::collections::VecDeque; @@ -33,7 +33,6 @@ pub fn minimize_exports(module: &mut Module, is_root: impl Fn(&ExportKey) -> boo seen_types: FxHashSet::default(), seen_consts: FxHashSet::default(), - seen_data_inst_forms: FxHashSet::default(), seen_global_vars: FxHashSet::default(), seen_funcs: FxHashSet::default(), }; @@ -61,7 +60,6 @@ struct LiveExportCollector<'a> { // FIXME(eddyb) build some automation to avoid ever repeating these. seen_types: FxHashSet, seen_consts: FxHashSet, - seen_data_inst_forms: FxHashSet, seen_global_vars: FxHashSet, seen_funcs: FxHashSet, } @@ -81,11 +79,6 @@ impl Visitor<'_> for LiveExportCollector<'_> { self.visit_const_def(&self.cx[ct]); } } - fn visit_data_inst_form_use(&mut self, data_inst_form: DataInstForm) { - if self.seen_data_inst_forms.insert(data_inst_form) { - self.visit_data_inst_form_def(&self.cx[data_inst_form]); - } - } fn visit_global_var_use(&mut self, gv: GlobalVar) { if self.seen_global_vars.insert(gv) { @@ -128,7 +121,6 @@ pub fn resolve_imports(module: &mut Module) { seen_types: FxHashSet::default(), seen_consts: FxHashSet::default(), - seen_data_inst_forms: FxHashSet::default(), seen_global_vars: FxHashSet::default(), seen_funcs: FxHashSet::default(), }; @@ -144,7 +136,6 @@ pub fn resolve_imports(module: &mut Module) { transformed_types: FxHashMap::default(), transformed_consts: FxHashMap::default(), - transformed_data_inst_forms: FxHashMap::default(), transformed_global_vars: FxHashMap::default(), global_var_queue: VecDeque::new(), transformed_funcs: FxHashMap::default(), @@ -179,7 +170,6 @@ struct ImportResolutionCollector<'a> { // FIXME(eddyb) build some automation to avoid ever repeating these. seen_types: FxHashSet, seen_consts: FxHashSet, - seen_data_inst_forms: FxHashSet, seen_global_vars: FxHashSet, seen_funcs: FxHashSet, } @@ -199,11 +189,6 @@ impl Visitor<'_> for ImportResolutionCollector<'_> { self.visit_const_def(&self.cx[ct]); } } - fn visit_data_inst_form_use(&mut self, data_inst_form: DataInstForm) { - if self.seen_data_inst_forms.insert(data_inst_form) { - self.visit_data_inst_form_def(&self.cx[data_inst_form]); - } - } fn visit_global_var_use(&mut self, gv: GlobalVar) { if self.seen_global_vars.insert(gv) { @@ -250,7 +235,6 @@ struct ImportResolver<'a> { // FIXME(eddyb) build some automation to avoid ever repeating these. transformed_types: FxHashMap>, transformed_consts: FxHashMap>, - transformed_data_inst_forms: FxHashMap>, transformed_global_vars: FxHashMap>, global_var_queue: VecDeque, transformed_funcs: FxHashMap>, @@ -277,19 +261,6 @@ impl Transformer for ImportResolver<'_> { self.transformed_consts.insert(ct, transformed); transformed } - fn transform_data_inst_form_use( - &mut self, - data_inst_form: DataInstForm, - ) -> Transformed { - if let Some(&cached) = self.transformed_data_inst_forms.get(&data_inst_form) { - return cached; - } - let transformed = self - .transform_data_inst_form_def(&self.cx[data_inst_form]) - .map(|data_inst_form_def| self.cx.intern(data_inst_form_def)); - self.transformed_data_inst_forms.insert(data_inst_form, transformed); - transformed - } fn transform_global_var_use(&mut self, gv: GlobalVar) -> Transformed { if let Some(&cached) = self.transformed_global_vars.get(&gv) { diff --git a/src/passes/qptr.rs b/src/passes/qptr.rs index a0fb9b0..0cf95ef 100644 --- a/src/passes/qptr.rs +++ b/src/passes/qptr.rs @@ -1,8 +1,8 @@ //! [`QPtr`](crate::TypeKind::QPtr) transforms. +use crate::qptr; use crate::visit::{InnerVisit, Visitor}; use crate::{AttrSet, Const, Context, Func, FxIndexSet, GlobalVar, Module, Type}; -use crate::{DataInstForm, qptr}; pub fn lower_from_spv_ptrs(module: &mut Module, layout_config: &qptr::LayoutConfig) { let cx = &module.cx(); @@ -15,7 +15,6 @@ pub fn lower_from_spv_ptrs(module: &mut Module, layout_config: &qptr::LayoutConf seen_types: FxIndexSet::default(), seen_consts: FxIndexSet::default(), - seen_data_inst_forms: FxIndexSet::default(), seen_global_vars: FxIndexSet::default(), seen_funcs: FxIndexSet::default(), }; @@ -50,7 +49,6 @@ pub fn lift_to_spv_ptrs(module: &mut Module, layout_config: &qptr::LayoutConfig) seen_types: FxIndexSet::default(), seen_consts: FxIndexSet::default(), - seen_data_inst_forms: FxIndexSet::default(), seen_global_vars: FxIndexSet::default(), seen_funcs: FxIndexSet::default(), }; @@ -75,7 +73,6 @@ struct ReachableUseCollector<'a> { // FIXME(eddyb) build some automation to avoid ever repeating these. seen_types: FxIndexSet, seen_consts: FxIndexSet, - seen_data_inst_forms: FxIndexSet, seen_global_vars: FxIndexSet, seen_funcs: FxIndexSet, } @@ -95,11 +92,6 @@ impl Visitor<'_> for ReachableUseCollector<'_> { self.visit_const_def(&self.cx[ct]); } } - fn visit_data_inst_form_use(&mut self, data_inst_form: DataInstForm) { - if self.seen_data_inst_forms.insert(data_inst_form) { - self.visit_data_inst_form_def(&self.cx[data_inst_form]); - } - } fn visit_global_var_use(&mut self, gv: GlobalVar) { if self.seen_global_vars.insert(gv) { diff --git a/src/print/mod.rs b/src/print/mod.rs index 649125f..e3c8c51 100644 --- a/src/print/mod.rs +++ b/src/print/mod.rs @@ -25,11 +25,11 @@ use crate::qptr::{self, QPtrAttr, QPtrMemUsage, QPtrMemUsageKind, QPtrOp, QPtrUs use crate::visit::{InnerVisit, Visit, Visitor}; use crate::{ AddrSpace, Attr, AttrSet, AttrSetDef, Const, ConstDef, ConstKind, Context, DataInst, - DataInstDef, DataInstForm, DataInstFormDef, DataInstKind, DbgSrcLoc, DeclDef, Diag, DiagLevel, - DiagMsgPart, EntityListIter, ExportKey, Exportee, Func, FuncDecl, FuncParam, FxIndexMap, - FxIndexSet, GlobalVar, GlobalVarDecl, GlobalVarDefBody, Import, Module, ModuleDebugInfo, - ModuleDialect, Node, NodeDef, NodeKind, NodeOutputDecl, OrdAssertEq, Region, RegionDef, - RegionInputDecl, SelectionKind, Type, TypeDef, TypeKind, TypeOrConst, Value, cfg, spv, + DataInstDef, DataInstKind, DbgSrcLoc, DeclDef, Diag, DiagLevel, DiagMsgPart, EntityListIter, + ExportKey, Exportee, Func, FuncDecl, FuncParam, FxIndexMap, FxIndexSet, GlobalVar, + GlobalVarDecl, GlobalVarDefBody, Import, Module, ModuleDebugInfo, ModuleDialect, Node, NodeDef, + NodeKind, NodeOutputDecl, OrdAssertEq, Region, RegionDef, RegionInputDecl, SelectionKind, Type, + TypeDef, TypeKind, TypeOrConst, Value, cfg, spv, }; use arrayvec::ArrayVec; use itertools::Either; @@ -463,12 +463,6 @@ impl<'a> Visitor<'a> for Plan<'a> { fn visit_const_use(&mut self, ct: Const) { self.use_interned(CxInterned::Const(ct)); } - fn visit_data_inst_form_use(&mut self, data_inst_form: DataInstForm) { - // NOTE(eddyb) this contains no deduplication because each `DataInstDef` - // will be pretty-printed separately, so everything in its `form` also - // needs to get use counts incremented separately per-`DataInstDef`. - self.visit_data_inst_form_def(&self.cx[data_inst_form]); - } fn visit_global_var_use(&mut self, gv: GlobalVar) { if let Some(module) = self.current_module { @@ -974,7 +968,7 @@ impl<'a> Printer<'a> { None, ); let inst_def = func_at_inst.def(); - if cx[inst_def.form].output_type.is_some() { + if inst_def.output_type.is_some() { define( Use::DataInstOutput(func_at_inst.position), Some(inst_def.attrs), @@ -1000,7 +994,6 @@ impl<'a> Printer<'a> { fn visit_attr_set_use(&mut self, _: AttrSet) {} fn visit_type_use(&mut self, _: Type) {} fn visit_const_use(&mut self, _: Const) {} - fn visit_data_inst_form_use(&mut self, _: DataInstForm) {} fn visit_global_var_use(&mut self, _: GlobalVar) {} fn visit_func_use(&mut self, _: Func) {} @@ -3153,12 +3146,10 @@ impl Print for NodeOutputDecl { impl Print for FuncAt<'_, DataInst> { type Output = pretty::Fragment; fn print(&self, printer: &Printer<'_>) -> pretty::Fragment { - let DataInstDef { attrs, form, inputs } = self.def(); + let DataInstDef { attrs, kind, inputs, output_type } = self.def(); let attrs = attrs.print(printer); - let DataInstFormDef { kind, output_type } = &printer.cx[*form]; - let mut output_use_to_print_as_lhs = output_type.map(|_| Use::DataInstOutput(self.position)); diff --git a/src/qptr/analyze.rs b/src/qptr/analyze.rs index 2ad1112..df7acc7 100644 --- a/src/qptr/analyze.rs +++ b/src/qptr/analyze.rs @@ -7,9 +7,9 @@ use super::{QPtrAttr, QPtrMemUsage, QPtrOp, QPtrUsage, shapes}; use crate::func_at::FuncAt; use crate::visit::{InnerVisit, Visitor}; use crate::{ - AddrSpace, Attr, AttrSet, AttrSetDef, Const, ConstKind, Context, DataInst, DataInstForm, - DataInstKind, DeclDef, Diag, EntityList, ExportKey, Exportee, Func, FxIndexMap, GlobalVar, - Module, Node, NodeKind, OrdAssertEq, Type, TypeKind, Value, + AddrSpace, Attr, AttrSet, AttrSetDef, Const, ConstKind, Context, DataInst, DataInstKind, + DeclDef, Diag, EntityList, ExportKey, Exportee, Func, FxIndexMap, GlobalVar, Module, Node, + NodeKind, OrdAssertEq, Type, TypeKind, Value, }; use itertools::Either; use rustc_hash::FxHashMap; @@ -866,7 +866,6 @@ impl<'a> InferUsage<'a> { for func_at_inst in func_def_body.at(insts).into_iter().rev() { let data_inst = func_at_inst.position; let data_inst_def = func_at_inst.def(); - let data_inst_form_def = &cx[data_inst_def.form]; let output_usage = data_inst_output_usages.remove(&data_inst).flatten(); let mut generate_usage = |this: &mut Self, ptr: Value, new_usage| { @@ -904,7 +903,7 @@ impl<'a> InferUsage<'a> { None => new_usage, }); }; - match &data_inst_form_def.kind { + match &data_inst_def.kind { &DataInstKind::FuncCall(callee) => { match self.infer_usage_in_func(module, callee) { FuncInferUsageState::Complete(callee_results) => { @@ -925,7 +924,7 @@ impl<'a> InferUsage<'a> { )); } }; - if data_inst_form_def.output_type.map_or(false, is_qptr) { + if data_inst_def.output_type.map_or(false, is_qptr) { if let Some(usage) = output_usage { usage_or_err_attrs_to_attach .push((Value::DataInstOutput(data_inst), usage)); @@ -1108,7 +1107,7 @@ impl<'a> InferUsage<'a> { } DataInstKind::QPtr(op @ (QPtrOp::Load | QPtrOp::Store)) => { let (op_name, access_type) = match op { - QPtrOp::Load => ("Load", data_inst_form_def.output_type.unwrap()), + QPtrOp::Load => ("Load", data_inst_def.output_type.unwrap()), QPtrOp::Store => { ("Store", func_at_inst.at(data_inst_def.inputs[1]).type_of(&cx)) } @@ -1250,7 +1249,6 @@ impl Visitor<'_> for CollectAllDataInsts { fn visit_attr_set_use(&mut self, _: AttrSet) {} fn visit_type_use(&mut self, _: Type) {} fn visit_const_use(&mut self, _: Const) {} - fn visit_data_inst_form_use(&mut self, _: DataInstForm) {} fn visit_global_var_use(&mut self, _: GlobalVar) {} fn visit_func_use(&mut self, _: Func) {} diff --git a/src/qptr/lift.rs b/src/qptr/lift.rs index e4c88b7..4fe0e1a 100644 --- a/src/qptr/lift.rs +++ b/src/qptr/lift.rs @@ -8,9 +8,9 @@ use crate::qptr::{QPtrAttr, QPtrMemUsage, QPtrMemUsageKind, QPtrOp, QPtrUsage, s use crate::transform::{InnerInPlaceTransform, InnerTransform, Transformed, Transformer}; use crate::{ AddrSpace, Attr, AttrSet, AttrSetDef, Const, ConstDef, ConstKind, Context, DataInst, - DataInstDef, DataInstFormDef, DataInstKind, DeclDef, Diag, DiagLevel, EntityDefs, - EntityOrientedDenseMap, Func, FuncDecl, FxIndexMap, GlobalVar, GlobalVarDecl, Module, Node, - NodeKind, Type, TypeDef, TypeKind, TypeOrConst, Value, spv, + DataInstDef, DataInstKind, DeclDef, Diag, DiagLevel, EntityDefs, EntityOrientedDenseMap, Func, + FuncDecl, FxIndexMap, GlobalVar, GlobalVarDecl, Module, Node, NodeKind, Type, TypeDef, + TypeKind, TypeOrConst, Value, spv, }; use smallvec::SmallVec; use std::cell::Cell; @@ -425,7 +425,6 @@ impl LiftToSpvPtrInstsInFunc<'_> { let func_at_data_inst_frozen = func_at_data_inst.reborrow().freeze(); let data_inst = func_at_data_inst_frozen.position; let data_inst_def = func_at_data_inst_frozen.def(); - let data_inst_form_def = &cx[data_inst_def.form]; let func = func_at_data_inst_frozen.at(()); let type_of_val = |v: Value| func.at(v).type_of(cx); // FIXME(eddyb) maybe all this data should be packaged up together in a @@ -447,7 +446,7 @@ impl LiftToSpvPtrInstsInFunc<'_> { Ok((addr_space, self.lifter.layout_of(pointee_type)?)) }; - let replacement_data_inst_def = match &data_inst_form_def.kind { + let replacement_data_inst_def = match &data_inst_def.kind { &DataInstKind::FuncCall(_callee) => { for &v in &data_inst_def.inputs { if self.lifter.as_spv_ptr_type(type_of_val(v)).is_some() { @@ -466,21 +465,15 @@ impl LiftToSpvPtrInstsInFunc<'_> { let pointee_type = self.lifter.pointee_type_for_usage(qptr_usage)?; DataInstDef { attrs: self.lifter.strip_qptr_usage_attr(data_inst_def.attrs), - form: cx.intern(DataInstFormDef { - kind: DataInstKind::SpvInst(spv::Inst { - opcode: wk.OpVariable, - imms: [spv::Imm::Short(wk.StorageClass, wk.Function)] - .into_iter() - .collect(), - }), - output_type: Some( - self.lifter.spv_ptr_type( - AddrSpace::SpvStorageClass(wk.Function), - pointee_type, - ), - ), + kind: DataInstKind::SpvInst(spv::Inst { + opcode: wk.OpVariable, + imms: [spv::Imm::Short(wk.StorageClass, wk.Function)].into_iter().collect(), }), inputs: data_inst_def.inputs.clone(), + output_type: Some( + self.lifter + .spv_ptr_type(AddrSpace::SpvStorageClass(wk.Function), pointee_type), + ), } } DataInstKind::QPtr(QPtrOp::HandleArrayIndex) => { @@ -504,11 +497,9 @@ impl LiftToSpvPtrInstsInFunc<'_> { }; DataInstDef { attrs: data_inst_def.attrs, - form: cx.intern(DataInstFormDef { - kind: DataInstKind::SpvInst(wk.OpAccessChain.into()), - output_type: Some(self.lifter.spv_ptr_type(addr_space, handle_type)), - }), + kind: DataInstKind::SpvInst(wk.OpAccessChain.into()), inputs: data_inst_def.inputs.clone(), + output_type: Some(self.lifter.spv_ptr_type(addr_space, handle_type)), } } DataInstKind::QPtr(QPtrOp::BufferData) => { @@ -528,13 +519,10 @@ impl LiftToSpvPtrInstsInFunc<'_> { }); DataInstDef { - // FIXME(eddyb) avoid the repeated call to `type_of_val` - // (and the interning of a temporary `DataInstFormDef`), - // maybe don't even replace the `QPtrOp::Buffer` instruction? - form: cx.intern(DataInstFormDef { - kind: QPtrOp::BufferData.into(), - output_type: Some(type_of_val(buf_ptr)), - }), + kind: QPtrOp::BufferData.into(), + // FIXME(eddyb) avoid the repeated call to `type_of_val`, + // maybe don't even replace the `QPtrOp::BufferData` instruction? + output_type: Some(type_of_val(buf_ptr)), ..data_inst_def.clone() } } @@ -571,14 +559,9 @@ impl LiftToSpvPtrInstsInFunc<'_> { }; DataInstDef { - form: cx.intern(DataInstFormDef { - kind: DataInstKind::SpvInst(spv::Inst { - opcode: wk.OpArrayLength, - imms: [spv::Imm::Short(wk.LiteralInteger, field_idx)] - .into_iter() - .collect(), - }), - output_type: data_inst_form_def.output_type, + kind: DataInstKind::SpvInst(spv::Inst { + opcode: wk.OpArrayLength, + imms: [spv::Imm::Short(wk.LiteralInteger, field_idx)].into_iter().collect(), }), ..data_inst_def.clone() } @@ -663,26 +646,22 @@ impl LiftToSpvPtrInstsInFunc<'_> { output_pointee_layout: TypeLayout::Concrete(layout), parent_block, }); + + // FIXME(eddyb) avoid the repeated call to `type_of_val`, + // maybe don't even replace the `QPtrOp::Offset` instruction? DataInstDef { - // FIXME(eddyb) avoid the repeated call to `type_of_val` - // (and the interning of a temporary `DataInstFormDef`), - // maybe don't even replace the `QPtrOp::Offset` instruction? - form: cx.intern(DataInstFormDef { - kind: QPtrOp::Offset(0).into(), - output_type: Some(type_of_val(base_ptr)), - }), + kind: QPtrOp::Offset(0).into(), + output_type: Some(type_of_val(base_ptr)), ..data_inst_def.clone() } } else { DataInstDef { attrs: data_inst_def.attrs, - form: cx.intern(DataInstFormDef { - kind: DataInstKind::SpvInst(wk.OpAccessChain.into()), - output_type: Some( - self.lifter.spv_ptr_type(addr_space, layout.original_type), - ), - }), + kind: DataInstKind::SpvInst(wk.OpAccessChain.into()), inputs: access_chain_inputs, + output_type: Some( + self.lifter.spv_ptr_type(addr_space, layout.original_type), + ), } } } @@ -761,18 +740,14 @@ impl LiftToSpvPtrInstsInFunc<'_> { } DataInstDef { attrs: data_inst_def.attrs, - form: cx.intern(DataInstFormDef { - kind: DataInstKind::SpvInst(wk.OpAccessChain.into()), - output_type: Some( - self.lifter.spv_ptr_type(addr_space, layout.original_type), - ), - }), + kind: DataInstKind::SpvInst(wk.OpAccessChain.into()), inputs: access_chain_inputs, + output_type: Some(self.lifter.spv_ptr_type(addr_space, layout.original_type)), } } DataInstKind::QPtr(op @ (QPtrOp::Load | QPtrOp::Store)) => { let (spv_opcode, access_type) = match op { - QPtrOp::Load => (wk.OpLoad, data_inst_form_def.output_type.unwrap()), + QPtrOp::Load => (wk.OpLoad, data_inst_def.output_type.unwrap()), QPtrOp::Store => (wk.OpStore, type_of_val(data_inst_def.inputs[1])), _ => unreachable!(), }; @@ -793,10 +768,7 @@ impl LiftToSpvPtrInstsInFunc<'_> { }; let mut new_data_inst_def = DataInstDef { - form: cx.intern(DataInstFormDef { - kind: DataInstKind::SpvInst(spv_opcode.into()), - output_type: data_inst_form_def.output_type, - }), + kind: DataInstKind::SpvInst(spv_opcode.into()), ..data_inst_def.clone() }; @@ -906,10 +878,8 @@ impl LiftToSpvPtrInstsInFunc<'_> { } if let Some((addr_space, pointee_type)) = from_spv_ptr_output { - new_data_inst_def.form = cx.intern(DataInstFormDef { - output_type: Some(self.lifter.spv_ptr_type(addr_space, pointee_type)), - ..cx[new_data_inst_def.form].clone() - }); + new_data_inst_def.output_type = + Some(self.lifter.spv_ptr_type(addr_space, pointee_type)); } new_data_inst_def @@ -1023,11 +993,9 @@ impl LiftToSpvPtrInstsInFunc<'_> { Ok(if access_chain_inputs.len() > 1 { Some(DataInstDef { attrs: Default::default(), - form: self.lifter.cx.intern(DataInstFormDef { - kind: DataInstKind::SpvInst(wk.OpAccessChain.into()), - output_type: Some(self.lifter.spv_ptr_type(addr_space, access_type)), - }), + kind: DataInstKind::SpvInst(wk.OpAccessChain.into()), inputs: access_chain_inputs, + output_type: Some(self.lifter.spv_ptr_type(addr_space, access_type)), }) } else { None @@ -1117,11 +1085,10 @@ impl Transformer for LiftToSpvPtrInstsInFunc<'_> { let mut lifted = self.try_lift_data_inst_def(func_at_inst.reborrow(), node); if let Ok(Transformed::Unchanged) = lifted { let data_inst_def = func_at_inst.reborrow().def(); - let data_inst_form_def = &self.lifter.cx[data_inst_def.form]; - if let DataInstKind::QPtr(_) = data_inst_form_def.kind { + if let DataInstKind::QPtr(_) = data_inst_def.kind { lifted = Err(LiftError(Diag::bug(["unimplemented qptr instruction".into()]))); - } else if let Some(ty) = data_inst_form_def.output_type { + } else if let Some(ty) = data_inst_def.output_type { if matches!(self.lifter.cx[ty].kind, TypeKind::QPtr) { lifted = Err(LiftError(Diag::bug([ "unimplemented qptr-producing instruction".into(), diff --git a/src/qptr/lower.rs b/src/qptr/lower.rs index 7878b98..fc947da 100644 --- a/src/qptr/lower.rs +++ b/src/qptr/lower.rs @@ -8,8 +8,8 @@ use crate::qptr::{QPtrAttr, QPtrOp, shapes}; use crate::transform::{InnerInPlaceTransform, Transformed, Transformer}; use crate::{ AddrSpace, AttrSet, AttrSetDef, Const, ConstDef, ConstKind, Context, DataInst, DataInstDef, - DataInstForm, DataInstFormDef, DataInstKind, Diag, FuncDecl, GlobalVarDecl, Node, NodeKind, - OrdAssertEq, Type, TypeKind, TypeOrConst, Value, spv, + DataInstKind, Diag, FuncDecl, GlobalVarDecl, Node, NodeKind, OrdAssertEq, Type, TypeKind, + TypeOrConst, Value, spv, }; use smallvec::SmallVec; use std::cell::Cell; @@ -232,19 +232,6 @@ impl Transformer for EraseSpvPtrs<'_> { Transformed::Unchanged } } - - // FIXME(eddyb) because this is now interned, it might be better to - // temporarily track the old output types in a map, and not actually - // intern the non-`qptr`-output `qptr.*` instructions, only to replace - // the output type with `qptr` here. - fn transform_data_inst_form_use( - &mut self, - data_inst_form: DataInstForm, - ) -> Transformed { - // FIXME(eddyb) maybe cache this remap (in `LowerFromSpvPtrs`, globally). - self.transform_data_inst_form_def(&self.lowerer.cx[data_inst_form]) - .map(|data_inst_form_def| self.lowerer.cx.intern(data_inst_form_def)) - } } struct LowerFromSpvPtrInstsInFunc<'a> { @@ -409,9 +396,9 @@ impl LowerFromSpvPtrInstsInFunc<'_> { let func = func_at_data_inst_frozen.at(()); let mut attrs = data_inst_def.attrs; - let DataInstFormDef { ref kind, output_type } = cx[data_inst_def.form]; + let output_type = data_inst_def.output_type; - let spv_inst = match kind { + let spv_inst = match &data_inst_def.kind { DataInstKind::SpvInst(spv_inst) => spv_inst, _ => return Ok(Transformed::Unchanged), }; @@ -549,11 +536,9 @@ impl LowerFromSpvPtrInstsInFunc<'_> { cx, DataInstDef { attrs: Default::default(), - form: cx.intern(DataInstFormDef { - kind, - output_type: Some(self.lowerer.qptr_type()), - }), + kind, inputs, + output_type: Some(self.lowerer.qptr_type()), } .into(), ); @@ -600,11 +585,9 @@ impl LowerFromSpvPtrInstsInFunc<'_> { let (new_kind, new_inputs) = replacement_kind_and_inputs; Ok(Transformed::Changed(DataInstDef { attrs, - // FIXME(eddyb) because this is now interned, it might be better to - // temporarily track the old output types in a map, and not actually - // intern the non-`qptr`-output `qptr.*` instructions. - form: cx.intern(DataInstFormDef { kind: new_kind, output_type }), + kind: new_kind, inputs: new_inputs, + output_type, })) } @@ -617,12 +600,11 @@ impl LowerFromSpvPtrInstsInFunc<'_> { let func_at_data_inst_frozen = func_at_data_inst.reborrow().freeze(); let data_inst_def = func_at_data_inst_frozen.def(); - let data_inst_form_def = &cx[data_inst_def.form]; // FIXME(eddyb) is this a good convention? let func = func_at_data_inst_frozen.at(()); - match data_inst_form_def.kind { + match data_inst_def.kind { // Known semantics, no need to preserve SPIR-V pointer information. DataInstKind::FuncCall(_) | DataInstKind::QPtr(_) => return, @@ -643,7 +625,7 @@ impl LowerFromSpvPtrInstsInFunc<'_> { ); } } - if let Some(output_type) = data_inst_form_def.output_type { + if let Some(output_type) = data_inst_def.output_type { if let Some((addr_space, pointee)) = self.lowerer.as_spv_ptr_type(output_type) { old_and_new_attrs.get_or_insert_with(get_old_attrs).attrs.insert( QPtrAttr::FromSpvPtrOutput { diff --git a/src/spv/lift.rs b/src/spv/lift.rs index 1da234d..7d50611 100644 --- a/src/spv/lift.rs +++ b/src/spv/lift.rs @@ -5,10 +5,10 @@ use crate::spv::{self, spec}; use crate::visit::{InnerVisit, Visitor}; use crate::{ AddrSpace, Attr, AttrSet, Const, ConstDef, ConstKind, Context, DataInst, DataInstDef, - DataInstForm, DataInstFormDef, DataInstKind, DbgSrcLoc, DeclDef, EntityList, ExportKey, - Exportee, Func, FuncDecl, FuncParam, FxIndexMap, FxIndexSet, GlobalVar, GlobalVarDefBody, - Import, Module, ModuleDebugInfo, ModuleDialect, Node, NodeKind, NodeOutputDecl, OrdAssertEq, - Region, RegionInputDecl, SelectionKind, Type, TypeDef, TypeKind, TypeOrConst, Value, cfg, + DataInstKind, DbgSrcLoc, DeclDef, EntityList, ExportKey, Exportee, Func, FuncDecl, FuncParam, + FxIndexMap, FxIndexSet, GlobalVar, GlobalVarDefBody, Import, Module, ModuleDebugInfo, + ModuleDialect, Node, NodeKind, NodeOutputDecl, OrdAssertEq, Region, RegionInputDecl, + SelectionKind, Type, TypeDef, TypeKind, TypeOrConst, Value, cfg, }; use rustc_hash::FxHashMap; use smallvec::SmallVec; @@ -99,7 +99,6 @@ struct NeedsIdsCollector<'a> { debug_strings: BTreeSet<&'a str>, globals: FxIndexSet, - data_inst_forms_seen: FxIndexSet, global_vars_seen: FxIndexSet, funcs: FxIndexSet, } @@ -169,11 +168,6 @@ impl Visitor<'_> for NeedsIdsCollector<'_> { } } } - fn visit_data_inst_form_use(&mut self, data_inst_form: DataInstForm) { - if self.data_inst_forms_seen.insert(data_inst_form) { - self.visit_data_inst_form_def(&self.cx[data_inst_form]); - } - } fn visit_global_var_use(&mut self, gv: GlobalVar) { if self.global_vars_seen.insert(gv) { @@ -214,9 +208,9 @@ impl Visitor<'_> for NeedsIdsCollector<'_> { attr.inner_visit_with(self); } - fn visit_data_inst_form_def(&mut self, data_inst_form_def: &DataInstFormDef) { + fn visit_data_inst_def(&mut self, data_inst_def: &DataInstDef) { #[allow(clippy::match_same_arms)] - match data_inst_form_def.kind { + match data_inst_def.kind { // FIXME(eddyb) this should be a proper `Result`-based error instead, // and/or `spv::lift` should mutate the module for legalization. DataInstKind::QPtr(_) => { @@ -230,7 +224,7 @@ impl Visitor<'_> for NeedsIdsCollector<'_> { self.ext_inst_imports.insert(&self.cx[ext_set]); } } - data_inst_form_def.inner_visit_with(self); + data_inst_def.inner_visit_with(self); } } @@ -359,7 +353,6 @@ impl<'a> NeedsIdsCollector<'a> { ext_inst_imports, debug_strings, globals, - data_inst_forms_seen: _, global_vars_seen: _, funcs, } = self; @@ -959,7 +952,7 @@ impl<'a> FuncLifting<'a> { .values() .flat_map(|block| block.insts.iter().copied()) .flat_map(|insts| func_def_body.at(insts)) - .filter(|&func_at_inst| cx[func_at_inst.def().form].output_type.is_some()) + .filter(|&func_at_inst| func_at_inst.def().output_type.is_some()) .map(|func_at_inst| func_at_inst.position); Ok(Self { @@ -1227,8 +1220,7 @@ impl LazyInst<'_, '_> { .collect(), }, Self::DataInst { parent_func, result_id: _, data_inst_def } => { - let DataInstFormDef { kind, output_type } = &cx[data_inst_def.form]; - let (inst, extra_initial_id_operand) = match kind { + let (inst, extra_initial_id_operand) = match &data_inst_def.kind { // Disallowed while visiting. DataInstKind::QPtr(_) => unreachable!(), @@ -1247,7 +1239,9 @@ impl LazyInst<'_, '_> { }; spv::InstWithIds { without_ids: inst, - result_type_id: output_type.map(|ty| ids.globals[&Global::Type(ty)]), + result_type_id: data_inst_def + .output_type + .map(|ty| ids.globals[&Global::Type(ty)]), result_id, ids: extra_initial_id_operand .into_iter() @@ -1354,7 +1348,6 @@ impl Module { ext_inst_imports: BTreeSet::new(), debug_strings: BTreeSet::new(), globals: FxIndexSet::default(), - data_inst_forms_seen: FxIndexSet::default(), global_vars_seen: FxIndexSet::default(), funcs: FxIndexSet::default(), }; @@ -1427,12 +1420,10 @@ impl Module { let data_inst_def = func_at_inst.def(); LazyInst::DataInst { parent_func: func_lifting, - result_id: cx[data_inst_def.form].output_type.map( - |_| { - func_lifting.data_inst_output_ids - [&func_at_inst.position] - }, - ), + result_id: data_inst_def.output_type.map(|_| { + func_lifting.data_inst_output_ids + [&func_at_inst.position] + }), data_inst_def, } }), diff --git a/src/spv/lower.rs b/src/spv/lower.rs index e99d6b6..eb7b6f6 100644 --- a/src/spv/lower.rs +++ b/src/spv/lower.rs @@ -3,11 +3,11 @@ use crate::spv::{self, spec}; // FIXME(eddyb) import more to avoid `crate::` everywhere. use crate::{ - AddrSpace, Attr, AttrSet, Const, ConstDef, ConstKind, Context, DataInstDef, DataInstFormDef, - DataInstKind, DbgSrcLoc, DeclDef, Diag, EntityDefs, EntityList, ExportKey, Exportee, Func, - FuncDecl, FuncDefBody, FuncParam, FxIndexMap, GlobalVarDecl, GlobalVarDefBody, Import, - InternedStr, Module, NodeDef, NodeKind, Region, RegionDef, RegionInputDecl, SelectionKind, - Type, TypeDef, TypeKind, TypeOrConst, Value, cfg, print, + AddrSpace, Attr, AttrSet, Const, ConstDef, ConstKind, Context, DataInstDef, DataInstKind, + DbgSrcLoc, DeclDef, Diag, EntityDefs, EntityList, ExportKey, Exportee, Func, FuncDecl, + FuncDefBody, FuncParam, FxIndexMap, GlobalVarDecl, GlobalVarDefBody, Import, InternedStr, + Module, NodeDef, NodeKind, Region, RegionDef, RegionInputDecl, SelectionKind, Type, TypeDef, + TypeKind, TypeOrConst, Value, cfg, print, }; use rustc_hash::FxHashMap; use smallvec::SmallVec; @@ -820,18 +820,6 @@ impl Module { return Err(invalid("OpFunction without matching OpFunctionEnd")); } - // HACK(eddyb) `OpNop` is useful for defining `DataInst`s before they're - // actually lowered (to be able to refer to their outputs `Value`s). - let mut cached_op_nop_form = None; - let mut get_op_nop_form = || { - *cached_op_nop_form.get_or_insert_with(|| { - cx.intern(DataInstFormDef { - kind: DataInstKind::SpvInst(wk.OpNop.into()), - output_type: None, - }) - }) - }; - // Process function bodies, having seen the whole module. for func_body in pending_func_bodies { let FuncBody { func_id, func, insts: raw_insts } = func_body; @@ -969,9 +957,9 @@ impl Module { &cx, DataInstDef { attrs: AttrSet::default(), - // FIXME(eddyb) cache this form locally. - form: get_op_nop_form(), + kind: DataInstKind::SpvInst(wk.OpNop.into()), inputs: [].into_iter().collect(), + output_type: None, } .into(), ); @@ -1523,19 +1511,7 @@ impl Module { let data_inst_def = DataInstDef { attrs, - form: cx.intern(DataInstFormDef { - kind, - output_type: result_id - .map(|_| { - result_type.ok_or_else(|| { - invalid( - "expected value-producing instruction, \ - with a result type", - ) - }) - }) - .transpose()?, - }), + kind, inputs: ids .iter() .map(|&id| { @@ -1549,6 +1525,16 @@ impl Module { } }) .collect::>()?, + output_type: result_id + .map(|_| { + result_type.ok_or_else(|| { + invalid( + "expected value-producing instruction, \ + with a result type", + ) + }) + }) + .transpose()?, }; let inst = match result_id { Some(id) => match local_id_defs[&id] { diff --git a/src/spv/mod.rs b/src/spv/mod.rs index eb5a2e7..bd9e7f5 100644 --- a/src/spv/mod.rs +++ b/src/spv/mod.rs @@ -58,8 +58,6 @@ pub struct Inst { // FIXME(eddyb) change the inline size of this to fit most instructions. // FIXME(eddyb) it might be worth investigating the performance implications // of interning "long immediates", compared to the flattened representation. - // NOTE(eddyb) interning these separately is likely unnecessary in many cases, - // now that `DataInstForm`s are interned, and `Const`s etc. were already. pub imms: SmallVec<[Imm; 2]>, } diff --git a/src/transform.rs b/src/transform.rs index c49c6d3..74670d3 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -4,11 +4,11 @@ use crate::func_at::FuncAtMut; use crate::qptr::{self, QPtrAttr, QPtrMemUsage, QPtrMemUsageKind, QPtrOp, QPtrUsage}; use crate::{ AddrSpace, Attr, AttrSet, AttrSetDef, Const, ConstDef, ConstKind, DataInst, DataInstDef, - DataInstForm, DataInstFormDef, DataInstKind, DbgSrcLoc, DeclDef, EntityListIter, ExportKey, - Exportee, Func, FuncDecl, FuncDefBody, FuncParam, GlobalVar, GlobalVarDecl, GlobalVarDefBody, - Import, Module, ModuleDebugInfo, ModuleDialect, Node, NodeDef, NodeKind, NodeOutputDecl, - OrdAssertEq, Region, RegionDef, RegionInputDecl, SelectionKind, Type, TypeDef, TypeKind, - TypeOrConst, Value, cfg, spv, + DataInstKind, DbgSrcLoc, DeclDef, EntityListIter, ExportKey, Exportee, Func, FuncDecl, + FuncDefBody, FuncParam, GlobalVar, GlobalVarDecl, GlobalVarDefBody, Import, Module, + ModuleDebugInfo, ModuleDialect, Node, NodeDef, NodeKind, NodeOutputDecl, OrdAssertEq, Region, + RegionDef, RegionInputDecl, SelectionKind, Type, TypeDef, TypeKind, TypeOrConst, Value, cfg, + spv, }; use std::cmp::Ordering; use std::rc::Rc; @@ -145,12 +145,6 @@ pub trait Transformer: Sized { fn transform_const_use(&mut self, _ct: Const) -> Transformed { Transformed::Unchanged } - fn transform_data_inst_form_use( - &mut self, - _data_inst_form: DataInstForm, - ) -> Transformed { - Transformed::Unchanged - } // Module-stored entity leaves (noop default behavior). fn transform_global_var_use(&mut self, _gv: GlobalVar) -> Transformed { @@ -178,12 +172,6 @@ pub trait Transformer: Sized { fn transform_const_def(&mut self, ct_def: &ConstDef) -> Transformed { ct_def.inner_transform_with(self) } - fn transform_data_inst_form_def( - &mut self, - data_inst_form_def: &DataInstFormDef, - ) -> Transformed { - data_inst_form_def.inner_transform_with(self) - } fn transform_value_use(&mut self, v: &Value) -> Transformed { v.inner_transform_with(self) } @@ -711,43 +699,35 @@ impl InnerTransform for NodeOutputDecl { impl InnerInPlaceTransform for FuncAtMut<'_, DataInst> { fn inner_in_place_transform_with(&mut self, transformer: &mut impl Transformer) { - let DataInstDef { attrs, form, inputs } = self.reborrow().def(); + let DataInstDef { attrs, kind, inputs, output_type } = self.reborrow().def(); transformer.transform_attr_set_use(*attrs).apply_to(attrs); - transformer.transform_data_inst_form_use(*form).apply_to(form); + kind.inner_in_place_transform_with(transformer); for v in inputs { transformer.transform_value_use(v).apply_to(v); } + if let Some(output_type) = output_type { + transformer.transform_type_use(*output_type).apply_to(output_type); + } } } -impl InnerTransform for DataInstFormDef { - fn inner_transform_with(&self, transformer: &mut impl Transformer) -> Transformed { - let Self { kind, output_type } = self; - - transform!({ - kind -> match kind { - DataInstKind::FuncCall(func) => transformer.transform_func_use(*func).map(DataInstKind::FuncCall), - DataInstKind::QPtr(op) => match op { - QPtrOp::FuncLocalVar(_) - | QPtrOp::HandleArrayIndex - | QPtrOp::BufferData - | QPtrOp::BufferDynLen { .. } - | QPtrOp::Offset(_) - | QPtrOp::DynOffset { .. } - | QPtrOp::Load - | QPtrOp::Store => Transformed::Unchanged, - }, - DataInstKind::SpvInst(_) | DataInstKind::SpvExtInst { .. } => Transformed::Unchanged, +impl InnerInPlaceTransform for DataInstKind { + fn inner_in_place_transform_with(&mut self, transformer: &mut impl Transformer) { + match self { + DataInstKind::FuncCall(func) => transformer.transform_func_use(*func).apply_to(func), + DataInstKind::QPtr(op) => match op { + QPtrOp::FuncLocalVar(_) + | QPtrOp::HandleArrayIndex + | QPtrOp::BufferData + | QPtrOp::BufferDynLen { .. } + | QPtrOp::Offset(_) + | QPtrOp::DynOffset { .. } + | QPtrOp::Load + | QPtrOp::Store => {} }, - // FIXME(eddyb) this should be replaced with an impl of `InnerTransform` - // for `Option` or some other helper, to avoid "manual transpose". - output_type -> output_type.map(|ty| transformer.transform_type_use(ty)) - .map_or(Transformed::Unchanged, |t| t.map(Some)), - } => Self { - kind, - output_type, - }) + DataInstKind::SpvInst(_) | DataInstKind::SpvExtInst { .. } => {} + } } } diff --git a/src/visit.rs b/src/visit.rs index 1bba627..1829c46 100644 --- a/src/visit.rs +++ b/src/visit.rs @@ -3,12 +3,12 @@ use crate::func_at::FuncAt; use crate::qptr::{self, QPtrAttr, QPtrMemUsage, QPtrMemUsageKind, QPtrOp, QPtrUsage}; use crate::{ - AddrSpace, Attr, AttrSet, AttrSetDef, Const, ConstDef, ConstKind, DataInstDef, DataInstForm, - DataInstFormDef, DataInstKind, DbgSrcLoc, DeclDef, DiagMsgPart, EntityListIter, ExportKey, - Exportee, Func, FuncDecl, FuncDefBody, FuncParam, GlobalVar, GlobalVarDecl, GlobalVarDefBody, - Import, Module, ModuleDebugInfo, ModuleDialect, Node, NodeDef, NodeKind, NodeOutputDecl, - OrdAssertEq, Region, RegionDef, RegionInputDecl, SelectionKind, Type, TypeDef, TypeKind, - TypeOrConst, Value, cfg, spv, + AddrSpace, Attr, AttrSet, AttrSetDef, Const, ConstDef, ConstKind, DataInstDef, DataInstKind, + DbgSrcLoc, DeclDef, DiagMsgPart, EntityListIter, ExportKey, Exportee, Func, FuncDecl, + FuncDefBody, FuncParam, GlobalVar, GlobalVarDecl, GlobalVarDefBody, Import, Module, + ModuleDebugInfo, ModuleDialect, Node, NodeDef, NodeKind, NodeOutputDecl, OrdAssertEq, Region, + RegionDef, RegionInputDecl, SelectionKind, Type, TypeDef, TypeKind, TypeOrConst, Value, cfg, + spv, }; // FIXME(eddyb) `Sized` bound shouldn't be needed but removing it requires @@ -20,7 +20,6 @@ pub trait Visitor<'a>: Sized { fn visit_attr_set_use(&mut self, attrs: AttrSet); fn visit_type_use(&mut self, ty: Type); fn visit_const_use(&mut self, ct: Const); - fn visit_data_inst_form_use(&mut self, data_inst_form: DataInstForm); // Module-stored entity leaves (no default provided). fn visit_global_var_use(&mut self, gv: GlobalVar); @@ -68,9 +67,6 @@ pub trait Visitor<'a>: Sized { fn visit_data_inst_def(&mut self, data_inst_def: &'a DataInstDef) { data_inst_def.inner_visit_with(self); } - fn visit_data_inst_form_def(&mut self, data_inst_form_def: &'a DataInstFormDef) { - data_inst_form_def.inner_visit_with(self); - } fn visit_value_use(&mut self, v: &'a Value) { v.inner_visit_with(self); } @@ -521,21 +517,22 @@ impl InnerVisit for NodeOutputDecl { impl InnerVisit for DataInstDef { fn inner_visit_with<'a>(&'a self, visitor: &mut impl Visitor<'a>) { - let Self { attrs, form, inputs } = self; + let Self { attrs, kind, inputs, output_type } = self; visitor.visit_attr_set_use(*attrs); - visitor.visit_data_inst_form_use(*form); + kind.inner_visit_with(visitor); for v in inputs { visitor.visit_value_use(v); } + if let Some(ty) = *output_type { + visitor.visit_type_use(ty); + } } } -impl InnerVisit for DataInstFormDef { +impl InnerVisit for DataInstKind { fn inner_visit_with<'a>(&'a self, visitor: &mut impl Visitor<'a>) { - let Self { kind, output_type } = self; - - match kind { + match self { &DataInstKind::FuncCall(func) => visitor.visit_func_use(func), DataInstKind::QPtr(op) => match *op { QPtrOp::FuncLocalVar(_) @@ -549,9 +546,6 @@ impl InnerVisit for DataInstFormDef { }, DataInstKind::SpvInst(_) | DataInstKind::SpvExtInst { .. } => {} } - if let Some(ty) = *output_type { - visitor.visit_type_use(ty); - } } }