diff --git a/crates/autogen/src/main.rs b/crates/autogen/src/main.rs index 5a9c1b6f..2641ce0c 100644 --- a/crates/autogen/src/main.rs +++ b/crates/autogen/src/main.rs @@ -16,10 +16,19 @@ pub fn main() -> anyhow::Result<()> { pub fn autogen() -> anyhow::Result<()> { let core_json = PATH_GRAMMAR_CORE.read()?; let mut core = core_json.parse_grammar()?; + + // instructions that require custom implementations core.insts .iter_mut() - .filter(|i| i.opname == "OpSwitch") + .filter(|i| i.opname == "OpSwitch" || i.opname == "OpSpecConstantOp") .for_each(|i| i.source = Source::MetaOnly); + + // mark instructions as OpSpecOp + core.insts + .iter_mut() + .filter(|i| OP_SPEC_OP_NAMES.contains(&&*i.opname)) + .for_each(|i| i.op_spec_op = true); + write_grammar( GrammarWriter::new(Path::new(PATH_GRAMMAR_CRATE_SRC).join("core"))?, &core, @@ -29,3 +38,70 @@ pub fn autogen() -> anyhow::Result<()> { )?; Ok(()) } + +/// All instructions that are allowed in `OpSpecConstantOp`, see List at +/// +/// +/// List is not yet machine parsable, see +const OP_SPEC_OP_NAMES: &[&str] = &[ + "OpSConvert", + "OpUConvert", + "OpFConvert", + "OpSNegate", + "OpNot", + "OpIAdd", + "OpISub", + "OpIMul", + "OpUDiv", + "OpSDiv", + "OpUMod", + "OpSRem", + "OpSMod", + "OpShiftRightLogical", + "OpShiftRightArithmetic", + "OpShiftLeftLogical", + "OpBitwiseOr", + "OpBitwiseXor", + "OpBitwiseAnd", + "OpVectorShuffle", + "OpCompositeExtract", + "OpCompositeInsert", + "OpLogicalOr", + "OpLogicalAnd", + "OpLogicalNot", + "OpLogicalEqual", + "OpLogicalNotEqual", + "OpSelect", + "OpIEqual", + "OpINotEqual", + "OpULessThan", + "OpSLessThan", + "OpUGreaterThan", + "OpSGreaterThan", + "OpULessThanEqual", + "OpSLessThanEqual", + "OpUGreaterThanEqual", + "OpSGreaterThanEqual", + "OpQuantizeToF16", + "OpConvertFToS", + "OpConvertSToF", + "OpConvertFToU", + "OpConvertUToF", + "OpUConvert", + "OpConvertPtrToU", + "OpConvertUToPtr", + "OpGenericCastToPtr", + "OpPtrCastToGeneric", + "OpBitcast", + "OpFNegate", + "OpFAdd", + "OpFSub", + "OpFMul", + "OpFDiv", + "OpFRem", + "OpFMod", + "OpAccessChain", + "OpInBoundsAccessChain", + "OpPtrAccessChain", + "OpInBoundsPtrAccessChain", +]; diff --git a/crates/grammar-parser/src/codegen/inst.rs b/crates/grammar-parser/src/codegen/inst.rs index b244e822..62df7cbf 100644 --- a/crates/grammar-parser/src/codegen/inst.rs +++ b/crates/grammar-parser/src/codegen/inst.rs @@ -1,12 +1,14 @@ use crate::codegen::{GrammarWriter, OPERAND_ID_RESULT, OPERAND_ID_RESULT_TYPE}; use crate::parse::{Grammar, InstMeta, Operand, Quantifier}; +use anyhow::Context; +use proc_macro2::TokenStream; use quote::{format_ident, quote}; pub fn write_inst(writer: &mut GrammarWriter, grammar: &Grammar<'_>) -> anyhow::Result<()> { let insts = grammar.insts.iter().map(|inst| { let struct_ident = InstMeta::type_ident(&inst.opname); if !inst.source.codegen_impl() { - return quote!(pub use super::preamble::#struct_ident;); + return Ok(quote!(pub use super::preamble::#struct_ident;)); } let meta = InstMeta::const_ident(&inst.opname); @@ -53,6 +55,80 @@ pub fn write_inst(writer: &mut GrammarWriter, grammar: &Grammar<'_>) -> anyhow:: (quote!(()), quote!()) }; + // OpSpecOp + let op_spec_op_encoding = if inst.op_spec_op { + let missing_operands = || { + format!("Instruction {} is marked as `op_spec_op` compatible but doesn't have required `IdResult` and \ + `IdResultType` operands. All operands: {:?}", inst.opname, inst.operands) + }; + let id_result = id_result.with_context(missing_operands)?; + let id_result_type = id_result_type.with_context(missing_operands)?; + + // members that are not IdResult or IdResultType, since those need special casing. + let member_operands = member_operands + .iter() + .filter(|&op| { + !core::ptr::eq(op, id_result) + && !core::ptr::eq(op, id_result_type) + }) + .collect::>(); + let members = member_operands + .iter() + .map(|Operand { name, .. }| name) + .collect::>(); + let members_non_last = &members[..members.len().saturating_sub(1)]; + let members_last = members.last().into_iter(); + let member_id_result = &id_result.name; + let member_id_result_type = &id_result_type.name; + + // disassembly + let dis_operands_value = member_operands + .iter() + .map(|op| { + let name = &op.name; + quote!(, self.#name.dis(ctx)) + }) + .collect::>(); + let pat = [inst.opname.as_ref()] + .into_iter() + .chain(member_operands.iter().map(|_| "{}")) + .collect::(); + + quote! { + impl OpSpecOpInst for #struct_ident { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.#member_id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.#member_id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + #(OperandEncoding::encode(&self.#members, &mut *writer)?;)* + Ok(()) + } + + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let #member_id_result_type = OperandEncoding::decode(&mut op_reader)?; + let #member_id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + #member_id_result_type, + #member_id_result, + #(#members_non_last: OperandEncoding::decode(&mut op_reader)?,)* + #(#members_last: OperandEncoding::decode_last(&mut op_reader)?,)* + }) + } + + fn op_spec_op_dis_fmt(&self, f: &mut Formatter<'_>, ctx: OperandDisContext<'_>) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, #pat #(#dis_operands_value)*) + } + } + } + } else { + quote!() + }; + // encode decode let members = member_operands .iter() @@ -133,7 +209,7 @@ pub fn write_inst(writer: &mut GrammarWriter, grammar: &Grammar<'_>) -> anyhow:: } }; - quote! { + Ok(quote! { #struct_def #(#aliases)* @@ -177,12 +253,9 @@ pub fn write_inst(writer: &mut GrammarWriter, grammar: &Grammar<'_>) -> anyhow:: write!(f, #pat, ctx.id_result_writer() #(#dis_operands_value)*) } } - } - }); - writer.write_module( - "inst", - quote! { - #(#insts)* - }, - ) + + #op_spec_op_encoding + }) + }).collect::>()?; + writer.write_module("inst", insts) } diff --git a/crates/grammar-parser/src/codegen/inst_set.rs b/crates/grammar-parser/src/codegen/inst_set.rs index 43d2649a..ecb074cd 100644 --- a/crates/grammar-parser/src/codegen/inst_set.rs +++ b/crates/grammar-parser/src/codegen/inst_set.rs @@ -1,5 +1,6 @@ use crate::codegen::{CodegenOptions, GrammarWriter}; use crate::parse::{Grammar, InstMeta}; +use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; pub fn write_inst_enum( @@ -7,16 +8,89 @@ pub fn write_inst_enum( grammar: &Grammar<'_>, opt: &CodegenOptions<'_>, ) -> anyhow::Result<()> { - let name = format_ident!("{}InstSet", opt.name_suffix_type); - let insts = grammar - .insts - .iter() + writer.write_module( + "inst_set", + quote_inst_set( + &prep_insts(grammar.insts.iter()), + &format_ident!("{}InstSet", opt.name_suffix_type), + ), + ) +} + +pub fn write_op_spec_op_inst_enum( + writer: &mut GrammarWriter, + grammar: &Grammar<'_>, + opt: &CodegenOptions<'_>, +) -> anyhow::Result<()> { + let name = format_ident!("{}OpSpecOpInstSet", opt.name_suffix_type); + let insts = prep_insts(grammar.insts.iter().filter(|i| i.op_spec_op)); + let inst_set = quote_inst_set(&insts, &name); + + let op_spec_op_inst_set = { + let encode_match = insts.iter().map( + |(_, _, enum_ident)| quote!(Self::#enum_ident(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer),), + ); + let decode_match = insts.iter().map(|(inst, type_ident, enum_ident)| { + let opcode = inst.opcode; + quote!(#opcode => Self::#enum_ident(<#type_ident as OpSpecOpInst>::op_spec_op_decode(reader)?),) + }); + let dis_match = insts.iter().map( + |(_, _, enum_ident)| quote!(Self::#enum_ident(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx),), + ); + quote! { + impl OpSpecOpInst for #name { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + match self { + #(#encode_match)* + } + } + + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let opcode = reader[2].to_op().0; + Ok(match opcode { + #(#decode_match)* + _ => return Err(DecodeErrorKind::UnknownOpCode { opcode }.into()), + }) + } + + fn op_spec_op_dis_fmt(&self, f: &mut Formatter<'_>, ctx: OperandDisContext<'_>) -> std::fmt::Result { + profiling::function_scope!(); + match self { + #(#dis_match)* + } + } + } + } + }; + + writer.write_module( + "op_spec_op", + quote! { + #inst_set + #op_spec_op_inst_set + }, + ) +} + +pub fn prep_insts<'a, 'b: 'a>( + insts: impl IntoIterator>, +) -> Vec<(&'a InstMeta<'b>, Ident, Ident)> { + insts + .into_iter() .map(|inst| { let type_ident = InstMeta::type_ident(&inst.opname); let enum_ident = InstMeta::enum_ident(&inst.opname); (inst, type_ident, enum_ident) }) - .collect::>(); + .collect::>() +} + +pub fn quote_inst_set<'a, 'b: 'a>( + insts: &[(&'a InstMeta<'b>, Ident, Ident)], + name: &Ident, +) -> TokenStream { let enum_variants = insts .iter() .map(|(_, type_ident, enum_ident)| quote!(#enum_ident(#type_ident),)); @@ -45,61 +119,59 @@ pub fn write_inst_enum( } } }); - writer.write_module( - "inst_set", - quote! { - #[derive(Clone, Debug, Eq, PartialEq, Hash)] - pub enum #name { - #(#enum_variants)* - } - impl InstEncoding for #name { - type IdResult = Option; - type IdResultType = Option; + quote! { + #[derive(Clone, Debug, Eq, PartialEq, Hash)] + pub enum #name { + #(#enum_variants)* + } - fn id_result(&self) -> Self::IdResult { - profiling::function_scope!(); - match self { - #(#id_result_match)* - } - } + impl InstEncoding for #name { + type IdResult = Option; + type IdResultType = Option; - fn id_result_type(&self) -> Self::IdResultType { - profiling::function_scope!(); - match self { - #(#id_result_type_match)* - } + fn id_result(&self) -> Self::IdResult { + profiling::function_scope!(); + match self { + #(#id_result_match)* } + } - fn name() -> &'static str { - stringify!(#name) + fn id_result_type(&self) -> Self::IdResultType { + profiling::function_scope!(); + match self { + #(#id_result_type_match)* } + } - fn encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { - profiling::function_scope!(); - match self { - #(#encode_match)* - } - } + fn name() -> &'static str { + stringify!(#name) + } - fn decode(reader: InstReader<'_>) -> Result { - profiling::function_scope!(); - let opcode = reader.opcode(); - Ok(match opcode { - #(#decode_match)* - _ => return Err(DecodeErrorKind::UnknownOpCode { opcode }.into()), - }) + fn encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + match self { + #(#encode_match)* } + } - fn dis_fmt(&self, f: &mut Formatter<'_>, ctx: &DisContext) -> std::fmt::Result { - profiling::function_scope!(); - match self { - #(#dis_match)* - } + fn decode(reader: InstReader<'_>) -> Result { + profiling::function_scope!(); + let opcode = reader.opcode(); + Ok(match opcode { + #(#decode_match)* + _ => return Err(DecodeErrorKind::UnknownOpCode { opcode }.into()), + }) + } + + fn dis_fmt(&self, f: &mut Formatter<'_>, ctx: &DisContext) -> std::fmt::Result { + profiling::function_scope!(); + match self { + #(#dis_match)* } } + } - #(#from_impls)* - }, - ) + #(#from_impls)* + } } diff --git a/crates/grammar-parser/src/codegen/modules.rs b/crates/grammar-parser/src/codegen/modules.rs index 1daf378c..8d4a12ed 100644 --- a/crates/grammar-parser/src/codegen/modules.rs +++ b/crates/grammar-parser/src/codegen/modules.rs @@ -1,5 +1,5 @@ use crate::codegen::inst::write_inst; -use crate::codegen::inst_set::write_inst_enum; +use crate::codegen::inst_set::{write_inst_enum, write_op_spec_op_inst_enum}; use crate::codegen::operands::write_operands; use crate::codegen::options::CodegenOptions; use crate::codegen::{EmitRef, GrammarWriter}; @@ -40,6 +40,7 @@ pub fn write_grammar<'a>( write_inst_meta(&mut writer, grammar)?; write_inst(&mut writer, grammar)?; write_inst_enum(&mut writer, grammar, opt)?; + write_op_spec_op_inst_enum(&mut writer, grammar, opt)?; write_grammar_mod(&mut writer, grammar)?; writer.finish()?; Ok(()) diff --git a/crates/grammar-parser/src/parse/instruction.rs b/crates/grammar-parser/src/parse/instruction.rs index 68c09ba1..d4b2e62b 100644 --- a/crates/grammar-parser/src/parse/instruction.rs +++ b/crates/grammar-parser/src/parse/instruction.rs @@ -27,6 +27,11 @@ pub struct InstMeta<'a> { pub provisional: bool, #[serde(skip)] pub source: Source, + /// Instruction may be used within an `OpSpecConstantOp` instruction. + /// + /// The Instruction *must* contain both an `IdResult` and an `IdResultType` operand, or codegen will assert. + #[serde(skip)] + pub op_spec_op: bool, } /// See `rspirv2_types::meta::OperandSpecMeta` @@ -84,6 +89,7 @@ impl Import for rspirv2_types::meta::InstMeta { last_version: self.last_version.map(Cow::Borrowed), aliases: self.aliases.iter().map(|s| Cow::Borrowed(*s)).collect(), provisional: self.provisional, + op_spec_op: false, source: Source::Import, } } diff --git a/crates/rspirv2-types/src/binary/reader.rs b/crates/rspirv2-types/src/binary/reader.rs index ed4add65..a0404a32 100644 --- a/crates/rspirv2-types/src/binary/reader.rs +++ b/crates/rspirv2-types/src/binary/reader.rs @@ -160,6 +160,22 @@ impl<'a> OperandReader<'a> { .into() } + /// Check whether the next Word is equal to this opcode, needed for `OpSpecConstantOp`. + #[inline] + pub fn pull_expected_opcode(&mut self, meta: &InstMeta) -> Result<(), DecodeError> { + let opcode = self.pull()?.to_op().0; + if opcode != meta.opcode { + Err(DecodeErrorKind::WrongOpCode { + name: meta.opname, + expected: meta.opcode, + actual: opcode, + } + .into()) + } else { + Ok(()) + } + } + /// View the *remaining* Words as a slice, does not advance the `params_offset`. #[inline] pub fn as_slice(&self) -> &'a [Word] { diff --git a/crates/rspirv2-types/src/lib.rs b/crates/rspirv2-types/src/lib.rs index f452cba3..1a511b00 100644 --- a/crates/rspirv2-types/src/lib.rs +++ b/crates/rspirv2-types/src/lib.rs @@ -5,6 +5,7 @@ pub mod dis; pub mod inst; pub mod meta; pub mod module; +pub mod op_spec_op; pub mod operand; pub mod slice; pub mod vec; diff --git a/crates/rspirv2-types/src/op_spec_op.rs b/crates/rspirv2-types/src/op_spec_op.rs new file mode 100644 index 00000000..d5c26eae --- /dev/null +++ b/crates/rspirv2-types/src/op_spec_op.rs @@ -0,0 +1,54 @@ +use crate::Word; +use crate::binary::{DecodeError, EncodeError, WordWriter}; +use crate::inst::InstEncoding; +use crate::operand::OperandDisContext; +use std::fmt::{Display, Formatter}; + +/// Like [`InstEncoding`] but encodes supported instruction in the slightly different binary format that +/// `OpSpecConstantOp` requires. +/// +/// The `ResultType` and `Result` operands are moved to the front and the `opcode` is the 3rd operand instead of the +/// first: +/// ```plain +/// # normal encoding: +/// [(IAdd.opcode | len << 16), ResultType, Result, IdRef, IdRef] +/// # OpSpecConstantOp encoding: +/// [(OpSpecConstantOp.opcode | len << 16), ResultType, Result, IAdd.opcode, IdRef, IdRef] +/// ``` +/// +/// Also see: +/// * +/// * +pub trait OpSpecOpInst: InstEncoding { + /// Encode this instruction to a [`WordWriter`] + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError>; + + /// Decode this instruction from a slice of words. + /// + /// `InstReader` assumes the opcode is at offset 0, but here it's at offset 2. + fn op_spec_op_decode(reader: &[Word]) -> Result; + + /// Like [`InstEncoding::dis_fmt`] but printing everything after `OpSpecConstantOp`, eg. `OpIAdd %1 %2`. + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result; + + /// Like [`InstEncoding::dis`] but printing everything after `OpSpecConstantOp`, eg. `OpIAdd %1 %2`. + /// + /// You shouldn't overwrite this function but [`Self::op_spec_op_dis`] instead. + #[inline] + fn op_spec_op_dis<'a>(&'a self, ctx: OperandDisContext<'a>) -> OpSpecOpDis<'a, Self> { + OpSpecOpDis(self, ctx) + } +} + +pub struct OpSpecOpDis<'a, T: OpSpecOpInst>(&'a T, OperandDisContext<'a>); + +impl<'a, T: OpSpecOpInst> Display for OpSpecOpDis<'a, T> { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + self.0.op_spec_op_dis_fmt(f, self.1) + } +} diff --git a/crates/rspirv2/src/core/inst.rs b/crates/rspirv2/src/core/inst.rs index 929071ea..9fa67070 100644 --- a/crates/rspirv2/src/core/inst.rs +++ b/crates/rspirv2/src/core/inst.rs @@ -2316,62 +2316,7 @@ impl InstEncoding for OpSpecConstantComposite { ) } } -#[derive(Clone, Debug, Eq, PartialEq, Hash)] -pub struct OpSpecConstantOp { - pub id_result_type: IdResultType, - pub id_result: IdResult, - pub opcode: LiteralSpecConstantOpInteger, -} -impl Inst for OpSpecConstantOp { - const META: &InstMeta = &OP_SPEC_CONSTANT_OP; -} -impl InstEncoding for OpSpecConstantOp { - type IdResult = IdResult; - type IdResultType = IdResultType; - fn id_result(&self) -> Self::IdResult { - self.id_result - } - fn id_result_type(&self) -> Self::IdResultType { - self.id_result_type - } - fn encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { - profiling::function_scope!(); - let len = 1 - + OperandEncoding::word_len(&self.id_result_type) - + OperandEncoding::word_len(&self.id_result) - + OperandEncoding::word_len(&self.opcode); - writer.write_op(Self::META.opcode, len)?; - OperandEncoding::encode(&self.id_result_type, &mut *writer)?; - OperandEncoding::encode(&self.id_result, &mut *writer)?; - OperandEncoding::encode(&self.opcode, &mut *writer)?; - Ok(()) - } - fn decode(reader: InstReader<'_>) -> Result { - profiling::function_scope!(); - let mut op_reader = reader.check_opcode(Self::META)?; - Ok(Self { - id_result_type: OperandEncoding::decode(&mut op_reader)?, - id_result: OperandEncoding::decode(&mut op_reader)?, - opcode: OperandEncoding::decode_last(&mut op_reader)?, - }) - } - fn dis_fmt(&self, f: &mut Formatter<'_>, ctx: &DisContext) -> std::fmt::Result { - profiling::function_scope!(); - let ctx = OperandDisContext { - id_result: Some(self.id_result), - id_result_type: Some(self.id_result_type), - ctx, - }; - let rspirv_space = ctx.rspirv_space(); - write!( - f, - "{}OpSpecConstantOp{rspirv_space}{}{rspirv_space}{}", - ctx.id_result_writer(), - self.id_result_type.dis(ctx), - self.opcode.dis(ctx) - ) - } -} +pub use super::preamble::OpSpecConstantOp; #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpFunction { pub id_result_type: IdResultType, @@ -2996,6 +2941,43 @@ impl InstEncoding for OpAccessChain { ) } } +impl OpSpecOpInst for OpAccessChain { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.base, &mut *writer)?; + OperandEncoding::encode(&self.indexes, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + base: OperandEncoding::decode(&mut op_reader)?, + indexes: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpAccessChain{}{}", + self.base.dis(ctx), + self.indexes.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpInBoundsAccessChain { pub id_result_type: IdResultType, @@ -3057,6 +3039,43 @@ impl InstEncoding for OpInBoundsAccessChain { ) } } +impl OpSpecOpInst for OpInBoundsAccessChain { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.base, &mut *writer)?; + OperandEncoding::encode(&self.indexes, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + base: OperandEncoding::decode(&mut op_reader)?, + indexes: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpInBoundsAccessChain{}{}", + self.base.dis(ctx), + self.indexes.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpPtrAccessChain { pub id_result_type: IdResultType, @@ -3123,6 +3142,46 @@ impl InstEncoding for OpPtrAccessChain { ) } } +impl OpSpecOpInst for OpPtrAccessChain { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.base, &mut *writer)?; + OperandEncoding::encode(&self.element, &mut *writer)?; + OperandEncoding::encode(&self.indexes, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + base: OperandEncoding::decode(&mut op_reader)?, + element: OperandEncoding::decode(&mut op_reader)?, + indexes: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpPtrAccessChain{}{}{}", + self.base.dis(ctx), + self.element.dis(ctx), + self.indexes.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpArrayLength { pub id_result_type: IdResultType, @@ -3306,6 +3365,46 @@ impl InstEncoding for OpInBoundsPtrAccessChain { ) } } +impl OpSpecOpInst for OpInBoundsPtrAccessChain { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.base, &mut *writer)?; + OperandEncoding::encode(&self.element, &mut *writer)?; + OperandEncoding::encode(&self.indexes, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + base: OperandEncoding::decode(&mut op_reader)?, + element: OperandEncoding::decode(&mut op_reader)?, + indexes: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpInBoundsPtrAccessChain{}{}{}", + self.base.dis(ctx), + self.element.dis(ctx), + self.indexes.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpDecorate { pub target: IdRef, @@ -3730,6 +3829,46 @@ impl InstEncoding for OpVectorShuffle { ) } } +impl OpSpecOpInst for OpVectorShuffle { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.vector_1, &mut *writer)?; + OperandEncoding::encode(&self.vector_2, &mut *writer)?; + OperandEncoding::encode(&self.components, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + vector_1: OperandEncoding::decode(&mut op_reader)?, + vector_2: OperandEncoding::decode(&mut op_reader)?, + components: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpVectorShuffle{}{}{}", + self.vector_1.dis(ctx), + self.vector_2.dis(ctx), + self.components.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpCompositeConstruct { pub id_result_type: IdResultType, @@ -3847,6 +3986,43 @@ impl InstEncoding for OpCompositeExtract { ) } } +impl OpSpecOpInst for OpCompositeExtract { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.composite, &mut *writer)?; + OperandEncoding::encode(&self.indexes, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + composite: OperandEncoding::decode(&mut op_reader)?, + indexes: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpCompositeExtract{}{}", + self.composite.dis(ctx), + self.indexes.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpCompositeInsert { pub id_result_type: IdResultType, @@ -3913,6 +4089,46 @@ impl InstEncoding for OpCompositeInsert { ) } } +impl OpSpecOpInst for OpCompositeInsert { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.object, &mut *writer)?; + OperandEncoding::encode(&self.composite, &mut *writer)?; + OperandEncoding::encode(&self.indexes, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + object: OperandEncoding::decode(&mut op_reader)?, + composite: OperandEncoding::decode(&mut op_reader)?, + indexes: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpCompositeInsert{}{}{}", + self.object.dis(ctx), + self.composite.dis(ctx), + self.indexes.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpCopyObject { pub id_result_type: IdResultType, @@ -5479,6 +5695,36 @@ impl InstEncoding for OpConvertFToU { ) } } +impl OpSpecOpInst for OpConvertFToU { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.float_value, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + float_value: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpConvertFToU{}", self.float_value.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpConvertFToS { pub id_result_type: IdResultType, @@ -5535,6 +5781,36 @@ impl InstEncoding for OpConvertFToS { ) } } +impl OpSpecOpInst for OpConvertFToS { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.float_value, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + float_value: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpConvertFToS{}", self.float_value.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpConvertSToF { pub id_result_type: IdResultType, @@ -5591,6 +5867,36 @@ impl InstEncoding for OpConvertSToF { ) } } +impl OpSpecOpInst for OpConvertSToF { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.signed_value, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + signed_value: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpConvertSToF{}", self.signed_value.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpConvertUToF { pub id_result_type: IdResultType, @@ -5647,14 +5953,44 @@ impl InstEncoding for OpConvertUToF { ) } } -#[derive(Clone, Debug, Eq, PartialEq, Hash)] -pub struct OpUConvert { - pub id_result_type: IdResultType, - pub id_result: IdResult, - pub unsigned_value: IdRef, -} -impl Inst for OpUConvert { - const META: &InstMeta = &OP_U_CONVERT; +impl OpSpecOpInst for OpConvertUToF { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.unsigned_value, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + unsigned_value: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpConvertUToF{}", self.unsigned_value.dis(ctx)) + } +} +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub struct OpUConvert { + pub id_result_type: IdResultType, + pub id_result: IdResult, + pub unsigned_value: IdRef, +} +impl Inst for OpUConvert { + const META: &InstMeta = &OP_U_CONVERT; } impl InstEncoding for OpUConvert { type IdResult = IdResult; @@ -5703,6 +6039,36 @@ impl InstEncoding for OpUConvert { ) } } +impl OpSpecOpInst for OpUConvert { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.unsigned_value, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + unsigned_value: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpUConvert{}", self.unsigned_value.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpSConvert { pub id_result_type: IdResultType, @@ -5759,6 +6125,36 @@ impl InstEncoding for OpSConvert { ) } } +impl OpSpecOpInst for OpSConvert { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.signed_value, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + signed_value: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpSConvert{}", self.signed_value.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpFConvert { pub id_result_type: IdResultType, @@ -5815,6 +6211,36 @@ impl InstEncoding for OpFConvert { ) } } +impl OpSpecOpInst for OpFConvert { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.float_value, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + float_value: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpFConvert{}", self.float_value.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpQuantizeToF16 { pub id_result_type: IdResultType, @@ -5871,6 +6297,36 @@ impl InstEncoding for OpQuantizeToF16 { ) } } +impl OpSpecOpInst for OpQuantizeToF16 { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.value, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + value: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpQuantizeToF16{}", self.value.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpConvertPtrToU { pub id_result_type: IdResultType, @@ -5927,6 +6383,36 @@ impl InstEncoding for OpConvertPtrToU { ) } } +impl OpSpecOpInst for OpConvertPtrToU { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.pointer, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + pointer: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpConvertPtrToU{}", self.pointer.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpSatConvertSToU { pub id_result_type: IdResultType, @@ -6095,6 +6581,36 @@ impl InstEncoding for OpConvertUToPtr { ) } } +impl OpSpecOpInst for OpConvertUToPtr { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.integer_value, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + integer_value: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpConvertUToPtr{}", self.integer_value.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpPtrCastToGeneric { pub id_result_type: IdResultType, @@ -6151,6 +6667,36 @@ impl InstEncoding for OpPtrCastToGeneric { ) } } +impl OpSpecOpInst for OpPtrCastToGeneric { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.pointer, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + pointer: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpPtrCastToGeneric{}", self.pointer.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpGenericCastToPtr { pub id_result_type: IdResultType, @@ -6207,6 +6753,36 @@ impl InstEncoding for OpGenericCastToPtr { ) } } +impl OpSpecOpInst for OpGenericCastToPtr { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.pointer, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + pointer: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpGenericCastToPtr{}", self.pointer.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpGenericCastToPtrExplicit { pub id_result_type: IdResultType, @@ -6324,6 +6900,36 @@ impl InstEncoding for OpBitcast { ) } } +impl OpSpecOpInst for OpBitcast { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpBitcast{}", self.operand.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpSNegate { pub id_result_type: IdResultType, @@ -6380,6 +6986,36 @@ impl InstEncoding for OpSNegate { ) } } +impl OpSpecOpInst for OpSNegate { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpSNegate{}", self.operand.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpFNegate { pub id_result_type: IdResultType, @@ -6436,6 +7072,36 @@ impl InstEncoding for OpFNegate { ) } } +impl OpSpecOpInst for OpFNegate { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpFNegate{}", self.operand.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpIAdd { pub id_result_type: IdResultType, @@ -6497,6 +7163,43 @@ impl InstEncoding for OpIAdd { ) } } +impl OpSpecOpInst for OpIAdd { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpIAdd{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpFAdd { pub id_result_type: IdResultType, @@ -6558,6 +7261,43 @@ impl InstEncoding for OpFAdd { ) } } +impl OpSpecOpInst for OpFAdd { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpFAdd{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpISub { pub id_result_type: IdResultType, @@ -6619,6 +7359,43 @@ impl InstEncoding for OpISub { ) } } +impl OpSpecOpInst for OpISub { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpISub{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpFSub { pub id_result_type: IdResultType, @@ -6680,6 +7457,43 @@ impl InstEncoding for OpFSub { ) } } +impl OpSpecOpInst for OpFSub { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpFSub{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpIMul { pub id_result_type: IdResultType, @@ -6741,6 +7555,43 @@ impl InstEncoding for OpIMul { ) } } +impl OpSpecOpInst for OpIMul { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpIMul{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpFMul { pub id_result_type: IdResultType, @@ -6802,6 +7653,43 @@ impl InstEncoding for OpFMul { ) } } +impl OpSpecOpInst for OpFMul { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpFMul{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpUDiv { pub id_result_type: IdResultType, @@ -6863,6 +7751,43 @@ impl InstEncoding for OpUDiv { ) } } +impl OpSpecOpInst for OpUDiv { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpUDiv{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpSDiv { pub id_result_type: IdResultType, @@ -6924,6 +7849,43 @@ impl InstEncoding for OpSDiv { ) } } +impl OpSpecOpInst for OpSDiv { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpSDiv{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpFDiv { pub id_result_type: IdResultType, @@ -6985,6 +7947,43 @@ impl InstEncoding for OpFDiv { ) } } +impl OpSpecOpInst for OpFDiv { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpFDiv{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpUMod { pub id_result_type: IdResultType, @@ -7046,6 +8045,43 @@ impl InstEncoding for OpUMod { ) } } +impl OpSpecOpInst for OpUMod { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpUMod{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpSRem { pub id_result_type: IdResultType, @@ -7107,6 +8143,43 @@ impl InstEncoding for OpSRem { ) } } +impl OpSpecOpInst for OpSRem { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpSRem{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpSMod { pub id_result_type: IdResultType, @@ -7168,6 +8241,43 @@ impl InstEncoding for OpSMod { ) } } +impl OpSpecOpInst for OpSMod { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpSMod{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpFRem { pub id_result_type: IdResultType, @@ -7229,6 +8339,43 @@ impl InstEncoding for OpFRem { ) } } +impl OpSpecOpInst for OpFRem { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpFRem{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpFMod { pub id_result_type: IdResultType, @@ -7250,41 +8397,78 @@ impl InstEncoding for OpFMod { } fn encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { profiling::function_scope!(); - let len = 1 - + OperandEncoding::word_len(&self.id_result_type) - + OperandEncoding::word_len(&self.id_result) - + OperandEncoding::word_len(&self.operand_1) - + OperandEncoding::word_len(&self.operand_2); - writer.write_op(Self::META.opcode, len)?; + let len = 1 + + OperandEncoding::word_len(&self.id_result_type) + + OperandEncoding::word_len(&self.id_result) + + OperandEncoding::word_len(&self.operand_1) + + OperandEncoding::word_len(&self.operand_2); + writer.write_op(Self::META.opcode, len)?; + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn decode(reader: InstReader<'_>) -> Result { + profiling::function_scope!(); + let mut op_reader = reader.check_opcode(Self::META)?; + Ok(Self { + id_result_type: OperandEncoding::decode(&mut op_reader)?, + id_result: OperandEncoding::decode(&mut op_reader)?, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn dis_fmt(&self, f: &mut Formatter<'_>, ctx: &DisContext) -> std::fmt::Result { + profiling::function_scope!(); + let ctx = OperandDisContext { + id_result: Some(self.id_result), + id_result_type: Some(self.id_result_type), + ctx, + }; + let rspirv_space = ctx.rspirv_space(); + write!( + f, + "{}OpFMod{rspirv_space}{}{rspirv_space}{}{}", + ctx.id_result_writer(), + self.id_result_type.dis(ctx), + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} +impl OpSpecOpInst for OpFMod { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); OperandEncoding::encode(&self.id_result_type, &mut *writer)?; OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; OperandEncoding::encode(&self.operand_1, &mut *writer)?; OperandEncoding::encode(&self.operand_2, &mut *writer)?; Ok(()) } - fn decode(reader: InstReader<'_>) -> Result { + fn op_spec_op_decode(reader: &[Word]) -> Result { profiling::function_scope!(); - let mut op_reader = reader.check_opcode(Self::META)?; + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; Ok(Self { - id_result_type: OperandEncoding::decode(&mut op_reader)?, - id_result: OperandEncoding::decode(&mut op_reader)?, + id_result_type, + id_result, operand_1: OperandEncoding::decode(&mut op_reader)?, operand_2: OperandEncoding::decode_last(&mut op_reader)?, }) } - fn dis_fmt(&self, f: &mut Formatter<'_>, ctx: &DisContext) -> std::fmt::Result { + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { profiling::function_scope!(); - let ctx = OperandDisContext { - id_result: Some(self.id_result), - id_result_type: Some(self.id_result_type), - ctx, - }; - let rspirv_space = ctx.rspirv_space(); write!( f, - "{}OpFMod{rspirv_space}{}{rspirv_space}{}{}", - ctx.id_result_writer(), - self.id_result_type.dis(ctx), + "OpFMod{}{}", self.operand_1.dis(ctx), self.operand_2.dis(ctx) ) @@ -8597,6 +9781,43 @@ impl InstEncoding for OpLogicalEqual { ) } } +impl OpSpecOpInst for OpLogicalEqual { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpLogicalEqual{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpLogicalNotEqual { pub id_result_type: IdResultType, @@ -8658,6 +9879,43 @@ impl InstEncoding for OpLogicalNotEqual { ) } } +impl OpSpecOpInst for OpLogicalNotEqual { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpLogicalNotEqual{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpLogicalOr { pub id_result_type: IdResultType, @@ -8719,6 +9977,43 @@ impl InstEncoding for OpLogicalOr { ) } } +impl OpSpecOpInst for OpLogicalOr { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpLogicalOr{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpLogicalAnd { pub id_result_type: IdResultType, @@ -8780,6 +10075,43 @@ impl InstEncoding for OpLogicalAnd { ) } } +impl OpSpecOpInst for OpLogicalAnd { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpLogicalAnd{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpLogicalNot { pub id_result_type: IdResultType, @@ -8836,6 +10168,36 @@ impl InstEncoding for OpLogicalNot { ) } } +impl OpSpecOpInst for OpLogicalNot { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpLogicalNot{}", self.operand.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpSelect { pub id_result_type: IdResultType, @@ -8902,6 +10264,46 @@ impl InstEncoding for OpSelect { ) } } +impl OpSpecOpInst for OpSelect { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.condition, &mut *writer)?; + OperandEncoding::encode(&self.object_1, &mut *writer)?; + OperandEncoding::encode(&self.object_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + condition: OperandEncoding::decode(&mut op_reader)?, + object_1: OperandEncoding::decode(&mut op_reader)?, + object_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpSelect{}{}{}", + self.condition.dis(ctx), + self.object_1.dis(ctx), + self.object_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpIEqual { pub id_result_type: IdResultType, @@ -8963,6 +10365,43 @@ impl InstEncoding for OpIEqual { ) } } +impl OpSpecOpInst for OpIEqual { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpIEqual{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpINotEqual { pub id_result_type: IdResultType, @@ -9024,6 +10463,43 @@ impl InstEncoding for OpINotEqual { ) } } +impl OpSpecOpInst for OpINotEqual { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpINotEqual{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpUGreaterThan { pub id_result_type: IdResultType, @@ -9085,6 +10561,43 @@ impl InstEncoding for OpUGreaterThan { ) } } +impl OpSpecOpInst for OpUGreaterThan { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpUGreaterThan{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpSGreaterThan { pub id_result_type: IdResultType, @@ -9146,6 +10659,43 @@ impl InstEncoding for OpSGreaterThan { ) } } +impl OpSpecOpInst for OpSGreaterThan { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpSGreaterThan{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpUGreaterThanEqual { pub id_result_type: IdResultType, @@ -9189,19 +10739,56 @@ impl InstEncoding for OpUGreaterThanEqual { operand_2: OperandEncoding::decode_last(&mut op_reader)?, }) } - fn dis_fmt(&self, f: &mut Formatter<'_>, ctx: &DisContext) -> std::fmt::Result { + fn dis_fmt(&self, f: &mut Formatter<'_>, ctx: &DisContext) -> std::fmt::Result { + profiling::function_scope!(); + let ctx = OperandDisContext { + id_result: Some(self.id_result), + id_result_type: Some(self.id_result_type), + ctx, + }; + let rspirv_space = ctx.rspirv_space(); + write!( + f, + "{}OpUGreaterThanEqual{rspirv_space}{}{rspirv_space}{}{}", + ctx.id_result_writer(), + self.id_result_type.dis(ctx), + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} +impl OpSpecOpInst for OpUGreaterThanEqual { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { profiling::function_scope!(); - let ctx = OperandDisContext { - id_result: Some(self.id_result), - id_result_type: Some(self.id_result_type), - ctx, - }; - let rspirv_space = ctx.rspirv_space(); write!( f, - "{}OpUGreaterThanEqual{rspirv_space}{}{rspirv_space}{}{}", - ctx.id_result_writer(), - self.id_result_type.dis(ctx), + "OpUGreaterThanEqual{}{}", self.operand_1.dis(ctx), self.operand_2.dis(ctx) ) @@ -9268,6 +10855,43 @@ impl InstEncoding for OpSGreaterThanEqual { ) } } +impl OpSpecOpInst for OpSGreaterThanEqual { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpSGreaterThanEqual{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpULessThan { pub id_result_type: IdResultType, @@ -9329,6 +10953,43 @@ impl InstEncoding for OpULessThan { ) } } +impl OpSpecOpInst for OpULessThan { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpULessThan{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpSLessThan { pub id_result_type: IdResultType, @@ -9390,6 +11051,43 @@ impl InstEncoding for OpSLessThan { ) } } +impl OpSpecOpInst for OpSLessThan { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpSLessThan{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpULessThanEqual { pub id_result_type: IdResultType, @@ -9451,6 +11149,43 @@ impl InstEncoding for OpULessThanEqual { ) } } +impl OpSpecOpInst for OpULessThanEqual { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpULessThanEqual{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpSLessThanEqual { pub id_result_type: IdResultType, @@ -9512,6 +11247,43 @@ impl InstEncoding for OpSLessThanEqual { ) } } +impl OpSpecOpInst for OpSLessThanEqual { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpSLessThanEqual{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpFOrdEqual { pub id_result_type: IdResultType, @@ -10305,6 +12077,43 @@ impl InstEncoding for OpShiftRightLogical { ) } } +impl OpSpecOpInst for OpShiftRightLogical { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.base, &mut *writer)?; + OperandEncoding::encode(&self.shift, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + base: OperandEncoding::decode(&mut op_reader)?, + shift: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpShiftRightLogical{}{}", + self.base.dis(ctx), + self.shift.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpShiftRightArithmetic { pub id_result_type: IdResultType, @@ -10366,6 +12175,43 @@ impl InstEncoding for OpShiftRightArithmetic { ) } } +impl OpSpecOpInst for OpShiftRightArithmetic { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.base, &mut *writer)?; + OperandEncoding::encode(&self.shift, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + base: OperandEncoding::decode(&mut op_reader)?, + shift: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpShiftRightArithmetic{}{}", + self.base.dis(ctx), + self.shift.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpShiftLeftLogical { pub id_result_type: IdResultType, @@ -10427,6 +12273,43 @@ impl InstEncoding for OpShiftLeftLogical { ) } } +impl OpSpecOpInst for OpShiftLeftLogical { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.base, &mut *writer)?; + OperandEncoding::encode(&self.shift, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + base: OperandEncoding::decode(&mut op_reader)?, + shift: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpShiftLeftLogical{}{}", + self.base.dis(ctx), + self.shift.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpBitwiseOr { pub id_result_type: IdResultType, @@ -10488,6 +12371,43 @@ impl InstEncoding for OpBitwiseOr { ) } } +impl OpSpecOpInst for OpBitwiseOr { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpBitwiseOr{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpBitwiseXor { pub id_result_type: IdResultType, @@ -10549,6 +12469,43 @@ impl InstEncoding for OpBitwiseXor { ) } } +impl OpSpecOpInst for OpBitwiseXor { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpBitwiseXor{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpBitwiseAnd { pub id_result_type: IdResultType, @@ -10610,6 +12567,43 @@ impl InstEncoding for OpBitwiseAnd { ) } } +impl OpSpecOpInst for OpBitwiseAnd { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand_1, &mut *writer)?; + OperandEncoding::encode(&self.operand_2, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand_1: OperandEncoding::decode(&mut op_reader)?, + operand_2: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!( + f, + "OpBitwiseAnd{}{}", + self.operand_1.dis(ctx), + self.operand_2.dis(ctx) + ) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpNot { pub id_result_type: IdResultType, @@ -10666,6 +12660,36 @@ impl InstEncoding for OpNot { ) } } +impl OpSpecOpInst for OpNot { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + OperandEncoding::encode(&self.id_result_type, &mut *writer)?; + OperandEncoding::encode(&self.id_result, &mut *writer)?; + writer.write_op(Self::META.opcode, 0)?; + OperandEncoding::encode(&self.operand, &mut *writer)?; + Ok(()) + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let mut op_reader = OperandReader::new(reader); + let id_result_type = OperandEncoding::decode(&mut op_reader)?; + let id_result = OperandEncoding::decode(&mut op_reader)?; + op_reader.pull_expected_opcode(Self::META)?; + Ok(Self { + id_result_type, + id_result, + operand: OperandEncoding::decode_last(&mut op_reader)?, + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + write!(f, "OpNot{}", self.operand.dis(ctx)) + } +} #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct OpBitFieldInsert { pub id_result_type: IdResultType, diff --git a/crates/rspirv2/src/core/mod.rs b/crates/rspirv2/src/core/mod.rs index dcad9a1e..c62e49fd 100644 --- a/crates/rspirv2/src/core/mod.rs +++ b/crates/rspirv2/src/core/mod.rs @@ -12,6 +12,7 @@ pub mod inst; pub mod inst_class; pub mod inst_meta; pub mod inst_set; +pub mod op_spec_op; pub mod operand_kinds; pub mod operands; @@ -46,6 +47,7 @@ pub mod preamble { pub use crate::dis::*; pub use crate::inst::*; pub use crate::meta::*; + pub use crate::op_spec_op::*; pub use crate::op_switch::*; pub use crate::operand::*; pub use crate::*; diff --git a/crates/rspirv2/src/core/op_spec_op.rs b/crates/rspirv2/src/core/op_spec_op.rs new file mode 100644 index 00000000..59d76a37 --- /dev/null +++ b/crates/rspirv2/src/core/op_spec_op.rs @@ -0,0 +1,955 @@ +use super::preamble::*; +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub enum CoreOpSpecOpInstSet { + AccessChain(OpAccessChain), + InBoundsAccessChain(OpInBoundsAccessChain), + PtrAccessChain(OpPtrAccessChain), + InBoundsPtrAccessChain(OpInBoundsPtrAccessChain), + VectorShuffle(OpVectorShuffle), + CompositeExtract(OpCompositeExtract), + CompositeInsert(OpCompositeInsert), + ConvertFToU(OpConvertFToU), + ConvertFToS(OpConvertFToS), + ConvertSToF(OpConvertSToF), + ConvertUToF(OpConvertUToF), + UConvert(OpUConvert), + SConvert(OpSConvert), + FConvert(OpFConvert), + QuantizeToF16(OpQuantizeToF16), + ConvertPtrToU(OpConvertPtrToU), + ConvertUToPtr(OpConvertUToPtr), + PtrCastToGeneric(OpPtrCastToGeneric), + GenericCastToPtr(OpGenericCastToPtr), + Bitcast(OpBitcast), + SNegate(OpSNegate), + FNegate(OpFNegate), + IAdd(OpIAdd), + FAdd(OpFAdd), + ISub(OpISub), + FSub(OpFSub), + IMul(OpIMul), + FMul(OpFMul), + UDiv(OpUDiv), + SDiv(OpSDiv), + FDiv(OpFDiv), + UMod(OpUMod), + SRem(OpSRem), + SMod(OpSMod), + FRem(OpFRem), + FMod(OpFMod), + LogicalEqual(OpLogicalEqual), + LogicalNotEqual(OpLogicalNotEqual), + LogicalOr(OpLogicalOr), + LogicalAnd(OpLogicalAnd), + LogicalNot(OpLogicalNot), + Select(OpSelect), + IEqual(OpIEqual), + INotEqual(OpINotEqual), + UGreaterThan(OpUGreaterThan), + SGreaterThan(OpSGreaterThan), + UGreaterThanEqual(OpUGreaterThanEqual), + SGreaterThanEqual(OpSGreaterThanEqual), + ULessThan(OpULessThan), + SLessThan(OpSLessThan), + ULessThanEqual(OpULessThanEqual), + SLessThanEqual(OpSLessThanEqual), + ShiftRightLogical(OpShiftRightLogical), + ShiftRightArithmetic(OpShiftRightArithmetic), + ShiftLeftLogical(OpShiftLeftLogical), + BitwiseOr(OpBitwiseOr), + BitwiseXor(OpBitwiseXor), + BitwiseAnd(OpBitwiseAnd), + Not(OpNot), +} +impl InstEncoding for CoreOpSpecOpInstSet { + type IdResult = Option; + type IdResultType = Option; + fn id_result(&self) -> Self::IdResult { + profiling::function_scope!(); + match self { + Self::AccessChain(inst) => InstEncoding::id_result(inst).to_optional(), + Self::InBoundsAccessChain(inst) => InstEncoding::id_result(inst).to_optional(), + Self::PtrAccessChain(inst) => InstEncoding::id_result(inst).to_optional(), + Self::InBoundsPtrAccessChain(inst) => InstEncoding::id_result(inst).to_optional(), + Self::VectorShuffle(inst) => InstEncoding::id_result(inst).to_optional(), + Self::CompositeExtract(inst) => InstEncoding::id_result(inst).to_optional(), + Self::CompositeInsert(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ConvertFToU(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ConvertFToS(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ConvertSToF(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ConvertUToF(inst) => InstEncoding::id_result(inst).to_optional(), + Self::UConvert(inst) => InstEncoding::id_result(inst).to_optional(), + Self::SConvert(inst) => InstEncoding::id_result(inst).to_optional(), + Self::FConvert(inst) => InstEncoding::id_result(inst).to_optional(), + Self::QuantizeToF16(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ConvertPtrToU(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ConvertUToPtr(inst) => InstEncoding::id_result(inst).to_optional(), + Self::PtrCastToGeneric(inst) => InstEncoding::id_result(inst).to_optional(), + Self::GenericCastToPtr(inst) => InstEncoding::id_result(inst).to_optional(), + Self::Bitcast(inst) => InstEncoding::id_result(inst).to_optional(), + Self::SNegate(inst) => InstEncoding::id_result(inst).to_optional(), + Self::FNegate(inst) => InstEncoding::id_result(inst).to_optional(), + Self::IAdd(inst) => InstEncoding::id_result(inst).to_optional(), + Self::FAdd(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ISub(inst) => InstEncoding::id_result(inst).to_optional(), + Self::FSub(inst) => InstEncoding::id_result(inst).to_optional(), + Self::IMul(inst) => InstEncoding::id_result(inst).to_optional(), + Self::FMul(inst) => InstEncoding::id_result(inst).to_optional(), + Self::UDiv(inst) => InstEncoding::id_result(inst).to_optional(), + Self::SDiv(inst) => InstEncoding::id_result(inst).to_optional(), + Self::FDiv(inst) => InstEncoding::id_result(inst).to_optional(), + Self::UMod(inst) => InstEncoding::id_result(inst).to_optional(), + Self::SRem(inst) => InstEncoding::id_result(inst).to_optional(), + Self::SMod(inst) => InstEncoding::id_result(inst).to_optional(), + Self::FRem(inst) => InstEncoding::id_result(inst).to_optional(), + Self::FMod(inst) => InstEncoding::id_result(inst).to_optional(), + Self::LogicalEqual(inst) => InstEncoding::id_result(inst).to_optional(), + Self::LogicalNotEqual(inst) => InstEncoding::id_result(inst).to_optional(), + Self::LogicalOr(inst) => InstEncoding::id_result(inst).to_optional(), + Self::LogicalAnd(inst) => InstEncoding::id_result(inst).to_optional(), + Self::LogicalNot(inst) => InstEncoding::id_result(inst).to_optional(), + Self::Select(inst) => InstEncoding::id_result(inst).to_optional(), + Self::IEqual(inst) => InstEncoding::id_result(inst).to_optional(), + Self::INotEqual(inst) => InstEncoding::id_result(inst).to_optional(), + Self::UGreaterThan(inst) => InstEncoding::id_result(inst).to_optional(), + Self::SGreaterThan(inst) => InstEncoding::id_result(inst).to_optional(), + Self::UGreaterThanEqual(inst) => InstEncoding::id_result(inst).to_optional(), + Self::SGreaterThanEqual(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ULessThan(inst) => InstEncoding::id_result(inst).to_optional(), + Self::SLessThan(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ULessThanEqual(inst) => InstEncoding::id_result(inst).to_optional(), + Self::SLessThanEqual(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ShiftRightLogical(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ShiftRightArithmetic(inst) => InstEncoding::id_result(inst).to_optional(), + Self::ShiftLeftLogical(inst) => InstEncoding::id_result(inst).to_optional(), + Self::BitwiseOr(inst) => InstEncoding::id_result(inst).to_optional(), + Self::BitwiseXor(inst) => InstEncoding::id_result(inst).to_optional(), + Self::BitwiseAnd(inst) => InstEncoding::id_result(inst).to_optional(), + Self::Not(inst) => InstEncoding::id_result(inst).to_optional(), + } + } + fn id_result_type(&self) -> Self::IdResultType { + profiling::function_scope!(); + match self { + Self::AccessChain(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::InBoundsAccessChain(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::PtrAccessChain(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::InBoundsPtrAccessChain(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::VectorShuffle(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::CompositeExtract(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::CompositeInsert(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ConvertFToU(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ConvertFToS(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ConvertSToF(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ConvertUToF(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::UConvert(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::SConvert(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::FConvert(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::QuantizeToF16(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ConvertPtrToU(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ConvertUToPtr(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::PtrCastToGeneric(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::GenericCastToPtr(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::Bitcast(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::SNegate(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::FNegate(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::IAdd(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::FAdd(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ISub(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::FSub(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::IMul(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::FMul(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::UDiv(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::SDiv(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::FDiv(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::UMod(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::SRem(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::SMod(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::FRem(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::FMod(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::LogicalEqual(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::LogicalNotEqual(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::LogicalOr(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::LogicalAnd(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::LogicalNot(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::Select(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::IEqual(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::INotEqual(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::UGreaterThan(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::SGreaterThan(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::UGreaterThanEqual(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::SGreaterThanEqual(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ULessThan(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::SLessThan(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ULessThanEqual(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::SLessThanEqual(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ShiftRightLogical(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ShiftRightArithmetic(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::ShiftLeftLogical(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::BitwiseOr(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::BitwiseXor(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::BitwiseAnd(inst) => InstEncoding::id_result_type(inst).to_optional(), + Self::Not(inst) => InstEncoding::id_result_type(inst).to_optional(), + } + } + fn name() -> &'static str { + stringify!(CoreOpSpecOpInstSet) + } + fn encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + match self { + Self::AccessChain(inst) => InstEncoding::encode(inst, writer), + Self::InBoundsAccessChain(inst) => InstEncoding::encode(inst, writer), + Self::PtrAccessChain(inst) => InstEncoding::encode(inst, writer), + Self::InBoundsPtrAccessChain(inst) => InstEncoding::encode(inst, writer), + Self::VectorShuffle(inst) => InstEncoding::encode(inst, writer), + Self::CompositeExtract(inst) => InstEncoding::encode(inst, writer), + Self::CompositeInsert(inst) => InstEncoding::encode(inst, writer), + Self::ConvertFToU(inst) => InstEncoding::encode(inst, writer), + Self::ConvertFToS(inst) => InstEncoding::encode(inst, writer), + Self::ConvertSToF(inst) => InstEncoding::encode(inst, writer), + Self::ConvertUToF(inst) => InstEncoding::encode(inst, writer), + Self::UConvert(inst) => InstEncoding::encode(inst, writer), + Self::SConvert(inst) => InstEncoding::encode(inst, writer), + Self::FConvert(inst) => InstEncoding::encode(inst, writer), + Self::QuantizeToF16(inst) => InstEncoding::encode(inst, writer), + Self::ConvertPtrToU(inst) => InstEncoding::encode(inst, writer), + Self::ConvertUToPtr(inst) => InstEncoding::encode(inst, writer), + Self::PtrCastToGeneric(inst) => InstEncoding::encode(inst, writer), + Self::GenericCastToPtr(inst) => InstEncoding::encode(inst, writer), + Self::Bitcast(inst) => InstEncoding::encode(inst, writer), + Self::SNegate(inst) => InstEncoding::encode(inst, writer), + Self::FNegate(inst) => InstEncoding::encode(inst, writer), + Self::IAdd(inst) => InstEncoding::encode(inst, writer), + Self::FAdd(inst) => InstEncoding::encode(inst, writer), + Self::ISub(inst) => InstEncoding::encode(inst, writer), + Self::FSub(inst) => InstEncoding::encode(inst, writer), + Self::IMul(inst) => InstEncoding::encode(inst, writer), + Self::FMul(inst) => InstEncoding::encode(inst, writer), + Self::UDiv(inst) => InstEncoding::encode(inst, writer), + Self::SDiv(inst) => InstEncoding::encode(inst, writer), + Self::FDiv(inst) => InstEncoding::encode(inst, writer), + Self::UMod(inst) => InstEncoding::encode(inst, writer), + Self::SRem(inst) => InstEncoding::encode(inst, writer), + Self::SMod(inst) => InstEncoding::encode(inst, writer), + Self::FRem(inst) => InstEncoding::encode(inst, writer), + Self::FMod(inst) => InstEncoding::encode(inst, writer), + Self::LogicalEqual(inst) => InstEncoding::encode(inst, writer), + Self::LogicalNotEqual(inst) => InstEncoding::encode(inst, writer), + Self::LogicalOr(inst) => InstEncoding::encode(inst, writer), + Self::LogicalAnd(inst) => InstEncoding::encode(inst, writer), + Self::LogicalNot(inst) => InstEncoding::encode(inst, writer), + Self::Select(inst) => InstEncoding::encode(inst, writer), + Self::IEqual(inst) => InstEncoding::encode(inst, writer), + Self::INotEqual(inst) => InstEncoding::encode(inst, writer), + Self::UGreaterThan(inst) => InstEncoding::encode(inst, writer), + Self::SGreaterThan(inst) => InstEncoding::encode(inst, writer), + Self::UGreaterThanEqual(inst) => InstEncoding::encode(inst, writer), + Self::SGreaterThanEqual(inst) => InstEncoding::encode(inst, writer), + Self::ULessThan(inst) => InstEncoding::encode(inst, writer), + Self::SLessThan(inst) => InstEncoding::encode(inst, writer), + Self::ULessThanEqual(inst) => InstEncoding::encode(inst, writer), + Self::SLessThanEqual(inst) => InstEncoding::encode(inst, writer), + Self::ShiftRightLogical(inst) => InstEncoding::encode(inst, writer), + Self::ShiftRightArithmetic(inst) => InstEncoding::encode(inst, writer), + Self::ShiftLeftLogical(inst) => InstEncoding::encode(inst, writer), + Self::BitwiseOr(inst) => InstEncoding::encode(inst, writer), + Self::BitwiseXor(inst) => InstEncoding::encode(inst, writer), + Self::BitwiseAnd(inst) => InstEncoding::encode(inst, writer), + Self::Not(inst) => InstEncoding::encode(inst, writer), + } + } + fn decode(reader: InstReader<'_>) -> Result { + profiling::function_scope!(); + let opcode = reader.opcode(); + Ok(match opcode { + 65u16 => Self::AccessChain(::decode(reader)?), + 66u16 => { + Self::InBoundsAccessChain(::decode(reader)?) + } + 67u16 => Self::PtrAccessChain(::decode(reader)?), + 70u16 => Self::InBoundsPtrAccessChain( + ::decode(reader)?, + ), + 79u16 => Self::VectorShuffle(::decode(reader)?), + 81u16 => Self::CompositeExtract(::decode(reader)?), + 82u16 => Self::CompositeInsert(::decode(reader)?), + 109u16 => Self::ConvertFToU(::decode(reader)?), + 110u16 => Self::ConvertFToS(::decode(reader)?), + 111u16 => Self::ConvertSToF(::decode(reader)?), + 112u16 => Self::ConvertUToF(::decode(reader)?), + 113u16 => Self::UConvert(::decode(reader)?), + 114u16 => Self::SConvert(::decode(reader)?), + 115u16 => Self::FConvert(::decode(reader)?), + 116u16 => Self::QuantizeToF16(::decode(reader)?), + 117u16 => Self::ConvertPtrToU(::decode(reader)?), + 120u16 => Self::ConvertUToPtr(::decode(reader)?), + 121u16 => Self::PtrCastToGeneric(::decode(reader)?), + 122u16 => Self::GenericCastToPtr(::decode(reader)?), + 124u16 => Self::Bitcast(::decode(reader)?), + 126u16 => Self::SNegate(::decode(reader)?), + 127u16 => Self::FNegate(::decode(reader)?), + 128u16 => Self::IAdd(::decode(reader)?), + 129u16 => Self::FAdd(::decode(reader)?), + 130u16 => Self::ISub(::decode(reader)?), + 131u16 => Self::FSub(::decode(reader)?), + 132u16 => Self::IMul(::decode(reader)?), + 133u16 => Self::FMul(::decode(reader)?), + 134u16 => Self::UDiv(::decode(reader)?), + 135u16 => Self::SDiv(::decode(reader)?), + 136u16 => Self::FDiv(::decode(reader)?), + 137u16 => Self::UMod(::decode(reader)?), + 138u16 => Self::SRem(::decode(reader)?), + 139u16 => Self::SMod(::decode(reader)?), + 140u16 => Self::FRem(::decode(reader)?), + 141u16 => Self::FMod(::decode(reader)?), + 164u16 => Self::LogicalEqual(::decode(reader)?), + 165u16 => Self::LogicalNotEqual(::decode(reader)?), + 166u16 => Self::LogicalOr(::decode(reader)?), + 167u16 => Self::LogicalAnd(::decode(reader)?), + 168u16 => Self::LogicalNot(::decode(reader)?), + 169u16 => Self::Select(::decode(reader)?), + 170u16 => Self::IEqual(::decode(reader)?), + 171u16 => Self::INotEqual(::decode(reader)?), + 172u16 => Self::UGreaterThan(::decode(reader)?), + 173u16 => Self::SGreaterThan(::decode(reader)?), + 174u16 => { + Self::UGreaterThanEqual(::decode(reader)?) + } + 175u16 => { + Self::SGreaterThanEqual(::decode(reader)?) + } + 176u16 => Self::ULessThan(::decode(reader)?), + 177u16 => Self::SLessThan(::decode(reader)?), + 178u16 => Self::ULessThanEqual(::decode(reader)?), + 179u16 => Self::SLessThanEqual(::decode(reader)?), + 194u16 => { + Self::ShiftRightLogical(::decode(reader)?) + } + 195u16 => Self::ShiftRightArithmetic(::decode( + reader, + )?), + 196u16 => Self::ShiftLeftLogical(::decode(reader)?), + 197u16 => Self::BitwiseOr(::decode(reader)?), + 198u16 => Self::BitwiseXor(::decode(reader)?), + 199u16 => Self::BitwiseAnd(::decode(reader)?), + 200u16 => Self::Not(::decode(reader)?), + _ => { + return Err(DecodeErrorKind::UnknownOpCode { opcode }.into()); + } + }) + } + fn dis_fmt(&self, f: &mut Formatter<'_>, ctx: &DisContext) -> std::fmt::Result { + profiling::function_scope!(); + match self { + Self::AccessChain(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::InBoundsAccessChain(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::PtrAccessChain(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::InBoundsPtrAccessChain(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::VectorShuffle(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::CompositeExtract(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::CompositeInsert(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ConvertFToU(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ConvertFToS(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ConvertSToF(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ConvertUToF(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::UConvert(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::SConvert(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::FConvert(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::QuantizeToF16(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ConvertPtrToU(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ConvertUToPtr(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::PtrCastToGeneric(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::GenericCastToPtr(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::Bitcast(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::SNegate(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::FNegate(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::IAdd(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::FAdd(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ISub(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::FSub(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::IMul(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::FMul(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::UDiv(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::SDiv(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::FDiv(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::UMod(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::SRem(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::SMod(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::FRem(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::FMod(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::LogicalEqual(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::LogicalNotEqual(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::LogicalOr(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::LogicalAnd(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::LogicalNot(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::Select(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::IEqual(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::INotEqual(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::UGreaterThan(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::SGreaterThan(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::UGreaterThanEqual(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::SGreaterThanEqual(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ULessThan(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::SLessThan(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ULessThanEqual(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::SLessThanEqual(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ShiftRightLogical(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ShiftRightArithmetic(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::ShiftLeftLogical(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::BitwiseOr(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::BitwiseXor(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::BitwiseAnd(inst) => InstEncoding::dis_fmt(inst, f, ctx), + Self::Not(inst) => InstEncoding::dis_fmt(inst, f, ctx), + } + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpAccessChain) -> Self { + Self::AccessChain(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpInBoundsAccessChain) -> Self { + Self::InBoundsAccessChain(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpPtrAccessChain) -> Self { + Self::PtrAccessChain(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpInBoundsPtrAccessChain) -> Self { + Self::InBoundsPtrAccessChain(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpVectorShuffle) -> Self { + Self::VectorShuffle(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpCompositeExtract) -> Self { + Self::CompositeExtract(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpCompositeInsert) -> Self { + Self::CompositeInsert(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpConvertFToU) -> Self { + Self::ConvertFToU(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpConvertFToS) -> Self { + Self::ConvertFToS(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpConvertSToF) -> Self { + Self::ConvertSToF(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpConvertUToF) -> Self { + Self::ConvertUToF(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpUConvert) -> Self { + Self::UConvert(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpSConvert) -> Self { + Self::SConvert(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpFConvert) -> Self { + Self::FConvert(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpQuantizeToF16) -> Self { + Self::QuantizeToF16(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpConvertPtrToU) -> Self { + Self::ConvertPtrToU(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpConvertUToPtr) -> Self { + Self::ConvertUToPtr(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpPtrCastToGeneric) -> Self { + Self::PtrCastToGeneric(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpGenericCastToPtr) -> Self { + Self::GenericCastToPtr(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpBitcast) -> Self { + Self::Bitcast(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpSNegate) -> Self { + Self::SNegate(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpFNegate) -> Self { + Self::FNegate(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpIAdd) -> Self { + Self::IAdd(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpFAdd) -> Self { + Self::FAdd(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpISub) -> Self { + Self::ISub(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpFSub) -> Self { + Self::FSub(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpIMul) -> Self { + Self::IMul(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpFMul) -> Self { + Self::FMul(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpUDiv) -> Self { + Self::UDiv(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpSDiv) -> Self { + Self::SDiv(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpFDiv) -> Self { + Self::FDiv(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpUMod) -> Self { + Self::UMod(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpSRem) -> Self { + Self::SRem(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpSMod) -> Self { + Self::SMod(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpFRem) -> Self { + Self::FRem(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpFMod) -> Self { + Self::FMod(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpLogicalEqual) -> Self { + Self::LogicalEqual(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpLogicalNotEqual) -> Self { + Self::LogicalNotEqual(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpLogicalOr) -> Self { + Self::LogicalOr(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpLogicalAnd) -> Self { + Self::LogicalAnd(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpLogicalNot) -> Self { + Self::LogicalNot(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpSelect) -> Self { + Self::Select(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpIEqual) -> Self { + Self::IEqual(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpINotEqual) -> Self { + Self::INotEqual(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpUGreaterThan) -> Self { + Self::UGreaterThan(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpSGreaterThan) -> Self { + Self::SGreaterThan(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpUGreaterThanEqual) -> Self { + Self::UGreaterThanEqual(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpSGreaterThanEqual) -> Self { + Self::SGreaterThanEqual(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpULessThan) -> Self { + Self::ULessThan(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpSLessThan) -> Self { + Self::SLessThan(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpULessThanEqual) -> Self { + Self::ULessThanEqual(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpSLessThanEqual) -> Self { + Self::SLessThanEqual(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpShiftRightLogical) -> Self { + Self::ShiftRightLogical(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpShiftRightArithmetic) -> Self { + Self::ShiftRightArithmetic(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpShiftLeftLogical) -> Self { + Self::ShiftLeftLogical(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpBitwiseOr) -> Self { + Self::BitwiseOr(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpBitwiseXor) -> Self { + Self::BitwiseXor(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpBitwiseAnd) -> Self { + Self::BitwiseAnd(inst) + } +} +impl From for CoreOpSpecOpInstSet { + fn from(inst: OpNot) -> Self { + Self::Not(inst) + } +} +impl OpSpecOpInst for CoreOpSpecOpInstSet { + fn op_spec_op_encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + match self { + Self::AccessChain(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::InBoundsAccessChain(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::PtrAccessChain(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::InBoundsPtrAccessChain(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::VectorShuffle(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::CompositeExtract(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::CompositeInsert(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ConvertFToU(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ConvertFToS(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ConvertSToF(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ConvertUToF(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::UConvert(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::SConvert(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::FConvert(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::QuantizeToF16(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ConvertPtrToU(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ConvertUToPtr(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::PtrCastToGeneric(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::GenericCastToPtr(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::Bitcast(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::SNegate(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::FNegate(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::IAdd(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::FAdd(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ISub(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::FSub(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::IMul(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::FMul(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::UDiv(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::SDiv(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::FDiv(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::UMod(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::SRem(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::SMod(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::FRem(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::FMod(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::LogicalEqual(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::LogicalNotEqual(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::LogicalOr(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::LogicalAnd(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::LogicalNot(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::Select(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::IEqual(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::INotEqual(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::UGreaterThan(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::SGreaterThan(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::UGreaterThanEqual(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::SGreaterThanEqual(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ULessThan(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::SLessThan(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ULessThanEqual(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::SLessThanEqual(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ShiftRightLogical(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ShiftRightArithmetic(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::ShiftLeftLogical(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::BitwiseOr(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::BitwiseXor(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::BitwiseAnd(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + Self::Not(inst) => OpSpecOpInst::op_spec_op_encode(inst, writer), + } + } + fn op_spec_op_decode(reader: &[Word]) -> Result { + profiling::function_scope!(); + let opcode = reader[2].to_op().0; + Ok(match opcode { + 65u16 => Self::AccessChain(::op_spec_op_decode(reader)?), + 66u16 => Self::InBoundsAccessChain( + ::op_spec_op_decode(reader)?, + ), + 67u16 => Self::PtrAccessChain(::op_spec_op_decode( + reader, + )?), + 70u16 => Self::InBoundsPtrAccessChain( + ::op_spec_op_decode(reader)?, + ), + 79u16 => Self::VectorShuffle(::op_spec_op_decode( + reader, + )?), + 81u16 => Self::CompositeExtract( + ::op_spec_op_decode(reader)?, + ), + 82u16 => Self::CompositeInsert(::op_spec_op_decode( + reader, + )?), + 109u16 => { + Self::ConvertFToU(::op_spec_op_decode(reader)?) + } + 110u16 => { + Self::ConvertFToS(::op_spec_op_decode(reader)?) + } + 111u16 => { + Self::ConvertSToF(::op_spec_op_decode(reader)?) + } + 112u16 => { + Self::ConvertUToF(::op_spec_op_decode(reader)?) + } + 113u16 => Self::UConvert(::op_spec_op_decode(reader)?), + 114u16 => Self::SConvert(::op_spec_op_decode(reader)?), + 115u16 => Self::FConvert(::op_spec_op_decode(reader)?), + 116u16 => Self::QuantizeToF16(::op_spec_op_decode( + reader, + )?), + 117u16 => Self::ConvertPtrToU(::op_spec_op_decode( + reader, + )?), + 120u16 => Self::ConvertUToPtr(::op_spec_op_decode( + reader, + )?), + 121u16 => Self::PtrCastToGeneric( + ::op_spec_op_decode(reader)?, + ), + 122u16 => Self::GenericCastToPtr( + ::op_spec_op_decode(reader)?, + ), + 124u16 => Self::Bitcast(::op_spec_op_decode(reader)?), + 126u16 => Self::SNegate(::op_spec_op_decode(reader)?), + 127u16 => Self::FNegate(::op_spec_op_decode(reader)?), + 128u16 => Self::IAdd(::op_spec_op_decode(reader)?), + 129u16 => Self::FAdd(::op_spec_op_decode(reader)?), + 130u16 => Self::ISub(::op_spec_op_decode(reader)?), + 131u16 => Self::FSub(::op_spec_op_decode(reader)?), + 132u16 => Self::IMul(::op_spec_op_decode(reader)?), + 133u16 => Self::FMul(::op_spec_op_decode(reader)?), + 134u16 => Self::UDiv(::op_spec_op_decode(reader)?), + 135u16 => Self::SDiv(::op_spec_op_decode(reader)?), + 136u16 => Self::FDiv(::op_spec_op_decode(reader)?), + 137u16 => Self::UMod(::op_spec_op_decode(reader)?), + 138u16 => Self::SRem(::op_spec_op_decode(reader)?), + 139u16 => Self::SMod(::op_spec_op_decode(reader)?), + 140u16 => Self::FRem(::op_spec_op_decode(reader)?), + 141u16 => Self::FMod(::op_spec_op_decode(reader)?), + 164u16 => { + Self::LogicalEqual(::op_spec_op_decode(reader)?) + } + 165u16 => Self::LogicalNotEqual( + ::op_spec_op_decode(reader)?, + ), + 166u16 => Self::LogicalOr(::op_spec_op_decode(reader)?), + 167u16 => Self::LogicalAnd(::op_spec_op_decode(reader)?), + 168u16 => Self::LogicalNot(::op_spec_op_decode(reader)?), + 169u16 => Self::Select(::op_spec_op_decode(reader)?), + 170u16 => Self::IEqual(::op_spec_op_decode(reader)?), + 171u16 => Self::INotEqual(::op_spec_op_decode(reader)?), + 172u16 => { + Self::UGreaterThan(::op_spec_op_decode(reader)?) + } + 173u16 => { + Self::SGreaterThan(::op_spec_op_decode(reader)?) + } + 174u16 => Self::UGreaterThanEqual( + ::op_spec_op_decode(reader)?, + ), + 175u16 => Self::SGreaterThanEqual( + ::op_spec_op_decode(reader)?, + ), + 176u16 => Self::ULessThan(::op_spec_op_decode(reader)?), + 177u16 => Self::SLessThan(::op_spec_op_decode(reader)?), + 178u16 => Self::ULessThanEqual(::op_spec_op_decode( + reader, + )?), + 179u16 => Self::SLessThanEqual(::op_spec_op_decode( + reader, + )?), + 194u16 => Self::ShiftRightLogical( + ::op_spec_op_decode(reader)?, + ), + 195u16 => Self::ShiftRightArithmetic( + ::op_spec_op_decode(reader)?, + ), + 196u16 => Self::ShiftLeftLogical( + ::op_spec_op_decode(reader)?, + ), + 197u16 => Self::BitwiseOr(::op_spec_op_decode(reader)?), + 198u16 => Self::BitwiseXor(::op_spec_op_decode(reader)?), + 199u16 => Self::BitwiseAnd(::op_spec_op_decode(reader)?), + 200u16 => Self::Not(::op_spec_op_decode(reader)?), + _ => { + return Err(DecodeErrorKind::UnknownOpCode { opcode }.into()); + } + }) + } + fn op_spec_op_dis_fmt( + &self, + f: &mut Formatter<'_>, + ctx: OperandDisContext<'_>, + ) -> std::fmt::Result { + profiling::function_scope!(); + match self { + Self::AccessChain(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::InBoundsAccessChain(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::PtrAccessChain(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::InBoundsPtrAccessChain(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::VectorShuffle(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::CompositeExtract(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::CompositeInsert(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ConvertFToU(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ConvertFToS(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ConvertSToF(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ConvertUToF(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::UConvert(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::SConvert(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::FConvert(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::QuantizeToF16(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ConvertPtrToU(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ConvertUToPtr(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::PtrCastToGeneric(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::GenericCastToPtr(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::Bitcast(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::SNegate(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::FNegate(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::IAdd(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::FAdd(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ISub(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::FSub(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::IMul(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::FMul(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::UDiv(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::SDiv(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::FDiv(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::UMod(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::SRem(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::SMod(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::FRem(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::FMod(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::LogicalEqual(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::LogicalNotEqual(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::LogicalOr(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::LogicalAnd(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::LogicalNot(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::Select(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::IEqual(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::INotEqual(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::UGreaterThan(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::SGreaterThan(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::UGreaterThanEqual(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::SGreaterThanEqual(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ULessThan(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::SLessThan(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ULessThanEqual(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::SLessThanEqual(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ShiftRightLogical(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ShiftRightArithmetic(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::ShiftLeftLogical(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::BitwiseOr(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::BitwiseXor(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::BitwiseAnd(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + Self::Not(inst) => OpSpecOpInst::op_spec_op_dis_fmt(inst, f, ctx), + } + } +} diff --git a/crates/rspirv2/src/lib.rs b/crates/rspirv2/src/lib.rs index 1a5cba2d..79f6c464 100644 --- a/crates/rspirv2/src/lib.rs +++ b/crates/rspirv2/src/lib.rs @@ -2,6 +2,7 @@ pub mod core; pub mod dis; +pub mod op_spec_op; pub mod op_switch; #[deprecated(note = "module renamed to `op_switch`")] diff --git a/crates/rspirv2/src/op_spec_op.rs b/crates/rspirv2/src/op_spec_op.rs new file mode 100644 index 00000000..ffa7641e --- /dev/null +++ b/crates/rspirv2/src/op_spec_op.rs @@ -0,0 +1,66 @@ +use crate::core::inst_meta::OP_SPEC_CONSTANT_OP; +use crate::core::op_spec_op::CoreOpSpecOpInstSet; +use rspirv2_types::binary::{DecodeError, EncodeError, InstReader, WordCounter, WordWriter}; +use rspirv2_types::dis::DisContext; +use rspirv2_types::inst::{Inst, InstEncoding}; +use rspirv2_types::meta::InstMeta; +pub use rspirv2_types::op_spec_op::*; +use rspirv2_types::operand::{IdResult, IdResultType, OperandDisContext, OperandEncoding}; +use std::fmt::Formatter; + +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub struct OpSpecConstantOp(pub CoreOpSpecOpInstSet); + +impl Inst for OpSpecConstantOp { + const META: &InstMeta = &OP_SPEC_CONSTANT_OP; +} + +impl InstEncoding for OpSpecConstantOp { + type IdResult = IdResult; + type IdResultType = IdResultType; + + fn id_result(&self) -> Self::IdResult { + // unwrap is unreachable + self.0.id_result().unwrap() + } + + fn id_result_type(&self) -> Self::IdResultType { + // unwrap is unreachable + self.0.id_result_type().unwrap() + } + + fn encode(&self, writer: &mut impl WordWriter) -> Result<(), EncodeError> { + profiling::function_scope!(); + // we don't have a good way of computing the len ourselves, let's hope this gets inlined and optimized nicely + let mut len = WordCounter::default(); + self.0.op_spec_op_encode(&mut len)?; + // +1 as len must include the `OpSpecConstantOp` opcode word as well + writer.write_op(Self::META.opcode, *len + 1)?; + self.0.op_spec_op_encode(writer) + } + + fn decode(reader: InstReader<'_>) -> Result { + profiling::function_scope!(); + let op_reader = reader.check_opcode(Self::META)?; + Ok(Self(CoreOpSpecOpInstSet::op_spec_op_decode( + op_reader.as_slice(), + )?)) + } + + fn dis_fmt(&self, f: &mut Formatter<'_>, ctx: &DisContext) -> std::fmt::Result { + profiling::function_scope!(); + let ctx = OperandDisContext { + id_result: Some(self.id_result()), + id_result_type: Some(self.id_result_type()), + ctx, + }; + let rspirv_space = ctx.rspirv_space(); + write!( + f, + "{}OpSpecConstantOp{rspirv_space}{}{rspirv_space} {}", + ctx.id_result_writer(), + self.id_result_type().dis(ctx), + self.0.op_spec_op_dis(ctx) + ) + } +} diff --git a/tests/spv/spec_constant_op/spec_constant_op.comp b/tests/spv/spec_constant_op/spec_constant_op.comp new file mode 100644 index 00000000..e06bb652 --- /dev/null +++ b/tests/spv/spec_constant_op/spec_constant_op.comp @@ -0,0 +1,17 @@ + +#version 450 + +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +layout(constant_id = 0) const uint a = 64; +layout(constant_id = 1) const uint b = 64; +layout(constant_id = 2) const int c = 64; + +layout(set = 0, binding = 0) buffer Data { + uint data[]; +}; + +void main() { + uint idx = gl_GlobalInvocationID.x; + data[idx] = a * b + int(c); +} diff --git a/tests/spv/spec_constant_op/spec_constant_op.rspirv2 b/tests/spv/spec_constant_op/spec_constant_op.rspirv2 new file mode 100644 index 00000000..eed3f9ea --- /dev/null +++ b/tests/spv/spec_constant_op/spec_constant_op.rspirv2 @@ -0,0 +1,63 @@ + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID + OpExecutionMode %main LocalSize 64 1 1 + OpSource GLSL 450 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %idx "idx" + OpName %gl_GlobalInvocationID "gl_GlobalInvocationID" + OpName %Data "Data" + OpMemberName %Data 0 "data" + OpName %19 "" + OpName %a "a" + OpName %b "b" + OpName %c "c" + OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId + OpDecorate %_runtimearr_u32 ArrayStride 4 + OpDecorate %Data BufferBlock + OpMemberDecorate %Data 0 Offset 0 + OpDecorate %19 Binding 0 + OpDecorate %19 DescriptorSet 0 + OpDecorate %a SpecId 0 + OpDecorate %b SpecId 1 + OpDecorate %c SpecId 2 + OpDecorate %33 BuiltIn WorkgroupSize + %void = OpTypeVoid + %3 = OpTypeFunction %void + %u32 = OpTypeInt 32 0 +%_ptr_Function_u32 = OpTypePointer Function %u32 + %v3u32 = OpTypeVector %u32 3 +%_ptr_Input_v3u32 = OpTypePointer Input %v3u32 +%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3u32 Input + %u32_0 = OpConstant %u32 0 +%_ptr_Input_u32 = OpTypePointer Input %u32 +%_runtimearr_u32 = OpTypeRuntimeArray %u32 + %Data = OpTypeStruct %_runtimearr_u32 +%_ptr_Uniform_Data = OpTypePointer Uniform %Data + %19 = OpVariable %_ptr_Uniform_Data Uniform + %i32 = OpTypeInt 32 1 + %i32_0 = OpConstant %i32 0 + %a = OpSpecConstant %u32 64 + %b = OpSpecConstant %u32 64 + %25 = OpSpecConstantOp %u32 OpIMul %a %b + %c = OpSpecConstant %i32 64 + %27 = OpSpecConstantOp %u32 OpIAdd %c %u32_0 + %28 = OpSpecConstantOp %u32 OpIAdd %25 %27 +%_ptr_Uniform_u32 = OpTypePointer Uniform %u32 + %u32_64 = OpConstant %u32 64 + %u32_1 = OpConstant %u32 1 + %33 = OpConstantComposite %v3u32 %u32_64 %u32_1 %u32_1 + %main = OpFunction %void None %3 + %5 = OpLabel + %idx = OpVariable %_ptr_Function_u32 Function + %14 = OpAccessChain %_ptr_Input_u32 %gl_GlobalInvocationID %u32_0 + %15 = OpLoad %u32 %14 + OpStore %idx %15 + %22 = OpLoad %u32 %idx + %30 = OpAccessChain %_ptr_Uniform_u32 %19 %i32_0 %22 + OpStore %30 %28 + OpReturn + OpFunctionEnd diff --git a/tests/spv/spec_constant_op/spec_constant_op.spv b/tests/spv/spec_constant_op/spec_constant_op.spv new file mode 100644 index 00000000..e5e90556 Binary files /dev/null and b/tests/spv/spec_constant_op/spec_constant_op.spv differ diff --git a/tests/src/lib.rs b/tests/src/lib.rs index f181a83e..ffe7c07e 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -41,6 +41,7 @@ pub const DIS_REFERENCE: SpvFolder<'_> = spv("dis_reference"); pub const TEXTURE_GRAD_OFFSET: SpvFolder<'_> = spv("textureGradOffset"); pub const CONST_SPECS: SpvFolder<'_> = spv("const_specs"); pub const CORE_PRE_LINK: SpvFolder<'_> = spv("core_pre_link"); +pub const SPEC_CONSTANT_OP: SpvFolder<'_> = spv("spec_constant_op"); pub fn test_disassembly(path: PathBuf, expect: ExpectFile, profile: Profile) -> anyhow::Result<()> { for module_swap_bytes in [false, true] { diff --git a/tests/tests/spec_constant_op.rs b/tests/tests/spec_constant_op.rs new file mode 100644 index 00000000..8f176a0c --- /dev/null +++ b/tests/tests/spec_constant_op.rs @@ -0,0 +1,68 @@ +use expect_test::expect; +use rspirv2::binary::IdResultAlloc; +use rspirv2::core::inst::{OpIAdd, OpSpecConstant, OpTypeInt}; +use rspirv2::core::inst_set::CoreInstSet; +use rspirv2::dis::DisOptions; +use rspirv2::module::Module; +use rspirv2::op_spec_op::OpSpecConstantOp; +use rspirv2::operand::{IdRef, IdResultType, LiteralConst, LiteralInteger}; +use rspirv2::vec::InstVec; +use rspirv2_tools_gen::dis::Profile; +use spv::SPEC_CONSTANT_OP; + +#[test] +fn test_encode_decode() { + let mut alloc = IdResultAlloc::new(); + let mut vec = InstVec::::new(); + let u32 = IdResultType(vec.push_inst(OpTypeInt { + id_result: alloc.alloc_id(), + width: LiteralInteger::new(32), + signedness: LiteralInteger::new(0), + })); + let a = vec.push_inst(OpSpecConstant { + id_result_type: u32, + id_result: alloc.alloc_id(), + value: LiteralConst::from(42u32), + }); + + let mut vec2 = InstVec::::new(); + vec2.push_inst(OpSpecConstantOp( + OpIAdd { + id_result_type: u32, + id_result: alloc.alloc_id(), + operand_1: IdRef(a), + operand_2: IdRef(a), + } + .into(), + )); + + // raw bytes + expect![[r#" + [ + 393268, + 0, + 2, + 128, + 1, + 1, + ] + "#]] + .assert_debug_eq(&vec2.as_words().iter().map(|a| a.0).collect::>()); + + // dis + expect![[r#" + %2 = OpSpecConstantOp %0 OpIAdd %1 %1 + "#]] + .assert_eq(&vec2.dis(DisOptions::simple()).to_string()); +} + +#[test] +fn test_spec_constant_op_dis() -> anyhow::Result<()> { + SPEC_CONSTANT_OP.test_disassembly("rspirv2", Profile::Default) +} + +#[test] +fn test_spec_constant_op_checked() -> anyhow::Result<()> { + Module::::from_bytes(&std::fs::read(SPEC_CONSTANT_OP.spv())?)?; + Ok(()) +}