use std::marker::PhantomData;
use crate::spirv;
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct BaseInstruction<'a, Op: Clone + Copy>
where
Op: Into<spirv::Word>,
{
pub opname: &'a str,
pub opcode: Op,
pub capabilities: &'a [spirv::Capability],
pub extensions: &'a [&'a str],
pub operands: &'a [LogicalOperand],
}
pub type Instruction<'a> = BaseInstruction<'a, spirv::Op>;
pub type ExtendedInstruction<'a> = BaseInstruction<'a, ExtInstOp>;
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct LogicalOperand {
pub kind: OperandKind,
pub quantifier: OperandQuantifier,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum OperandQuantifier {
One,
ZeroOrOne,
ZeroOrMore,
}
macro_rules! inst {
($op:ident, [$( $cap:ident ),*], [$( $ext:expr ),*], [$( ($kind:ident, $quant:ident) ),*]) => {
Instruction {
opname: stringify!($op),
opcode: spirv::Op::$op,
capabilities: &[
$( spirv::Capability::$cap ),*
],
extensions: &[
$( $ext ),*
],
operands: &[
$( LogicalOperand {
kind: OperandKind::$kind,
quantifier: OperandQuantifier::$quant }
),*
],
}
}
}
macro_rules! ext_inst {
($variant:ident, $opconst:ident, $opname:ident, [$( $cap:ident ),*], [$( $ext:expr ),*],
[$( ($kind:ident, $quant:ident) ),*]) => {
ext_inst!($variant, $opconst, $opname, [$($cap),*], [$($ext),*],
[$((OperandKind::$kind, $quant)),*],)
};
($variant:ident, $opconst:ident, $opname:ident, [$( $cap:ident ),*], [$( $ext:expr ),*],
[$( ($kind:expr, $quant:ident) ),*], ) => {
ExtendedInstruction {
opname: stringify!($opname),
opcode: ExtInstOp::$variant(spirv::$opconst::$opname),
capabilities: &[
$( spirv::Capability::$cap ),*
],
extensions: &[
$( $ext ),*
],
operands: &[
$( LogicalOperand {
kind: $kind,
quantifier: OperandQuantifier::$quant }
),*
],
}
}
}
pub struct InstructionTable<Op: Into<spirv::Word> + Clone + Copy + Eq + 'static>(
&'static [BaseInstruction<'static, Op>],
PhantomData<Op>,
);
impl<Op: Into<spirv::Word> + Clone + Copy + Eq> InstructionTable<Op> {
pub fn lookup_opcode(
&self,
opcode: spirv::Word,
) -> Option<&'static BaseInstruction<'static, Op>> {
self.0.iter().find(|inst| inst.opcode.into() == opcode)
}
pub fn get(&self, opcode: Op) -> &'static BaseInstruction<'static, Op> {
self.0
.iter()
.find(|inst| inst.opcode == opcode)
.expect("internal error")
}
pub fn iter(&self) -> impl Iterator<Item = &'static BaseInstruction<'static, Op>> {
self.0.iter()
}
}
include!("autogen_tables.rs");