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