1 //! Operator definitions.
2 
3 use peepmatic_macro::PeepmaticOperator;
4 use serde::{Deserialize, Serialize};
5 
6 /// An operator.
7 ///
8 /// These are a subset of Cranelift IR's operators.
9 ///
10 /// ## Caveats for Branching and Trapping Operators
11 ///
12 /// Branching operators are not fully modeled: we do not represent their label
13 /// and jump arguments. It is up to the interpreter doing the instruction
14 /// replacement to recognize when we are replacing one branch with another, and
15 /// copy over the extra information.
16 ///
17 /// Affected operations: `brz`, `brnz`, `trapz`, `trapnz`.
18 #[derive(PeepmaticOperator, Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
19 #[repr(u32)]
20 pub enum Operator {
21     /// `adjust_sp_down`
22     #[peepmatic(params(iNN), result(void))]
23     // NB: We convert `Operator`s into `NonZeroU32`s with unchecked casts;
24     // memory safety relies on `Operator` starting at `1` and no variant ever
25     // being zero.
26     AdjustSpDown = 1,
27 
28     /// `adjust_sp_down_imm`
29     #[peepmatic(immediates(iNN), result(void))]
30     AdjustSpDownImm,
31 
32     /// `band`
33     #[peepmatic(params(iNN, iNN), result(iNN))]
34     Band,
35 
36     /// `band_imm`
37     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
38     BandImm,
39 
40     /// `bconst`
41     #[peepmatic(immediates(b1), result(bNN))]
42     Bconst,
43 
44     /// `bint`
45     #[peepmatic(params(bNN), result(iNN))]
46     Bint,
47 
48     /// `bor`
49     #[peepmatic(params(iNN, iNN), result(iNN))]
50     Bor,
51 
52     /// `bor_imm`
53     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
54     BorImm,
55 
56     /// `brnz`
57     #[peepmatic(params(bool_or_int), result(void))]
58     Brnz,
59 
60     /// `brz`
61     #[peepmatic(params(bool_or_int), result(void))]
62     Brz,
63 
64     /// `bxor`
65     #[peepmatic(params(iNN, iNN), result(iNN))]
66     Bxor,
67 
68     /// `bxor_imm`
69     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
70     BxorImm,
71 
72     /// `iadd`
73     #[peepmatic(params(iNN, iNN), result(iNN))]
74     Iadd,
75 
76     /// `iadd_imm`
77     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
78     IaddImm,
79 
80     /// `icmp`
81     #[peepmatic(immediates(cc), params(iNN, iNN), result(b1))]
82     Icmp,
83 
84     /// `icmp_imm`
85     #[peepmatic(immediates(cc, iNN), params(iNN), result(b1))]
86     IcmpImm,
87 
88     /// `iconst`
89     #[peepmatic(immediates(iNN), result(iNN))]
90     Iconst,
91 
92     /// `ifcmp`
93     #[peepmatic(params(iNN, iNN), result(cpu_flags))]
94     Ifcmp,
95 
96     /// `ifcmp_imm`
97     #[peepmatic(immediates(iNN), params(iNN), result(cpu_flags))]
98     IfcmpImm,
99 
100     /// `imul`
101     #[peepmatic(params(iNN, iNN), result(iNN))]
102     Imul,
103 
104     /// `imul_imm`
105     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
106     ImulImm,
107 
108     /// `ireduce`
109     #[peepmatic(params(iNN), result(iMM))]
110     Ireduce,
111 
112     /// `irsub_imm`
113     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
114     IrsubImm,
115 
116     /// `ishl`
117     #[peepmatic(params(iNN, iNN), result(iNN))]
118     Ishl,
119 
120     /// `ishl_imm`
121     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
122     IshlImm,
123 
124     /// `isub`
125     #[peepmatic(params(iNN, iNN), result(iNN))]
126     Isub,
127 
128     /// `rotl`
129     #[peepmatic(params(iNN, iNN), result(iNN))]
130     Rotl,
131 
132     /// `rotl_imm`
133     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
134     RotlImm,
135 
136     /// `rotr`
137     #[peepmatic(params(iNN, iNN), result(iNN))]
138     Rotr,
139 
140     /// `rotr_imm`
141     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
142     RotrImm,
143 
144     /// `sdiv`
145     #[peepmatic(params(iNN, iNN), result(iNN))]
146     Sdiv,
147 
148     /// `sdiv_imm`
149     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
150     SdivImm,
151 
152     /// `select`
153     #[peepmatic(params(bool_or_int, any_t, any_t), result(any_t))]
154     Select,
155 
156     /// `sextend`
157     #[peepmatic(params(iNN), result(iMM))]
158     Sextend,
159 
160     /// `srem`
161     #[peepmatic(params(iNN, iNN), result(iNN))]
162     Srem,
163 
164     /// `srem_imm`
165     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
166     SremImm,
167 
168     /// `sshr`
169     #[peepmatic(params(iNN, iNN), result(iNN))]
170     Sshr,
171 
172     /// `sshr_imm`
173     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
174     SshrImm,
175 
176     /// `trapnz`
177     #[peepmatic(params(bool_or_int), result(void))]
178     Trapnz,
179 
180     /// `trapz`
181     #[peepmatic(params(bool_or_int), result(void))]
182     Trapz,
183 
184     /// `udiv`
185     #[peepmatic(params(iNN, iNN), result(iNN))]
186     Udiv,
187 
188     /// `udiv_imm`
189     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
190     UdivImm,
191 
192     /// `uextend`
193     #[peepmatic(params(iNN), result(iMM))]
194     Uextend,
195 
196     /// `urem`
197     #[peepmatic(params(iNN, iNN), result(iNN))]
198     Urem,
199 
200     /// `urem_imm`
201     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
202     UremImm,
203 
204     /// `ushr`
205     #[peepmatic(params(iNN, iNN), result(iNN))]
206     Ushr,
207 
208     /// `ushr_imm`
209     #[peepmatic(immediates(iNN), params(iNN), result(iNN))]
210     UshrImm,
211 }
212 
213 /// Compile-time unquote operators.
214 ///
215 /// These are used in the right-hand side to perform compile-time evaluation of
216 /// constants matched on the left-hand side.
217 #[derive(PeepmaticOperator, Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
218 #[repr(u32)]
219 pub enum UnquoteOperator {
220     /// Compile-time `band` of two constant values.
221     #[peepmatic(params(iNN, iNN), result(iNN))]
222     Band,
223 
224     /// Compile-time `bor` of two constant values.
225     #[peepmatic(params(iNN, iNN), result(iNN))]
226     Bor,
227 
228     /// Compile-time `bxor` of two constant values.
229     #[peepmatic(params(iNN, iNN), result(iNN))]
230     Bxor,
231 
232     /// Compile-time `iadd` of two constant values.
233     #[peepmatic(params(iNN, iNN), result(iNN))]
234     Iadd,
235 
236     /// Compile-time `imul` of two constant values.
237     #[peepmatic(params(iNN, iNN), result(iNN))]
238     Imul,
239 
240     /// Take the base-2 log of a power of two integer.
241     #[peepmatic(params(iNN), result(iNN))]
242     Log2,
243 
244     /// Wrapping negation of an integer.
245     #[peepmatic(params(iNN), result(iNN))]
246     Neg,
247 }
248 
249 /// A trait to represent a typing context.
250 ///
251 /// This is used by the macro-generated operator methods that create the type
252 /// variables for their immediates, parameters, and results. This trait is
253 /// implemented by the concrete typing context in `peepmatic/src/verify.rs`.
254 #[cfg(feature = "construct")]
255 pub trait TypingContext<'a> {
256     /// A type variable.
257     type TypeVariable;
258 
259     /// Create a condition code type.
cc(&mut self, span: wast::Span) -> Self::TypeVariable260     fn cc(&mut self, span: wast::Span) -> Self::TypeVariable;
261 
262     /// Create a boolean type with a polymorphic bit width.
263     ///
264     /// Each use of `bNN` by the same operator refers to the same type variable.
265     #[allow(non_snake_case)]
bNN(&mut self, span: wast::Span) -> Self::TypeVariable266     fn bNN(&mut self, span: wast::Span) -> Self::TypeVariable;
267 
268     /// Create an integer type with a polymorphic bit width.
269     ///
270     /// Each use of `iNN` by the same operator refers to the same type variable.
271     #[allow(non_snake_case)]
iNN(&mut self, span: wast::Span) -> Self::TypeVariable272     fn iNN(&mut self, span: wast::Span) -> Self::TypeVariable;
273 
274     /// Create an integer type with a polymorphic bit width.
275     ///
276     /// Each use of `iMM` by the same operator refers to the same type variable.
277     #[allow(non_snake_case)]
iMM(&mut self, span: wast::Span) -> Self::TypeVariable278     fn iMM(&mut self, span: wast::Span) -> Self::TypeVariable;
279 
280     /// Create the CPU flags type variable.
cpu_flags(&mut self, span: wast::Span) -> Self::TypeVariable281     fn cpu_flags(&mut self, span: wast::Span) -> Self::TypeVariable;
282 
283     /// Create a boolean type of size one bit.
b1(&mut self, span: wast::Span) -> Self::TypeVariable284     fn b1(&mut self, span: wast::Span) -> Self::TypeVariable;
285 
286     /// Create the void type, used as the result of operators that branch away,
287     /// or do not return anything.
void(&mut self, span: wast::Span) -> Self::TypeVariable288     fn void(&mut self, span: wast::Span) -> Self::TypeVariable;
289 
290     /// Create a type variable that may be either a boolean or an integer.
bool_or_int(&mut self, span: wast::Span) -> Self::TypeVariable291     fn bool_or_int(&mut self, span: wast::Span) -> Self::TypeVariable;
292 
293     /// Create a type variable that can be any type T.
294     ///
295     /// Each use of `any_t` by the same operator refers to the same type
296     /// variable.
any_t(&mut self, span: wast::Span) -> Self::TypeVariable297     fn any_t(&mut self, span: wast::Span) -> Self::TypeVariable;
298 }
299