rspirv/grammar/
syntax.rs

1use crate::spirv;
2
3/// Grammar for a SPIR-V instruction.
4#[derive(Debug, PartialEq, Eq, Hash)]
5pub struct Instruction<'a> {
6    /// Opname.
7    pub opname: &'a str,
8    /// Opcode.
9    pub opcode: spirv::Op,
10    /// Capabilities required for this instruction.
11    pub capabilities: &'a [spirv::Capability],
12    /// Extensions required for this instruction.
13    pub extensions: &'a [&'a str],
14    /// Logical operands for this instruction.
15    ///
16    /// This includes result type id and result id.
17    pub operands: &'a [LogicalOperand],
18}
19
20/// Grammar for an extended instruction.
21pub struct ExtendedInstruction<'a> {
22    /// OpName.
23    pub opname: &'a str,
24    /// Opcode.
25    pub opcode: spirv::Word,
26    /// Capabilities required for this instruction.
27    pub capabilities: &'a [spirv::Capability],
28    /// Extensions required for this instruction.
29    pub extensions: &'a [&'a str],
30    /// Logical operands for this instruction.
31    pub operands: &'a [LogicalOperand],
32}
33
34/// Grammar for a SPIR-V logical operand.
35#[derive(Debug, PartialEq, Eq, Hash, Clone)]
36pub struct LogicalOperand {
37    /// The kind of this logical operand.
38    pub kind: OperandKind,
39    /// The repeat specification for this logical operand.
40    pub quantifier: OperandQuantifier,
41}
42
43/// The repeat specification for a SPIR-V logical operand.
44#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
45pub enum OperandQuantifier {
46    /// This operand appears exactly one time.
47    One,
48    /// This operand can appear zero or one time.
49    ZeroOrOne,
50    /// This operand can appear zero or more times.
51    ZeroOrMore,
52}
53
54/// Declares the grammar for an SPIR-V instruction.
55macro_rules! inst {
56    ($op:ident, [$( $cap:ident ),*], [$( $ext:expr ),*], [$( ($kind:ident, $quant:ident) ),*]) => {
57        Instruction {
58            opname: stringify!($op),
59            opcode: spirv::Op::$op,
60            capabilities: &[
61                $( spirv::Capability::$cap ),*
62            ],
63            extensions: &[
64                $( $ext ),*
65            ],
66            operands: &[
67                $( LogicalOperand {
68                    kind: OperandKind::$kind,
69                    quantifier: OperandQuantifier::$quant }
70                ),*
71            ],
72        }
73    }
74}
75
76/// Declares the grammar for an extended instruction instruction.
77macro_rules! ext_inst {
78    ($opname:ident, $opcode: expr, [$( $cap:ident ),*], [$( $ext:expr ),*],
79     [$( ($kind:ident, $quant:ident) ),*]) => {
80        ExtendedInstruction {
81            opname: stringify!($opname),
82            opcode: $opcode,
83            capabilities: &[
84                $( spirv::Capability::$cap ),*
85            ],
86            extensions: &[
87                $( $ext ),*
88            ],
89            operands: &[
90                $( LogicalOperand {
91                    kind: OperandKind::$kind,
92                    quantifier: OperandQuantifier::$quant }
93                ),*
94            ],
95        }
96    }
97}
98
99/// The table for all SPIR-V core instructions.
100///
101/// This table is staic data stored in the library.
102pub struct CoreInstructionTable;
103
104impl CoreInstructionTable {
105    /// Looks up the given `opcode` in the instruction table and returns
106    /// a reference to the instruction grammar entry if found.
107    pub fn lookup_opcode(opcode: u16) -> Option<&'static Instruction<'static>> {
108        INSTRUCTION_TABLE
109            .iter()
110            .find(|inst| (inst.opcode as u16) == opcode)
111    }
112
113    /// Returns a reference to the instruction grammar entry with the given
114    /// `opcode`.
115    pub fn get(opcode: spirv::Op) -> &'static Instruction<'static> {
116        INSTRUCTION_TABLE
117            .iter()
118            .find(|inst| (inst.opcode == opcode))
119            .expect("internal error")
120    }
121
122    pub fn iter() -> impl Iterator<Item = &'static Instruction<'static>> {
123        INSTRUCTION_TABLE.iter()
124    }
125}
126
127include!("autogen_table.rs");
128
129/// The table for all `GLSLstd450` extended instructions.
130///
131/// This table is staic data stored in the library.
132pub struct GlslStd450InstructionTable;
133
134impl GlslStd450InstructionTable {
135    /// Looks up the given `opcode` in the instruction table and returns
136    /// a reference to the instruction grammar entry if found.
137    pub fn lookup_opcode(opcode: u32) -> Option<&'static ExtendedInstruction<'static>> {
138        GLSL_STD_450_INSTRUCTION_TABLE
139            .iter()
140            .find(|inst| inst.opcode == opcode)
141    }
142
143    /// Returns a reference to the instruction grammar entry with the given
144    /// `opcode`.
145    pub fn get(opcode: spirv::GLOp) -> &'static ExtendedInstruction<'static> {
146        GLSL_STD_450_INSTRUCTION_TABLE
147            .iter()
148            .find(|inst| (inst.opcode == opcode as spirv::Word))
149            .expect("internal error")
150    }
151
152    pub fn iter() -> impl Iterator<Item = &'static ExtendedInstruction<'static>> {
153        GLSL_STD_450_INSTRUCTION_TABLE.iter()
154    }
155}
156
157include!("autogen_glsl_std_450.rs");
158
159/// The table for all `OpenCLstd100` extended instructions.
160///
161/// This table is staic data stored in the library.
162#[allow(clippy::upper_case_acronyms)]
163pub struct OpenCLStd100InstructionTable;
164
165impl OpenCLStd100InstructionTable {
166    /// Looks up the given `opcode` in the instruction table and returns
167    /// a reference to the instruction grammar entry if found.
168    pub fn lookup_opcode(opcode: u32) -> Option<&'static ExtendedInstruction<'static>> {
169        OPENCL_STD_100_INSTRUCTION_TABLE
170            .iter()
171            .find(|inst| inst.opcode == opcode)
172    }
173
174    /// Returns a reference to the instruction grammar entry with the given
175    /// `opcode`.
176    pub fn get(opcode: spirv::CLOp) -> &'static ExtendedInstruction<'static> {
177        OPENCL_STD_100_INSTRUCTION_TABLE
178            .iter()
179            .find(|inst| (inst.opcode == opcode as spirv::Word))
180            .expect("internal error")
181    }
182
183    pub fn iter() -> impl Iterator<Item = &'static ExtendedInstruction<'static>> {
184        OPENCL_STD_100_INSTRUCTION_TABLE.iter()
185    }
186}
187
188include!("autogen_opencl_std_100.rs");