Skip to main content

rspirv/grammar/
syntax.rs

1use std::marker::PhantomData;
2
3use crate::spirv;
4
5/// Grammar for a SPIR-V instruction.
6#[derive(Debug, PartialEq, Eq, Hash)]
7pub struct BaseInstruction<'a, Op: Clone + Copy>
8where
9    Op: Into<spirv::Word>,
10{
11    /// Opname.
12    pub opname: &'a str,
13    /// Opcode.
14    pub opcode: Op,
15    /// Capabilities required for this instruction.
16    pub capabilities: &'a [spirv::Capability],
17    /// Extensions required for this instruction.
18    pub extensions: &'a [&'a str],
19    /// Logical operands for this instruction.
20    ///
21    /// This includes result type id and result id.
22    pub operands: &'a [LogicalOperand],
23}
24
25pub type Instruction<'a> = BaseInstruction<'a, spirv::Op>;
26pub type ExtendedInstruction<'a> = BaseInstruction<'a, ExtInstOp>;
27
28/// Grammar for a SPIR-V logical operand.
29#[derive(Debug, PartialEq, Eq, Hash, Clone)]
30pub struct LogicalOperand {
31    /// The kind of this logical operand.
32    pub kind: OperandKind,
33    /// The repeat specification for this logical operand.
34    pub quantifier: OperandQuantifier,
35}
36
37/// The repeat specification for a SPIR-V logical operand.
38#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
39pub enum OperandQuantifier {
40    /// This operand appears exactly one time.
41    One,
42    /// This operand can appear zero or one time.
43    ZeroOrOne,
44    /// This operand can appear zero or more times.
45    ZeroOrMore,
46}
47
48/// Declares the grammar for an SPIR-V instruction.
49macro_rules! inst {
50    ($op:ident, [$( $cap:ident ),*], [$( $ext:expr ),*], [$( ($kind:ident, $quant:ident) ),*]) => {
51        Instruction {
52            opname: stringify!($op),
53            opcode: spirv::Op::$op,
54            capabilities: &[
55                $( spirv::Capability::$cap ),*
56            ],
57            extensions: &[
58                $( $ext ),*
59            ],
60            operands: &[
61                $( LogicalOperand {
62                    kind: OperandKind::$kind,
63                    quantifier: OperandQuantifier::$quant }
64                ),*
65            ],
66        }
67    }
68}
69
70/// Declares the grammar for an extended instruction instruction.
71///
72/// Operand kinds can be plain idents (resolved as `OperandKind::$kind`)
73/// or full expressions (e.g. `OperandKind::DebugInfo(ExtOperandKind::...)`
74/// for extension-specific kinds).
75macro_rules! ext_inst {
76    // All-ident operands: wrap as OperandKind::$kind and forward to the expr arm
77    ($variant:ident, $opconst:ident, $opname:ident, [$( $cap:ident ),*], [$( $ext:expr ),*],
78     [$( ($kind:ident, $quant:ident) ),*]) => {
79        ext_inst!($variant, $opconst, $opname, [$($cap),*], [$($ext),*],
80            [$((OperandKind::$kind, $quant)),*],)
81    };
82    // Pre-wrapped expression operands (from extensions with own operand kinds).
83    // Trailing comma distinguishes from the ident arm above.
84    ($variant:ident, $opconst:ident, $opname:ident, [$( $cap:ident ),*], [$( $ext:expr ),*],
85     [$( ($kind:expr, $quant:ident) ),*], ) => {
86        ExtendedInstruction {
87            opname: stringify!($opname),
88            opcode: ExtInstOp::$variant(spirv::$opconst::$opname),
89            capabilities: &[
90                $( spirv::Capability::$cap ),*
91            ],
92            extensions: &[
93                $( $ext ),*
94            ],
95            operands: &[
96                $( LogicalOperand {
97                    kind: $kind,
98                    quantifier: OperandQuantifier::$quant }
99                ),*
100            ],
101        }
102    }
103}
104
105/// The table for all SPIR-V core instructions.
106///
107/// This table is static data stored in the library.
108pub struct InstructionTable<Op: Into<spirv::Word> + Clone + Copy + Eq + 'static>(
109    &'static [BaseInstruction<'static, Op>],
110    PhantomData<Op>,
111);
112
113impl<Op: Into<spirv::Word> + Clone + Copy + Eq> InstructionTable<Op> {
114    /// Looks up the given `opcode` in the instruction table and returns
115    /// a reference to the instruction grammar entry if found.
116    pub fn lookup_opcode(
117        &self,
118        opcode: spirv::Word,
119    ) -> Option<&'static BaseInstruction<'static, Op>> {
120        self.0.iter().find(|inst| inst.opcode.into() == opcode)
121    }
122
123    /// Returns a reference to the instruction grammar entry with the given
124    /// `opcode`.
125    pub fn get(&self, opcode: Op) -> &'static BaseInstruction<'static, Op> {
126        self.0
127            .iter()
128            .find(|inst| inst.opcode == opcode)
129            .expect("internal error")
130    }
131
132    pub fn iter(&self) -> impl Iterator<Item = &'static BaseInstruction<'static, Op>> {
133        self.0.iter()
134    }
135}
136
137include!("autogen_tables.rs");