1use crate::abi::RetArea;
8use crate::codegen::{
9 Callee, CodeGen, CodeGenError, ConditionalBranch, ControlStackFrame, Emission, FnCall,
10 UnconditionalBranch, control_index,
11};
12use crate::masm::{
13 AtomicWaitKind, DivKind, Extend, ExtractLaneKind, FloatCmpKind, IntCmpKind, LoadKind,
14 MacroAssembler, MulWideKind, OperandSize, RegImm, RemKind, ReplaceLaneKind, RmwOp,
15 RoundingMode, SPOffset, ShiftKind, Signed, SplatKind, SplatLoadKind, StoreKind, TruncKind,
16 V128AbsKind, V128AddKind, V128ConvertKind, V128ExtAddKind, V128ExtMulKind, V128ExtendKind,
17 V128LoadExtendKind, V128MaxKind, V128MinKind, V128MulKind, V128NarrowKind, V128NegKind,
18 V128SubKind, V128TruncKind, VectorCompareKind, VectorEqualityKind, Zero,
19};
20use crate::reg::{Reg, writable};
21use crate::stack::{TypedReg, Val};
22use crate::{Result, bail, ensure, format_err};
23use regalloc2::RegClass;
24use smallvec::{SmallVec, smallvec};
25use wasmparser::{
26 BlockType, BrTable, Ieee32, Ieee64, MemArg, V128, VisitOperator, VisitSimdOperator,
27};
28use wasmtime_cranelift::TRAP_INDIRECT_CALL_TO_NULL;
29use wasmtime_environ::{
30 FUNCREF_INIT_BIT, FuncIndex, GlobalIndex, MemoryIndex, TableIndex, TypeIndex, WasmHeapType,
31 WasmValType,
32};
33
34macro_rules! def_unsupported {
41 ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident $ann:tt)*) => {
42 $(
43 def_unsupported!(
44 emit
45 $op
46
47 fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output {
48 $($(let _ = $arg;)*)?
49
50 Err(format_err!(CodeGenError::unimplemented_wasm_instruction()))
51 }
52 );
53 )*
54 };
55
56 (emit I32Const $($rest:tt)*) => {};
57 (emit I64Const $($rest:tt)*) => {};
58 (emit F32Const $($rest:tt)*) => {};
59 (emit F64Const $($rest:tt)*) => {};
60 (emit V128Const $($rest:tt)*) => {};
61 (emit F32Add $($rest:tt)*) => {};
62 (emit F64Add $($rest:tt)*) => {};
63 (emit F32Sub $($rest:tt)*) => {};
64 (emit F64Sub $($rest:tt)*) => {};
65 (emit F32Mul $($rest:tt)*) => {};
66 (emit F64Mul $($rest:tt)*) => {};
67 (emit F32Div $($rest:tt)*) => {};
68 (emit F64Div $($rest:tt)*) => {};
69 (emit F32Min $($rest:tt)*) => {};
70 (emit F64Min $($rest:tt)*) => {};
71 (emit F32Max $($rest:tt)*) => {};
72 (emit F64Max $($rest:tt)*) => {};
73 (emit F32Copysign $($rest:tt)*) => {};
74 (emit F64Copysign $($rest:tt)*) => {};
75 (emit F32Abs $($rest:tt)*) => {};
76 (emit F64Abs $($rest:tt)*) => {};
77 (emit F32Neg $($rest:tt)*) => {};
78 (emit F64Neg $($rest:tt)*) => {};
79 (emit F32Floor $($rest:tt)*) => {};
80 (emit F64Floor $($rest:tt)*) => {};
81 (emit F32Ceil $($rest:tt)*) => {};
82 (emit F64Ceil $($rest:tt)*) => {};
83 (emit F32Nearest $($rest:tt)*) => {};
84 (emit F64Nearest $($rest:tt)*) => {};
85 (emit F32Trunc $($rest:tt)*) => {};
86 (emit F64Trunc $($rest:tt)*) => {};
87 (emit F32Sqrt $($rest:tt)*) => {};
88 (emit F64Sqrt $($rest:tt)*) => {};
89 (emit F32Eq $($rest:tt)*) => {};
90 (emit F64Eq $($rest:tt)*) => {};
91 (emit F32Ne $($rest:tt)*) => {};
92 (emit F64Ne $($rest:tt)*) => {};
93 (emit F32Lt $($rest:tt)*) => {};
94 (emit F64Lt $($rest:tt)*) => {};
95 (emit F32Gt $($rest:tt)*) => {};
96 (emit F64Gt $($rest:tt)*) => {};
97 (emit F32Le $($rest:tt)*) => {};
98 (emit F64Le $($rest:tt)*) => {};
99 (emit F32Ge $($rest:tt)*) => {};
100 (emit F64Ge $($rest:tt)*) => {};
101 (emit F32ConvertI32S $($rest:tt)*) => {};
102 (emit F32ConvertI32U $($rest:tt)*) => {};
103 (emit F32ConvertI64S $($rest:tt)*) => {};
104 (emit F32ConvertI64U $($rest:tt)*) => {};
105 (emit F64ConvertI32S $($rest:tt)*) => {};
106 (emit F64ConvertI32U $($rest:tt)*) => {};
107 (emit F64ConvertI64S $($rest:tt)*) => {};
108 (emit F64ConvertI64U $($rest:tt)*) => {};
109 (emit F32ReinterpretI32 $($rest:tt)*) => {};
110 (emit F64ReinterpretI64 $($rest:tt)*) => {};
111 (emit F32DemoteF64 $($rest:tt)*) => {};
112 (emit F64PromoteF32 $($rest:tt)*) => {};
113 (emit I32Add $($rest:tt)*) => {};
114 (emit I64Add $($rest:tt)*) => {};
115 (emit I32Sub $($rest:tt)*) => {};
116 (emit I32Mul $($rest:tt)*) => {};
117 (emit I32DivS $($rest:tt)*) => {};
118 (emit I32DivU $($rest:tt)*) => {};
119 (emit I64DivS $($rest:tt)*) => {};
120 (emit I64DivU $($rest:tt)*) => {};
121 (emit I64RemU $($rest:tt)*) => {};
122 (emit I64RemS $($rest:tt)*) => {};
123 (emit I32RemU $($rest:tt)*) => {};
124 (emit I32RemS $($rest:tt)*) => {};
125 (emit I64Mul $($rest:tt)*) => {};
126 (emit I64Sub $($rest:tt)*) => {};
127 (emit I32Eq $($rest:tt)*) => {};
128 (emit I64Eq $($rest:tt)*) => {};
129 (emit I32Ne $($rest:tt)*) => {};
130 (emit I64Ne $($rest:tt)*) => {};
131 (emit I32LtS $($rest:tt)*) => {};
132 (emit I64LtS $($rest:tt)*) => {};
133 (emit I32LtU $($rest:tt)*) => {};
134 (emit I64LtU $($rest:tt)*) => {};
135 (emit I32LeS $($rest:tt)*) => {};
136 (emit I64LeS $($rest:tt)*) => {};
137 (emit I32LeU $($rest:tt)*) => {};
138 (emit I64LeU $($rest:tt)*) => {};
139 (emit I32GtS $($rest:tt)*) => {};
140 (emit I64GtS $($rest:tt)*) => {};
141 (emit I32GtU $($rest:tt)*) => {};
142 (emit I64GtU $($rest:tt)*) => {};
143 (emit I32GeS $($rest:tt)*) => {};
144 (emit I64GeS $($rest:tt)*) => {};
145 (emit I32GeU $($rest:tt)*) => {};
146 (emit I64GeU $($rest:tt)*) => {};
147 (emit I32Eqz $($rest:tt)*) => {};
148 (emit I64Eqz $($rest:tt)*) => {};
149 (emit I32And $($rest:tt)*) => {};
150 (emit I64And $($rest:tt)*) => {};
151 (emit I32Or $($rest:tt)*) => {};
152 (emit I64Or $($rest:tt)*) => {};
153 (emit I32Xor $($rest:tt)*) => {};
154 (emit I64Xor $($rest:tt)*) => {};
155 (emit I32Shl $($rest:tt)*) => {};
156 (emit I64Shl $($rest:tt)*) => {};
157 (emit I32ShrS $($rest:tt)*) => {};
158 (emit I64ShrS $($rest:tt)*) => {};
159 (emit I32ShrU $($rest:tt)*) => {};
160 (emit I64ShrU $($rest:tt)*) => {};
161 (emit I32Rotl $($rest:tt)*) => {};
162 (emit I64Rotl $($rest:tt)*) => {};
163 (emit I32Rotr $($rest:tt)*) => {};
164 (emit I64Rotr $($rest:tt)*) => {};
165 (emit I32Clz $($rest:tt)*) => {};
166 (emit I64Clz $($rest:tt)*) => {};
167 (emit I32Ctz $($rest:tt)*) => {};
168 (emit I64Ctz $($rest:tt)*) => {};
169 (emit I32Popcnt $($rest:tt)*) => {};
170 (emit I64Popcnt $($rest:tt)*) => {};
171 (emit I32WrapI64 $($rest:tt)*) => {};
172 (emit I64ExtendI32S $($rest:tt)*) => {};
173 (emit I64ExtendI32U $($rest:tt)*) => {};
174 (emit I32Extend8S $($rest:tt)*) => {};
175 (emit I32Extend16S $($rest:tt)*) => {};
176 (emit I64Extend8S $($rest:tt)*) => {};
177 (emit I64Extend16S $($rest:tt)*) => {};
178 (emit I64Extend32S $($rest:tt)*) => {};
179 (emit I32TruncF32S $($rest:tt)*) => {};
180 (emit I32TruncF32U $($rest:tt)*) => {};
181 (emit I32TruncF64S $($rest:tt)*) => {};
182 (emit I32TruncF64U $($rest:tt)*) => {};
183 (emit I64TruncF32S $($rest:tt)*) => {};
184 (emit I64TruncF32U $($rest:tt)*) => {};
185 (emit I64TruncF64S $($rest:tt)*) => {};
186 (emit I64TruncF64U $($rest:tt)*) => {};
187 (emit I32ReinterpretF32 $($rest:tt)*) => {};
188 (emit I64ReinterpretF64 $($rest:tt)*) => {};
189 (emit LocalGet $($rest:tt)*) => {};
190 (emit LocalSet $($rest:tt)*) => {};
191 (emit Call $($rest:tt)*) => {};
192 (emit End $($rest:tt)*) => {};
193 (emit Nop $($rest:tt)*) => {};
194 (emit If $($rest:tt)*) => {};
195 (emit Else $($rest:tt)*) => {};
196 (emit Block $($rest:tt)*) => {};
197 (emit Loop $($rest:tt)*) => {};
198 (emit Br $($rest:tt)*) => {};
199 (emit BrIf $($rest:tt)*) => {};
200 (emit Return $($rest:tt)*) => {};
201 (emit Unreachable $($rest:tt)*) => {};
202 (emit LocalTee $($rest:tt)*) => {};
203 (emit GlobalGet $($rest:tt)*) => {};
204 (emit GlobalSet $($rest:tt)*) => {};
205 (emit Select $($rest:tt)*) => {};
206 (emit Drop $($rest:tt)*) => {};
207 (emit BrTable $($rest:tt)*) => {};
208 (emit CallIndirect $($rest:tt)*) => {};
209 (emit TableInit $($rest:tt)*) => {};
210 (emit TableCopy $($rest:tt)*) => {};
211 (emit TableGet $($rest:tt)*) => {};
212 (emit TableSet $($rest:tt)*) => {};
213 (emit TableGrow $($rest:tt)*) => {};
214 (emit TableSize $($rest:tt)*) => {};
215 (emit TableFill $($rest:tt)*) => {};
216 (emit ElemDrop $($rest:tt)*) => {};
217 (emit MemoryInit $($rest:tt)*) => {};
218 (emit MemoryCopy $($rest:tt)*) => {};
219 (emit DataDrop $($rest:tt)*) => {};
220 (emit MemoryFill $($rest:tt)*) => {};
221 (emit MemorySize $($rest:tt)*) => {};
222 (emit MemoryGrow $($rest:tt)*) => {};
223 (emit I32Load $($rest:tt)*) => {};
224 (emit I32Load8S $($rest:tt)*) => {};
225 (emit I32Load8U $($rest:tt)*) => {};
226 (emit I32Load16S $($rest:tt)*) => {};
227 (emit I32Load16U $($rest:tt)*) => {};
228 (emit I64Load8S $($rest:tt)*) => {};
229 (emit I64Load8U $($rest:tt)*) => {};
230 (emit I64Load16S $($rest:tt)*) => {};
231 (emit I64Load16U $($rest:tt)*) => {};
232 (emit I64Load32S $($rest:tt)*) => {};
233 (emit I64Load32U $($rest:tt)*) => {};
234 (emit I64Load $($rest:tt)*) => {};
235 (emit I32Store $($rest:tt)*) => {};
236 (emit I32Store8 $($rest:tt)*) => {};
237 (emit I32Store16 $($rest:tt)*) => {};
238 (emit I64Store $($rest:tt)*) => {};
239 (emit I64Store8 $($rest:tt)*) => {};
240 (emit I64Store16 $($rest:tt)*) => {};
241 (emit I64Store32 $($rest:tt)*) => {};
242 (emit F32Load $($rest:tt)*) => {};
243 (emit F32Store $($rest:tt)*) => {};
244 (emit F64Load $($rest:tt)*) => {};
245 (emit F64Store $($rest:tt)*) => {};
246 (emit I32TruncSatF32S $($rest:tt)*) => {};
247 (emit I32TruncSatF32U $($rest:tt)*) => {};
248 (emit I32TruncSatF64S $($rest:tt)*) => {};
249 (emit I32TruncSatF64U $($rest:tt)*) => {};
250 (emit I64TruncSatF32S $($rest:tt)*) => {};
251 (emit I64TruncSatF32U $($rest:tt)*) => {};
252 (emit I64TruncSatF64S $($rest:tt)*) => {};
253 (emit I64TruncSatF64U $($rest:tt)*) => {};
254 (emit V128Load $($rest:tt)*) => {};
255 (emit V128Store $($rest:tt)*) => {};
256 (emit I64Add128 $($rest:tt)*) => {};
257 (emit I64Sub128 $($rest:tt)*) => {};
258 (emit I64MulWideS $($rest:tt)*) => {};
259 (emit I64MulWideU $($rest:tt)*) => {};
260 (emit I32AtomicLoad8U $($rest:tt)*) => {};
261 (emit I32AtomicLoad16U $($rest:tt)*) => {};
262 (emit I32AtomicLoad $($rest:tt)*) => {};
263 (emit I64AtomicLoad8U $($rest:tt)*) => {};
264 (emit I64AtomicLoad16U $($rest:tt)*) => {};
265 (emit I64AtomicLoad32U $($rest:tt)*) => {};
266 (emit I64AtomicLoad $($rest:tt)*) => {};
267 (emit V128Load8x8S $($rest:tt)*) => {};
268 (emit V128Load8x8U $($rest:tt)*) => {};
269 (emit V128Load16x4S $($rest:tt)*) => {};
270 (emit V128Load16x4U $($rest:tt)*) => {};
271 (emit V128Load32x2S $($rest:tt)*) => {};
272 (emit V128Load32x2U $($rest:tt)*) => {};
273 (emit V128Load8Splat $($rest:tt)*) => {};
274 (emit V128Load16Splat $($rest:tt)*) => {};
275 (emit V128Load32Splat $($rest:tt)*) => {};
276 (emit V128Load64Splat $($rest:tt)*) => {};
277 (emit I8x16Splat $($rest:tt)*) => {};
278 (emit I16x8Splat $($rest:tt)*) => {};
279 (emit I32x4Splat $($rest:tt)*) => {};
280 (emit I64x2Splat $($rest:tt)*) => {};
281 (emit F32x4Splat $($rest:tt)*) => {};
282 (emit F64x2Splat $($rest:tt)*) => {};
283 (emit I32AtomicStore8 $($rest:tt)*) => {};
284 (emit I32AtomicStore16 $($rest:tt)*) => {};
285 (emit I32AtomicStore $($rest:tt)*) => {};
286 (emit I64AtomicStore8 $($rest:tt)*) => {};
287 (emit I64AtomicStore16 $($rest:tt)*) => {};
288 (emit I64AtomicStore32 $($rest:tt)*) => {};
289 (emit I64AtomicStore $($rest:tt)*) => {};
290 (emit I32AtomicRmw8AddU $($rest:tt)*) => {};
291 (emit I32AtomicRmw16AddU $($rest:tt)*) => {};
292 (emit I32AtomicRmwAdd $($rest:tt)*) => {};
293 (emit I64AtomicRmw8AddU $($rest:tt)*) => {};
294 (emit I64AtomicRmw16AddU $($rest:tt)*) => {};
295 (emit I64AtomicRmw32AddU $($rest:tt)*) => {};
296 (emit I64AtomicRmwAdd $($rest:tt)*) => {};
297 (emit I8x16Shuffle $($rest:tt)*) => {};
298 (emit I8x16Swizzle $($rest:tt)*) => {};
299 (emit I32AtomicRmw8SubU $($rest:tt)*) => {};
300 (emit I32AtomicRmw16SubU $($rest:tt)*) => {};
301 (emit I32AtomicRmwSub $($rest:tt)*) => {};
302 (emit I64AtomicRmw8SubU $($rest:tt)*) => {};
303 (emit I64AtomicRmw16SubU $($rest:tt)*) => {};
304 (emit I64AtomicRmw32SubU $($rest:tt)*) => {};
305 (emit I64AtomicRmwSub $($rest:tt)*) => {};
306 (emit I32AtomicRmw8XchgU $($rest:tt)*) => {};
307 (emit I32AtomicRmw16XchgU $($rest:tt)*) => {};
308 (emit I32AtomicRmwXchg $($rest:tt)*) => {};
309 (emit I64AtomicRmw8XchgU $($rest:tt)*) => {};
310 (emit I64AtomicRmw16XchgU $($rest:tt)*) => {};
311 (emit I64AtomicRmw32XchgU $($rest:tt)*) => {};
312 (emit I64AtomicRmwXchg $($rest:tt)*) => {};
313 (emit I8x16ExtractLaneS $($rest:tt)*) => {};
314 (emit I8x16ExtractLaneU $($rest:tt)*) => {};
315 (emit I16x8ExtractLaneS $($rest:tt)*) => {};
316 (emit I16x8ExtractLaneU $($rest:tt)*) => {};
317 (emit I32x4ExtractLane $($rest:tt)*) => {};
318 (emit I64x2ExtractLane $($rest:tt)*) => {};
319 (emit F32x4ExtractLane $($rest:tt)*) => {};
320 (emit F64x2ExtractLane $($rest:tt)*) => {};
321 (emit I32AtomicRmw8AndU $($rest:tt)*) => {};
322 (emit I32AtomicRmw16AndU $($rest:tt)*) => {};
323 (emit I32AtomicRmwAnd $($rest:tt)*) => {};
324 (emit I64AtomicRmw8AndU $($rest:tt)*) => {};
325 (emit I64AtomicRmw16AndU $($rest:tt)*) => {};
326 (emit I64AtomicRmw32AndU $($rest:tt)*) => {};
327 (emit I64AtomicRmwAnd $($rest:tt)*) => {};
328 (emit I32AtomicRmw8OrU $($rest:tt)*) => {};
329 (emit I32AtomicRmw16OrU $($rest:tt)*) => {};
330 (emit I32AtomicRmwOr $($rest:tt)*) => {};
331 (emit I64AtomicRmw8OrU $($rest:tt)*) => {};
332 (emit I64AtomicRmw16OrU $($rest:tt)*) => {};
333 (emit I64AtomicRmw32OrU $($rest:tt)*) => {};
334 (emit I64AtomicRmwOr $($rest:tt)*) => {};
335 (emit I32AtomicRmw8XorU $($rest:tt)*) => {};
336 (emit I32AtomicRmw16XorU $($rest:tt)*) => {};
337 (emit I32AtomicRmwXor $($rest:tt)*) => {};
338 (emit I64AtomicRmw8XorU $($rest:tt)*) => {};
339 (emit I64AtomicRmw16XorU $($rest:tt)*) => {};
340 (emit I64AtomicRmw32XorU $($rest:tt)*) => {};
341 (emit I64AtomicRmwXor $($rest:tt)*) => {};
342 (emit I8x16ReplaceLane $($rest:tt)*) => {};
343 (emit I16x8ReplaceLane $($rest:tt)*) => {};
344 (emit I32x4ReplaceLane $($rest:tt)*) => {};
345 (emit I64x2ReplaceLane $($rest:tt)*) => {};
346 (emit F32x4ReplaceLane $($rest:tt)*) => {};
347 (emit F64x2ReplaceLane $($rest:tt)*) => {};
348 (emit I32AtomicRmw8CmpxchgU $($rest:tt)*) => {};
349 (emit I32AtomicRmw16CmpxchgU $($rest:tt)*) => {};
350 (emit I32AtomicRmwCmpxchg $($rest:tt)*) => {};
351 (emit I64AtomicRmw8CmpxchgU $($rest:tt)*) => {};
352 (emit I64AtomicRmw16CmpxchgU $($rest:tt)*) => {};
353 (emit I64AtomicRmw32CmpxchgU $($rest:tt)*) => {};
354 (emit I64AtomicRmwCmpxchg $($rest:tt)*) => {};
355 (emit I8x16Eq $($rest:tt)*) => {};
356 (emit I16x8Eq $($rest:tt)*) => {};
357 (emit I32x4Eq $($rest:tt)*) => {};
358 (emit I64x2Eq $($rest:tt)*) => {};
359 (emit F32x4Eq $($rest:tt)*) => {};
360 (emit F64x2Eq $($rest:tt)*) => {};
361 (emit I8x16Ne $($rest:tt)*) => {};
362 (emit I16x8Ne $($rest:tt)*) => {};
363 (emit I32x4Ne $($rest:tt)*) => {};
364 (emit I64x2Ne $($rest:tt)*) => {};
365 (emit F32x4Ne $($rest:tt)*) => {};
366 (emit F64x2Ne $($rest:tt)*) => {};
367 (emit I8x16LtS $($rest:tt)*) => {};
368 (emit I8x16LtU $($rest:tt)*) => {};
369 (emit I16x8LtS $($rest:tt)*) => {};
370 (emit I16x8LtU $($rest:tt)*) => {};
371 (emit I32x4LtS $($rest:tt)*) => {};
372 (emit I32x4LtU $($rest:tt)*) => {};
373 (emit I64x2LtS $($rest:tt)*) => {};
374 (emit F32x4Lt $($rest:tt)*) => {};
375 (emit F64x2Lt $($rest:tt)*) => {};
376 (emit I8x16LeS $($rest:tt)*) => {};
377 (emit I8x16LeU $($rest:tt)*) => {};
378 (emit I16x8LeS $($rest:tt)*) => {};
379 (emit I16x8LeU $($rest:tt)*) => {};
380 (emit I32x4LeS $($rest:tt)*) => {};
381 (emit I32x4LeU $($rest:tt)*) => {};
382 (emit I64x2LeS $($rest:tt)*) => {};
383 (emit F32x4Le $($rest:tt)*) => {};
384 (emit F64x2Le $($rest:tt)*) => {};
385 (emit I8x16GtS $($rest:tt)*) => {};
386 (emit I8x16GtU $($rest:tt)*) => {};
387 (emit I16x8GtS $($rest:tt)*) => {};
388 (emit I16x8GtU $($rest:tt)*) => {};
389 (emit I32x4GtS $($rest:tt)*) => {};
390 (emit I32x4GtU $($rest:tt)*) => {};
391 (emit I64x2GtS $($rest:tt)*) => {};
392 (emit F32x4Gt $($rest:tt)*) => {};
393 (emit F64x2Gt $($rest:tt)*) => {};
394 (emit I8x16GeS $($rest:tt)*) => {};
395 (emit I8x16GeU $($rest:tt)*) => {};
396 (emit I16x8GeS $($rest:tt)*) => {};
397 (emit I16x8GeU $($rest:tt)*) => {};
398 (emit I32x4GeS $($rest:tt)*) => {};
399 (emit I32x4GeU $($rest:tt)*) => {};
400 (emit I64x2GeS $($rest:tt)*) => {};
401 (emit F32x4Ge $($rest:tt)*) => {};
402 (emit F64x2Ge $($rest:tt)*) => {};
403 (emit MemoryAtomicWait32 $($rest:tt)*) => {};
404 (emit MemoryAtomicWait64 $($rest:tt)*) => {};
405 (emit MemoryAtomicNotify $($rest:tt)*) => {};
406 (emit AtomicFence $($rest:tt)*) => {};
407 (emit V128Not $($rest:tt)*) => {};
408 (emit V128And $($rest:tt)*) => {};
409 (emit V128AndNot $($rest:tt)*) => {};
410 (emit V128Or $($rest:tt)*) => {};
411 (emit V128Xor $($rest:tt)*) => {};
412 (emit V128Bitselect $($rest:tt)*) => {};
413 (emit V128AnyTrue $($rest:tt)*) => {};
414 (emit V128Load8Lane $($rest:tt)*) => {};
415 (emit V128Load16Lane $($rest:tt)*) => {};
416 (emit V128Load32Lane $($rest:tt)*) => {};
417 (emit V128Load64Lane $($rest:tt)*) => {};
418 (emit V128Store8Lane $($rest:tt)*) => {};
419 (emit V128Store16Lane $($rest:tt)*) => {};
420 (emit V128Store32Lane $($rest:tt)*) => {};
421 (emit V128Store64Lane $($rest:tt)*) => {};
422 (emit F32x4ConvertI32x4S $($rest:tt)*) => {};
423 (emit F32x4ConvertI32x4U $($rest:tt)*) => {};
424 (emit F64x2ConvertLowI32x4S $($rest:tt)*) => {};
425 (emit F64x2ConvertLowI32x4U $($rest:tt)*) => {};
426 (emit I8x16NarrowI16x8S $($rest:tt)*) => {};
427 (emit I8x16NarrowI16x8U $($rest:tt)*) => {};
428 (emit I16x8NarrowI32x4S $($rest:tt)*) => {};
429 (emit I16x8NarrowI32x4U $($rest:tt)*) => {};
430 (emit F32x4DemoteF64x2Zero $($rest:tt)*) => {};
431 (emit F64x2PromoteLowF32x4 $($rest:tt)*) => {};
432 (emit I16x8ExtendLowI8x16S $($rest:tt)*) => {};
433 (emit I16x8ExtendHighI8x16S $($rest:tt)*) => {};
434 (emit I16x8ExtendLowI8x16U $($rest:tt)*) => {};
435 (emit I16x8ExtendHighI8x16U $($rest:tt)*) => {};
436 (emit I32x4ExtendLowI16x8S $($rest:tt)*) => {};
437 (emit I32x4ExtendHighI16x8S $($rest:tt)*) => {};
438 (emit I32x4ExtendLowI16x8U $($rest:tt)*) => {};
439 (emit I32x4ExtendHighI16x8U $($rest:tt)*) => {};
440 (emit I64x2ExtendLowI32x4S $($rest:tt)*) => {};
441 (emit I64x2ExtendHighI32x4S $($rest:tt)*) => {};
442 (emit I64x2ExtendLowI32x4U $($rest:tt)*) => {};
443 (emit I64x2ExtendHighI32x4U $($rest:tt)*) => {};
444 (emit I8x16Add $($rest:tt)*) => {};
445 (emit I16x8Add $($rest:tt)*) => {};
446 (emit I32x4Add $($rest:tt)*) => {};
447 (emit I64x2Add $($rest:tt)*) => {};
448 (emit I8x16Sub $($rest:tt)*) => {};
449 (emit I16x8Sub $($rest:tt)*) => {};
450 (emit I32x4Sub $($rest:tt)*) => {};
451 (emit I64x2Sub $($rest:tt)*) => {};
452 (emit I16x8Mul $($rest:tt)*) => {};
453 (emit I32x4Mul $($rest:tt)*) => {};
454 (emit I64x2Mul $($rest:tt)*) => {};
455 (emit I8x16AddSatS $($rest:tt)*) => {};
456 (emit I16x8AddSatS $($rest:tt)*) => {};
457 (emit I8x16AddSatU $($rest:tt)*) => {};
458 (emit I16x8AddSatU $($rest:tt)*) => {};
459 (emit I8x16SubSatS $($rest:tt)*) => {};
460 (emit I16x8SubSatS $($rest:tt)*) => {};
461 (emit I8x16SubSatU $($rest:tt)*) => {};
462 (emit I16x8SubSatU $($rest:tt)*) => {};
463 (emit I8x16Abs $($rest:tt)*) => {};
464 (emit I16x8Abs $($rest:tt)*) => {};
465 (emit I32x4Abs $($rest:tt)*) => {};
466 (emit I64x2Abs $($rest:tt)*) => {};
467 (emit F32x4Abs $($rest:tt)*) => {};
468 (emit F64x2Abs $($rest:tt)*) => {};
469 (emit I8x16Neg $($rest:tt)*) => {};
470 (emit I16x8Neg $($rest:tt)*) => {};
471 (emit I32x4Neg $($rest:tt)*) => {};
472 (emit I64x2Neg $($rest:tt)*) => {};
473 (emit I8x16Shl $($rest:tt)*) => {};
474 (emit I16x8Shl $($rest:tt)*) => {};
475 (emit I32x4Shl $($rest:tt)*) => {};
476 (emit I64x2Shl $($rest:tt)*) => {};
477 (emit I8x16ShrU $($rest:tt)*) => {};
478 (emit I16x8ShrU $($rest:tt)*) => {};
479 (emit I32x4ShrU $($rest:tt)*) => {};
480 (emit I64x2ShrU $($rest:tt)*) => {};
481 (emit I8x16ShrS $($rest:tt)*) => {};
482 (emit I16x8ShrS $($rest:tt)*) => {};
483 (emit I32x4ShrS $($rest:tt)*) => {};
484 (emit I64x2ShrS $($rest:tt)*) => {};
485 (emit I16x8Q15MulrSatS $($rest:tt)*) => {};
486 (emit I8x16AllTrue $($rest:tt)*) => {};
487 (emit I16x8AllTrue $($rest:tt)*) => {};
488 (emit I32x4AllTrue $($rest:tt)*) => {};
489 (emit I64x2AllTrue $($rest:tt)*) => {};
490 (emit I8x16Bitmask $($rest:tt)*) => {};
491 (emit I16x8Bitmask $($rest:tt)*) => {};
492 (emit I32x4Bitmask $($rest:tt)*) => {};
493 (emit I64x2Bitmask $($rest:tt)*) => {};
494 (emit I32x4TruncSatF32x4S $($rest:tt)*) => {};
495 (emit I32x4TruncSatF32x4U $($rest:tt)*) => {};
496 (emit I32x4TruncSatF64x2SZero $($rest:tt)*) => {};
497 (emit I32x4TruncSatF64x2UZero $($rest:tt)*) => {};
498 (emit I8x16MinU $($rest:tt)*) => {};
499 (emit I16x8MinU $($rest:tt)*) => {};
500 (emit I32x4MinU $($rest:tt)*) => {};
501 (emit I8x16MinS $($rest:tt)*) => {};
502 (emit I16x8MinS $($rest:tt)*) => {};
503 (emit I32x4MinS $($rest:tt)*) => {};
504 (emit I8x16MaxU $($rest:tt)*) => {};
505 (emit I16x8MaxU $($rest:tt)*) => {};
506 (emit I32x4MaxU $($rest:tt)*) => {};
507 (emit I8x16MaxS $($rest:tt)*) => {};
508 (emit I16x8MaxS $($rest:tt)*) => {};
509 (emit I32x4MaxS $($rest:tt)*) => {};
510 (emit I16x8ExtMulLowI8x16S $($rest:tt)*) => {};
511 (emit I32x4ExtMulLowI16x8S $($rest:tt)*) => {};
512 (emit I64x2ExtMulLowI32x4S $($rest:tt)*) => {};
513 (emit I16x8ExtMulHighI8x16S $($rest:tt)*) => {};
514 (emit I32x4ExtMulHighI16x8S $($rest:tt)*) => {};
515 (emit I64x2ExtMulHighI32x4S $($rest:tt)*) => {};
516 (emit I16x8ExtMulLowI8x16U $($rest:tt)*) => {};
517 (emit I32x4ExtMulLowI16x8U $($rest:tt)*) => {};
518 (emit I64x2ExtMulLowI32x4U $($rest:tt)*) => {};
519 (emit I16x8ExtMulHighI8x16U $($rest:tt)*) => {};
520 (emit I32x4ExtMulHighI16x8U $($rest:tt)*) => {};
521 (emit I64x2ExtMulHighI32x4U $($rest:tt)*) => {};
522 (emit I16x8ExtAddPairwiseI8x16U $($rest:tt)*) => {};
523 (emit I16x8ExtAddPairwiseI8x16S $($rest:tt)*) => {};
524 (emit I32x4ExtAddPairwiseI16x8U $($rest:tt)*) => {};
525 (emit I32x4ExtAddPairwiseI16x8S $($rest:tt)*) => {};
526 (emit I32x4DotI16x8S $($rest:tt)*) => {};
527 (emit I8x16Popcnt $($rest:tt)*) => {};
528 (emit I8x16AvgrU $($rest:tt)*) => {};
529 (emit I16x8AvgrU $($rest:tt)*) => {};
530 (emit F32x4Add $($rest:tt)*) => {};
531 (emit F64x2Add $($rest:tt)*) => {};
532 (emit F32x4Sub $($rest:tt)*) => {};
533 (emit F64x2Sub $($rest:tt)*) => {};
534 (emit F32x4Mul $($rest:tt)*) => {};
535 (emit F64x2Mul $($rest:tt)*) => {};
536 (emit F32x4Div $($rest:tt)*) => {};
537 (emit F64x2Div $($rest:tt)*) => {};
538 (emit F32x4Neg $($rest:tt)*) => {};
539 (emit F64x2Neg $($rest:tt)*) => {};
540 (emit F32x4Sqrt $($rest:tt)*) => {};
541 (emit F64x2Sqrt $($rest:tt)*) => {};
542 (emit F32x4Ceil $($rest:tt)*) => {};
543 (emit F64x2Ceil $($rest:tt)*) => {};
544 (emit F32x4Floor $($rest:tt)*) => {};
545 (emit F64x2Floor $($rest:tt)*) => {};
546 (emit F32x4Nearest $($rest:tt)*) => {};
547 (emit F64x2Nearest $($rest:tt)*) => {};
548 (emit F32x4Trunc $($rest:tt)*) => {};
549 (emit F64x2Trunc $($rest:tt)*) => {};
550 (emit V128Load32Zero $($rest:tt)*) => {};
551 (emit V128Load64Zero $($rest:tt)*) => {};
552 (emit F32x4PMin $($rest:tt)*) => {};
553 (emit F64x2PMin $($rest:tt)*) => {};
554 (emit F32x4PMax $($rest:tt)*) => {};
555 (emit F64x2PMax $($rest:tt)*) => {};
556 (emit F32x4Min $($rest:tt)*) => {};
557 (emit F64x2Min $($rest:tt)*) => {};
558 (emit F32x4Max $($rest:tt)*) => {};
559 (emit F64x2Max $($rest:tt)*) => {};
560
561 (emit $unsupported:tt $($rest:tt)*) => {$($rest)*};
562}
563
564impl<'a, 'translation, 'data, M> VisitOperator<'a> for CodeGen<'a, 'translation, 'data, M, Emission>
565where
566 M: MacroAssembler,
567{
568 type Output = Result<()>;
569
570 fn visit_i32_const(&mut self, val: i32) -> Self::Output {
571 self.context.stack.push(Val::i32(val));
572
573 Ok(())
574 }
575
576 fn visit_i64_const(&mut self, val: i64) -> Self::Output {
577 self.context.stack.push(Val::i64(val));
578 Ok(())
579 }
580
581 fn visit_f32_const(&mut self, val: Ieee32) -> Self::Output {
582 self.context.stack.push(Val::f32(val));
583 Ok(())
584 }
585
586 fn visit_f64_const(&mut self, val: Ieee64) -> Self::Output {
587 self.context.stack.push(Val::f64(val));
588 Ok(())
589 }
590
591 fn visit_f32_add(&mut self) -> Self::Output {
592 self.context.binop(
593 self.masm,
594 OperandSize::S32,
595 &mut |masm: &mut M, dst, src, size| {
596 masm.float_add(writable!(dst), dst, src, size)?;
597 Ok(TypedReg::f32(dst))
598 },
599 )
600 }
601
602 fn visit_f64_add(&mut self) -> Self::Output {
603 self.context.binop(
604 self.masm,
605 OperandSize::S64,
606 &mut |masm: &mut M, dst, src, size| {
607 masm.float_add(writable!(dst), dst, src, size)?;
608 Ok(TypedReg::f64(dst))
609 },
610 )
611 }
612
613 fn visit_f32_sub(&mut self) -> Self::Output {
614 self.context.binop(
615 self.masm,
616 OperandSize::S32,
617 &mut |masm: &mut M, dst, src, size| {
618 masm.float_sub(writable!(dst), dst, src, size)?;
619 Ok(TypedReg::f32(dst))
620 },
621 )
622 }
623
624 fn visit_f64_sub(&mut self) -> Self::Output {
625 self.context.binop(
626 self.masm,
627 OperandSize::S64,
628 &mut |masm: &mut M, dst, src, size| {
629 masm.float_sub(writable!(dst), dst, src, size)?;
630 Ok(TypedReg::f64(dst))
631 },
632 )
633 }
634
635 fn visit_f32_mul(&mut self) -> Self::Output {
636 self.context.binop(
637 self.masm,
638 OperandSize::S32,
639 &mut |masm: &mut M, dst, src, size| {
640 masm.float_mul(writable!(dst), dst, src, size)?;
641 Ok(TypedReg::f32(dst))
642 },
643 )
644 }
645
646 fn visit_f64_mul(&mut self) -> Self::Output {
647 self.context.binop(
648 self.masm,
649 OperandSize::S64,
650 &mut |masm: &mut M, dst, src, size| {
651 masm.float_mul(writable!(dst), dst, src, size)?;
652 Ok(TypedReg::f64(dst))
653 },
654 )
655 }
656
657 fn visit_f32_div(&mut self) -> Self::Output {
658 self.context.binop(
659 self.masm,
660 OperandSize::S32,
661 &mut |masm: &mut M, dst, src, size| {
662 masm.float_div(writable!(dst), dst, src, size)?;
663 Ok(TypedReg::f32(dst))
664 },
665 )
666 }
667
668 fn visit_f64_div(&mut self) -> Self::Output {
669 self.context.binop(
670 self.masm,
671 OperandSize::S64,
672 &mut |masm: &mut M, dst, src, size| {
673 masm.float_div(writable!(dst), dst, src, size)?;
674 Ok(TypedReg::f64(dst))
675 },
676 )
677 }
678
679 fn visit_f32_min(&mut self) -> Self::Output {
680 self.context.binop(
681 self.masm,
682 OperandSize::S32,
683 &mut |masm: &mut M, dst, src, size| {
684 masm.float_min(writable!(dst), dst, src, size)?;
685 Ok(TypedReg::f32(dst))
686 },
687 )
688 }
689
690 fn visit_f64_min(&mut self) -> Self::Output {
691 self.context.binop(
692 self.masm,
693 OperandSize::S64,
694 &mut |masm: &mut M, dst, src, size| {
695 masm.float_min(writable!(dst), dst, src, size)?;
696 Ok(TypedReg::f64(dst))
697 },
698 )
699 }
700
701 fn visit_f32_max(&mut self) -> Self::Output {
702 self.context.binop(
703 self.masm,
704 OperandSize::S32,
705 &mut |masm: &mut M, dst, src, size| {
706 masm.float_max(writable!(dst), dst, src, size)?;
707 Ok(TypedReg::f32(dst))
708 },
709 )
710 }
711
712 fn visit_f64_max(&mut self) -> Self::Output {
713 self.context.binop(
714 self.masm,
715 OperandSize::S64,
716 &mut |masm: &mut M, dst, src, size| {
717 masm.float_max(writable!(dst), dst, src, size)?;
718 Ok(TypedReg::f64(dst))
719 },
720 )
721 }
722
723 fn visit_f32_copysign(&mut self) -> Self::Output {
724 self.context.binop(
725 self.masm,
726 OperandSize::S32,
727 &mut |masm: &mut M, dst, src, size| {
728 masm.float_copysign(writable!(dst), dst, src, size)?;
729 Ok(TypedReg::f32(dst))
730 },
731 )
732 }
733
734 fn visit_f64_copysign(&mut self) -> Self::Output {
735 self.context.binop(
736 self.masm,
737 OperandSize::S64,
738 &mut |masm: &mut M, dst, src, size| {
739 masm.float_copysign(writable!(dst), dst, src, size)?;
740 Ok(TypedReg::f64(dst))
741 },
742 )
743 }
744
745 fn visit_f32_abs(&mut self) -> Self::Output {
746 self.context.unop(self.masm, |masm, reg| {
747 masm.float_abs(writable!(reg), OperandSize::S32)?;
748 Ok(TypedReg::f32(reg))
749 })
750 }
751
752 fn visit_f64_abs(&mut self) -> Self::Output {
753 self.context.unop(self.masm, |masm, reg| {
754 masm.float_abs(writable!(reg), OperandSize::S64)?;
755 Ok(TypedReg::f64(reg))
756 })
757 }
758
759 fn visit_f32_neg(&mut self) -> Self::Output {
760 self.context.unop(self.masm, |masm, reg| {
761 masm.float_neg(writable!(reg), OperandSize::S32)?;
762 Ok(TypedReg::f32(reg))
763 })
764 }
765
766 fn visit_f64_neg(&mut self) -> Self::Output {
767 self.context.unop(self.masm, |masm, reg| {
768 masm.float_neg(writable!(reg), OperandSize::S64)?;
769 Ok(TypedReg::f64(reg))
770 })
771 }
772
773 fn visit_f32_floor(&mut self) -> Self::Output {
774 self.masm.float_round(
775 RoundingMode::Down,
776 &mut self.env,
777 &mut self.context,
778 OperandSize::S32,
779 |env, cx, masm| {
780 let builtin = env.builtins.floor_f32::<M::ABI>()?;
781 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
782 },
783 )
784 }
785
786 fn visit_f64_floor(&mut self) -> Self::Output {
787 self.masm.float_round(
788 RoundingMode::Down,
789 &mut self.env,
790 &mut self.context,
791 OperandSize::S64,
792 |env, cx, masm| {
793 let builtin = env.builtins.floor_f64::<M::ABI>()?;
794 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
795 },
796 )
797 }
798
799 fn visit_f32_ceil(&mut self) -> Self::Output {
800 self.masm.float_round(
801 RoundingMode::Up,
802 &mut self.env,
803 &mut self.context,
804 OperandSize::S32,
805 |env, cx, masm| {
806 let builtin = env.builtins.ceil_f32::<M::ABI>()?;
807 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
808 },
809 )
810 }
811
812 fn visit_f64_ceil(&mut self) -> Self::Output {
813 self.masm.float_round(
814 RoundingMode::Up,
815 &mut self.env,
816 &mut self.context,
817 OperandSize::S64,
818 |env, cx, masm| {
819 let builtin = env.builtins.ceil_f64::<M::ABI>()?;
820 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
821 },
822 )
823 }
824
825 fn visit_f32_nearest(&mut self) -> Self::Output {
826 self.masm.float_round(
827 RoundingMode::Nearest,
828 &mut self.env,
829 &mut self.context,
830 OperandSize::S32,
831 |env, cx, masm| {
832 let builtin = env.builtins.nearest_f32::<M::ABI>()?;
833 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
834 },
835 )
836 }
837
838 fn visit_f64_nearest(&mut self) -> Self::Output {
839 self.masm.float_round(
840 RoundingMode::Nearest,
841 &mut self.env,
842 &mut self.context,
843 OperandSize::S64,
844 |env, cx, masm| {
845 let builtin = env.builtins.nearest_f64::<M::ABI>()?;
846 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
847 },
848 )
849 }
850
851 fn visit_f32_trunc(&mut self) -> Self::Output {
852 self.masm.float_round(
853 RoundingMode::Zero,
854 &mut self.env,
855 &mut self.context,
856 OperandSize::S32,
857 |env, cx, masm| {
858 let builtin = env.builtins.trunc_f32::<M::ABI>()?;
859 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
860 },
861 )
862 }
863
864 fn visit_f64_trunc(&mut self) -> Self::Output {
865 self.masm.float_round(
866 RoundingMode::Zero,
867 &mut self.env,
868 &mut self.context,
869 OperandSize::S64,
870 |env, cx, masm| {
871 let builtin = env.builtins.trunc_f64::<M::ABI>()?;
872 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
873 },
874 )
875 }
876
877 fn visit_f32_sqrt(&mut self) -> Self::Output {
878 self.context.unop(self.masm, |masm, reg| {
879 masm.float_sqrt(writable!(reg), reg, OperandSize::S32)?;
880 Ok(TypedReg::f32(reg))
881 })
882 }
883
884 fn visit_f64_sqrt(&mut self) -> Self::Output {
885 self.context.unop(self.masm, |masm, reg| {
886 masm.float_sqrt(writable!(reg), reg, OperandSize::S64)?;
887 Ok(TypedReg::f64(reg))
888 })
889 }
890
891 fn visit_f32_eq(&mut self) -> Self::Output {
892 self.context.float_cmp_op(
893 self.masm,
894 OperandSize::S32,
895 &mut |masm: &mut M, dst, src1, src2, size| {
896 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Eq, size)
897 },
898 )
899 }
900
901 fn visit_f64_eq(&mut self) -> Self::Output {
902 self.context.float_cmp_op(
903 self.masm,
904 OperandSize::S64,
905 &mut |masm: &mut M, dst, src1, src2, size| {
906 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Eq, size)
907 },
908 )
909 }
910
911 fn visit_f32_ne(&mut self) -> Self::Output {
912 self.context.float_cmp_op(
913 self.masm,
914 OperandSize::S32,
915 &mut |masm: &mut M, dst, src1, src2, size| {
916 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Ne, size)
917 },
918 )
919 }
920
921 fn visit_f64_ne(&mut self) -> Self::Output {
922 self.context.float_cmp_op(
923 self.masm,
924 OperandSize::S64,
925 &mut |masm: &mut M, dst, src1, src2, size| {
926 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Ne, size)
927 },
928 )
929 }
930
931 fn visit_f32_lt(&mut self) -> Self::Output {
932 self.context.float_cmp_op(
933 self.masm,
934 OperandSize::S32,
935 &mut |masm: &mut M, dst, src1, src2, size| {
936 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Lt, size)
937 },
938 )
939 }
940
941 fn visit_f64_lt(&mut self) -> Self::Output {
942 self.context.float_cmp_op(
943 self.masm,
944 OperandSize::S64,
945 &mut |masm: &mut M, dst, src1, src2, size| {
946 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Lt, size)
947 },
948 )
949 }
950
951 fn visit_f32_gt(&mut self) -> Self::Output {
952 self.context.float_cmp_op(
953 self.masm,
954 OperandSize::S32,
955 &mut |masm: &mut M, dst, src1, src2, size| {
956 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Gt, size)
957 },
958 )
959 }
960
961 fn visit_f64_gt(&mut self) -> Self::Output {
962 self.context.float_cmp_op(
963 self.masm,
964 OperandSize::S64,
965 &mut |masm: &mut M, dst, src1, src2, size| {
966 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Gt, size)
967 },
968 )
969 }
970
971 fn visit_f32_le(&mut self) -> Self::Output {
972 self.context.float_cmp_op(
973 self.masm,
974 OperandSize::S32,
975 &mut |masm: &mut M, dst, src1, src2, size| {
976 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Le, size)
977 },
978 )
979 }
980
981 fn visit_f64_le(&mut self) -> Self::Output {
982 self.context.float_cmp_op(
983 self.masm,
984 OperandSize::S64,
985 &mut |masm: &mut M, dst, src1, src2, size| {
986 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Le, size)
987 },
988 )
989 }
990
991 fn visit_f32_ge(&mut self) -> Self::Output {
992 self.context.float_cmp_op(
993 self.masm,
994 OperandSize::S32,
995 &mut |masm: &mut M, dst, src1, src2, size| {
996 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Ge, size)
997 },
998 )
999 }
1000
1001 fn visit_f64_ge(&mut self) -> Self::Output {
1002 self.context.float_cmp_op(
1003 self.masm,
1004 OperandSize::S64,
1005 &mut |masm: &mut M, dst, src1, src2, size| {
1006 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Ge, size)
1007 },
1008 )
1009 }
1010
1011 fn visit_f32_convert_i32_s(&mut self) -> Self::Output {
1012 self.context
1013 .convert_op(self.masm, WasmValType::F32, |masm, dst, src, dst_size| {
1014 masm.signed_convert(writable!(dst), src, OperandSize::S32, dst_size)
1015 })
1016 }
1017
1018 fn visit_f32_convert_i32_u(&mut self) -> Self::Output {
1019 self.context.convert_op_with_tmp_reg(
1020 self.masm,
1021 WasmValType::F32,
1022 RegClass::Int,
1023 |masm, dst, src, tmp_gpr, dst_size| {
1024 masm.unsigned_convert(writable!(dst), src, tmp_gpr, OperandSize::S32, dst_size)
1025 },
1026 )
1027 }
1028
1029 fn visit_f32_convert_i64_s(&mut self) -> Self::Output {
1030 self.context
1031 .convert_op(self.masm, WasmValType::F32, |masm, dst, src, dst_size| {
1032 masm.signed_convert(writable!(dst), src, OperandSize::S64, dst_size)
1033 })
1034 }
1035
1036 fn visit_f32_convert_i64_u(&mut self) -> Self::Output {
1037 self.context.convert_op_with_tmp_reg(
1038 self.masm,
1039 WasmValType::F32,
1040 RegClass::Int,
1041 |masm, dst, src, tmp_gpr, dst_size| {
1042 masm.unsigned_convert(writable!(dst), src, tmp_gpr, OperandSize::S64, dst_size)
1043 },
1044 )
1045 }
1046
1047 fn visit_f64_convert_i32_s(&mut self) -> Self::Output {
1048 self.context
1049 .convert_op(self.masm, WasmValType::F64, |masm, dst, src, dst_size| {
1050 masm.signed_convert(writable!(dst), src, OperandSize::S32, dst_size)
1051 })
1052 }
1053
1054 fn visit_f64_convert_i32_u(&mut self) -> Self::Output {
1055 self.context.convert_op_with_tmp_reg(
1056 self.masm,
1057 WasmValType::F64,
1058 RegClass::Int,
1059 |masm, dst, src, tmp_gpr, dst_size| {
1060 masm.unsigned_convert(writable!(dst), src, tmp_gpr, OperandSize::S32, dst_size)
1061 },
1062 )
1063 }
1064
1065 fn visit_f64_convert_i64_s(&mut self) -> Self::Output {
1066 self.context
1067 .convert_op(self.masm, WasmValType::F64, |masm, dst, src, dst_size| {
1068 masm.signed_convert(writable!(dst), src, OperandSize::S64, dst_size)
1069 })
1070 }
1071
1072 fn visit_f64_convert_i64_u(&mut self) -> Self::Output {
1073 self.context.convert_op_with_tmp_reg(
1074 self.masm,
1075 WasmValType::F64,
1076 RegClass::Int,
1077 |masm, dst, src, tmp_gpr, dst_size| {
1078 masm.unsigned_convert(writable!(dst), src, tmp_gpr, OperandSize::S64, dst_size)
1079 },
1080 )
1081 }
1082
1083 fn visit_f32_reinterpret_i32(&mut self) -> Self::Output {
1084 self.context
1085 .convert_op(self.masm, WasmValType::F32, |masm, dst, src, size| {
1086 masm.reinterpret_int_as_float(writable!(dst), src, size)
1087 })
1088 }
1089
1090 fn visit_f64_reinterpret_i64(&mut self) -> Self::Output {
1091 self.context
1092 .convert_op(self.masm, WasmValType::F64, |masm, dst, src, size| {
1093 masm.reinterpret_int_as_float(writable!(dst), src, size)
1094 })
1095 }
1096
1097 fn visit_f32_demote_f64(&mut self) -> Self::Output {
1098 self.context.unop(self.masm, |masm, reg| {
1099 masm.demote(writable!(reg), reg)?;
1100 Ok(TypedReg::f32(reg))
1101 })
1102 }
1103
1104 fn visit_f64_promote_f32(&mut self) -> Self::Output {
1105 self.context.unop(self.masm, |masm, reg| {
1106 masm.promote(writable!(reg), reg)?;
1107 Ok(TypedReg::f64(reg))
1108 })
1109 }
1110
1111 fn visit_i32_add(&mut self) -> Self::Output {
1112 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1113 masm.add(writable!(dst), dst, src, size)?;
1114 Ok(TypedReg::i32(dst))
1115 })
1116 }
1117
1118 fn visit_i64_add(&mut self) -> Self::Output {
1119 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1120 masm.add(writable!(dst), dst, src, size)?;
1121 Ok(TypedReg::i64(dst))
1122 })
1123 }
1124
1125 fn visit_i32_sub(&mut self) -> Self::Output {
1126 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1127 masm.sub(writable!(dst), dst, src, size)?;
1128 Ok(TypedReg::i32(dst))
1129 })
1130 }
1131
1132 fn visit_i64_sub(&mut self) -> Self::Output {
1133 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1134 masm.sub(writable!(dst), dst, src, size)?;
1135 Ok(TypedReg::i64(dst))
1136 })
1137 }
1138
1139 fn visit_i32_mul(&mut self) -> Self::Output {
1140 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1141 masm.mul(writable!(dst), dst, src, size)?;
1142 Ok(TypedReg::i32(dst))
1143 })
1144 }
1145
1146 fn visit_i64_mul(&mut self) -> Self::Output {
1147 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1148 masm.mul(writable!(dst), dst, src, size)?;
1149 Ok(TypedReg::i64(dst))
1150 })
1151 }
1152
1153 fn visit_i32_div_s(&mut self) -> Self::Output {
1154 use DivKind::*;
1155 use OperandSize::*;
1156
1157 self.masm.div(&mut self.context, Signed, S32)
1158 }
1159
1160 fn visit_i32_div_u(&mut self) -> Self::Output {
1161 use DivKind::*;
1162 use OperandSize::*;
1163
1164 self.masm.div(&mut self.context, Unsigned, S32)
1165 }
1166
1167 fn visit_i64_div_s(&mut self) -> Self::Output {
1168 use DivKind::*;
1169 use OperandSize::*;
1170
1171 self.masm.div(&mut self.context, Signed, S64)
1172 }
1173
1174 fn visit_i64_div_u(&mut self) -> Self::Output {
1175 use DivKind::*;
1176 use OperandSize::*;
1177
1178 self.masm.div(&mut self.context, Unsigned, S64)
1179 }
1180
1181 fn visit_i32_rem_s(&mut self) -> Self::Output {
1182 use OperandSize::*;
1183 use RemKind::*;
1184
1185 self.masm.rem(&mut self.context, Signed, S32)
1186 }
1187
1188 fn visit_i32_rem_u(&mut self) -> Self::Output {
1189 use OperandSize::*;
1190 use RemKind::*;
1191
1192 self.masm.rem(&mut self.context, Unsigned, S32)
1193 }
1194
1195 fn visit_i64_rem_s(&mut self) -> Self::Output {
1196 use OperandSize::*;
1197 use RemKind::*;
1198
1199 self.masm.rem(&mut self.context, Signed, S64)
1200 }
1201
1202 fn visit_i64_rem_u(&mut self) -> Self::Output {
1203 use OperandSize::*;
1204 use RemKind::*;
1205
1206 self.masm.rem(&mut self.context, Unsigned, S64)
1207 }
1208
1209 fn visit_i32_eq(&mut self) -> Self::Output {
1210 self.cmp_i32s(IntCmpKind::Eq)
1211 }
1212
1213 fn visit_i64_eq(&mut self) -> Self::Output {
1214 self.cmp_i64s(IntCmpKind::Eq)
1215 }
1216
1217 fn visit_i32_ne(&mut self) -> Self::Output {
1218 self.cmp_i32s(IntCmpKind::Ne)
1219 }
1220
1221 fn visit_i64_ne(&mut self) -> Self::Output {
1222 self.cmp_i64s(IntCmpKind::Ne)
1223 }
1224
1225 fn visit_i32_lt_s(&mut self) -> Self::Output {
1226 self.cmp_i32s(IntCmpKind::LtS)
1227 }
1228
1229 fn visit_i64_lt_s(&mut self) -> Self::Output {
1230 self.cmp_i64s(IntCmpKind::LtS)
1231 }
1232
1233 fn visit_i32_lt_u(&mut self) -> Self::Output {
1234 self.cmp_i32s(IntCmpKind::LtU)
1235 }
1236
1237 fn visit_i64_lt_u(&mut self) -> Self::Output {
1238 self.cmp_i64s(IntCmpKind::LtU)
1239 }
1240
1241 fn visit_i32_le_s(&mut self) -> Self::Output {
1242 self.cmp_i32s(IntCmpKind::LeS)
1243 }
1244
1245 fn visit_i64_le_s(&mut self) -> Self::Output {
1246 self.cmp_i64s(IntCmpKind::LeS)
1247 }
1248
1249 fn visit_i32_le_u(&mut self) -> Self::Output {
1250 self.cmp_i32s(IntCmpKind::LeU)
1251 }
1252
1253 fn visit_i64_le_u(&mut self) -> Self::Output {
1254 self.cmp_i64s(IntCmpKind::LeU)
1255 }
1256
1257 fn visit_i32_gt_s(&mut self) -> Self::Output {
1258 self.cmp_i32s(IntCmpKind::GtS)
1259 }
1260
1261 fn visit_i64_gt_s(&mut self) -> Self::Output {
1262 self.cmp_i64s(IntCmpKind::GtS)
1263 }
1264
1265 fn visit_i32_gt_u(&mut self) -> Self::Output {
1266 self.cmp_i32s(IntCmpKind::GtU)
1267 }
1268
1269 fn visit_i64_gt_u(&mut self) -> Self::Output {
1270 self.cmp_i64s(IntCmpKind::GtU)
1271 }
1272
1273 fn visit_i32_ge_s(&mut self) -> Self::Output {
1274 self.cmp_i32s(IntCmpKind::GeS)
1275 }
1276
1277 fn visit_i64_ge_s(&mut self) -> Self::Output {
1278 self.cmp_i64s(IntCmpKind::GeS)
1279 }
1280
1281 fn visit_i32_ge_u(&mut self) -> Self::Output {
1282 self.cmp_i32s(IntCmpKind::GeU)
1283 }
1284
1285 fn visit_i64_ge_u(&mut self) -> Self::Output {
1286 self.cmp_i64s(IntCmpKind::GeU)
1287 }
1288
1289 fn visit_i32_eqz(&mut self) -> Self::Output {
1290 use OperandSize::*;
1291
1292 self.context.unop(self.masm, |masm, reg| {
1293 masm.cmp_with_set(writable!(reg), RegImm::i32(0), IntCmpKind::Eq, S32)?;
1294 Ok(TypedReg::i32(reg))
1295 })
1296 }
1297
1298 fn visit_i64_eqz(&mut self) -> Self::Output {
1299 use OperandSize::*;
1300
1301 self.context.unop(self.masm, |masm, reg| {
1302 masm.cmp_with_set(writable!(reg), RegImm::i64(0), IntCmpKind::Eq, S64)?;
1303 Ok(TypedReg::i32(reg)) })
1305 }
1306
1307 fn visit_i32_clz(&mut self) -> Self::Output {
1308 use OperandSize::*;
1309
1310 self.context.unop(self.masm, |masm, reg| {
1311 masm.clz(writable!(reg), reg, S32)?;
1312 Ok(TypedReg::i32(reg))
1313 })
1314 }
1315
1316 fn visit_i64_clz(&mut self) -> Self::Output {
1317 use OperandSize::*;
1318
1319 self.context.unop(self.masm, |masm, reg| {
1320 masm.clz(writable!(reg), reg, S64)?;
1321 Ok(TypedReg::i64(reg))
1322 })
1323 }
1324
1325 fn visit_i32_ctz(&mut self) -> Self::Output {
1326 use OperandSize::*;
1327
1328 self.context.unop(self.masm, |masm, reg| {
1329 masm.ctz(writable!(reg), reg, S32)?;
1330 Ok(TypedReg::i32(reg))
1331 })
1332 }
1333
1334 fn visit_i64_ctz(&mut self) -> Self::Output {
1335 use OperandSize::*;
1336
1337 self.context.unop(self.masm, |masm, reg| {
1338 masm.ctz(writable!(reg), reg, S64)?;
1339 Ok(TypedReg::i64(reg))
1340 })
1341 }
1342
1343 fn visit_i32_and(&mut self) -> Self::Output {
1344 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1345 masm.and(writable!(dst), dst, src, size)?;
1346 Ok(TypedReg::i32(dst))
1347 })
1348 }
1349
1350 fn visit_i64_and(&mut self) -> Self::Output {
1351 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1352 masm.and(writable!(dst), dst, src, size)?;
1353 Ok(TypedReg::i64(dst))
1354 })
1355 }
1356
1357 fn visit_i32_or(&mut self) -> Self::Output {
1358 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1359 masm.or(writable!(dst), dst, src, size)?;
1360 Ok(TypedReg::i32(dst))
1361 })
1362 }
1363
1364 fn visit_i64_or(&mut self) -> Self::Output {
1365 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1366 masm.or(writable!(dst), dst, src, size)?;
1367 Ok(TypedReg::i64(dst))
1368 })
1369 }
1370
1371 fn visit_i32_xor(&mut self) -> Self::Output {
1372 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1373 masm.xor(writable!(dst), dst, src, size)?;
1374 Ok(TypedReg::i32(dst))
1375 })
1376 }
1377
1378 fn visit_i64_xor(&mut self) -> Self::Output {
1379 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1380 masm.xor(writable!(dst), dst, src, size)?;
1381 Ok(TypedReg::i64(dst))
1382 })
1383 }
1384
1385 fn visit_i32_shl(&mut self) -> Self::Output {
1386 use ShiftKind::*;
1387
1388 self.context.i32_shift(self.masm, Shl)
1389 }
1390
1391 fn visit_i64_shl(&mut self) -> Self::Output {
1392 use ShiftKind::*;
1393
1394 self.context.i64_shift(self.masm, Shl)
1395 }
1396
1397 fn visit_i32_shr_s(&mut self) -> Self::Output {
1398 use ShiftKind::*;
1399
1400 self.context.i32_shift(self.masm, ShrS)
1401 }
1402
1403 fn visit_i64_shr_s(&mut self) -> Self::Output {
1404 use ShiftKind::*;
1405
1406 self.context.i64_shift(self.masm, ShrS)
1407 }
1408
1409 fn visit_i32_shr_u(&mut self) -> Self::Output {
1410 use ShiftKind::*;
1411
1412 self.context.i32_shift(self.masm, ShrU)
1413 }
1414
1415 fn visit_i64_shr_u(&mut self) -> Self::Output {
1416 use ShiftKind::*;
1417
1418 self.context.i64_shift(self.masm, ShrU)
1419 }
1420
1421 fn visit_i32_rotl(&mut self) -> Self::Output {
1422 use ShiftKind::*;
1423
1424 self.context.i32_shift(self.masm, Rotl)
1425 }
1426
1427 fn visit_i64_rotl(&mut self) -> Self::Output {
1428 use ShiftKind::*;
1429
1430 self.context.i64_shift(self.masm, Rotl)
1431 }
1432
1433 fn visit_i32_rotr(&mut self) -> Self::Output {
1434 use ShiftKind::*;
1435
1436 self.context.i32_shift(self.masm, Rotr)
1437 }
1438
1439 fn visit_i64_rotr(&mut self) -> Self::Output {
1440 use ShiftKind::*;
1441
1442 self.context.i64_shift(self.masm, Rotr)
1443 }
1444
1445 fn visit_end(&mut self) -> Self::Output {
1446 if !self.context.reachable {
1447 self.handle_unreachable_end()
1448 } else {
1449 let mut control = self.pop_control_frame()?;
1450 control.emit_end(self.masm, &mut self.context)
1451 }
1452 }
1453
1454 fn visit_i32_popcnt(&mut self) -> Self::Output {
1455 use OperandSize::*;
1456 self.masm.popcnt(&mut self.context, S32)
1457 }
1458
1459 fn visit_i64_popcnt(&mut self) -> Self::Output {
1460 use OperandSize::*;
1461
1462 self.masm.popcnt(&mut self.context, S64)
1463 }
1464
1465 fn visit_i32_wrap_i64(&mut self) -> Self::Output {
1466 self.context.unop(self.masm, |masm, reg| {
1467 masm.wrap(writable!(reg), reg)?;
1468 Ok(TypedReg::i32(reg))
1469 })
1470 }
1471
1472 fn visit_i64_extend_i32_s(&mut self) -> Self::Output {
1473 self.context.unop(self.masm, |masm, reg| {
1474 masm.extend(writable!(reg), reg, Extend::<Signed>::I64Extend32.into())?;
1475 Ok(TypedReg::i64(reg))
1476 })
1477 }
1478
1479 fn visit_i64_extend_i32_u(&mut self) -> Self::Output {
1480 self.context.unop(self.masm, |masm, reg| {
1481 masm.extend(writable!(reg), reg, Extend::<Zero>::I64Extend32.into())?;
1482 Ok(TypedReg::i64(reg))
1483 })
1484 }
1485
1486 fn visit_i32_extend8_s(&mut self) -> Self::Output {
1487 self.context.unop(self.masm, |masm, reg| {
1488 masm.extend(writable!(reg), reg, Extend::<Signed>::I32Extend8.into())?;
1489 Ok(TypedReg::i32(reg))
1490 })
1491 }
1492
1493 fn visit_i32_extend16_s(&mut self) -> Self::Output {
1494 self.context.unop(self.masm, |masm, reg| {
1495 masm.extend(writable!(reg), reg, Extend::<Signed>::I32Extend16.into())?;
1496 Ok(TypedReg::i32(reg))
1497 })
1498 }
1499
1500 fn visit_i64_extend8_s(&mut self) -> Self::Output {
1501 self.context.unop(self.masm, |masm, reg| {
1502 masm.extend(writable!(reg), reg, Extend::<Signed>::I64Extend8.into())?;
1503 Ok(TypedReg::i64(reg))
1504 })
1505 }
1506
1507 fn visit_i64_extend16_s(&mut self) -> Self::Output {
1508 self.context.unop(self.masm, |masm, reg| {
1509 masm.extend(writable!(reg), reg, Extend::<Signed>::I64Extend16.into())?;
1510 Ok(TypedReg::i64(reg))
1511 })
1512 }
1513
1514 fn visit_i64_extend32_s(&mut self) -> Self::Output {
1515 self.context.unop(self.masm, |masm, reg| {
1516 masm.extend(writable!(reg), reg, Extend::<Signed>::I64Extend32.into())?;
1517 Ok(TypedReg::i64(reg))
1518 })
1519 }
1520
1521 fn visit_i32_trunc_f32_s(&mut self) -> Self::Output {
1522 use OperandSize::*;
1523
1524 self.context
1525 .convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
1526 masm.signed_truncate(writable!(dst), src, S32, dst_size, TruncKind::Unchecked)
1527 })
1528 }
1529
1530 fn visit_i32_trunc_f32_u(&mut self) -> Self::Output {
1531 use OperandSize::*;
1532
1533 self.masm
1534 .unsigned_truncate(&mut self.context, S32, S32, TruncKind::Unchecked)
1535 }
1536
1537 fn visit_i32_trunc_f64_s(&mut self) -> Self::Output {
1538 use OperandSize::*;
1539
1540 self.context
1541 .convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
1542 masm.signed_truncate(writable!(dst), src, S64, dst_size, TruncKind::Unchecked)
1543 })
1544 }
1545
1546 fn visit_i32_trunc_f64_u(&mut self) -> Self::Output {
1547 use OperandSize::*;
1548 self.masm
1549 .unsigned_truncate(&mut self.context, S64, S32, TruncKind::Unchecked)
1550 }
1551
1552 fn visit_i64_trunc_f32_s(&mut self) -> Self::Output {
1553 use OperandSize::*;
1554
1555 self.context
1556 .convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
1557 masm.signed_truncate(writable!(dst), src, S32, dst_size, TruncKind::Unchecked)
1558 })
1559 }
1560
1561 fn visit_i64_trunc_f32_u(&mut self) -> Self::Output {
1562 use OperandSize::*;
1563
1564 self.masm
1565 .unsigned_truncate(&mut self.context, S32, S64, TruncKind::Unchecked)
1566 }
1567
1568 fn visit_i64_trunc_f64_s(&mut self) -> Self::Output {
1569 use OperandSize::*;
1570
1571 self.context
1572 .convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
1573 masm.signed_truncate(writable!(dst), src, S64, dst_size, TruncKind::Unchecked)
1574 })
1575 }
1576
1577 fn visit_i64_trunc_f64_u(&mut self) -> Self::Output {
1578 use OperandSize::*;
1579
1580 self.masm
1581 .unsigned_truncate(&mut self.context, S64, S64, TruncKind::Unchecked)
1582 }
1583
1584 fn visit_i32_reinterpret_f32(&mut self) -> Self::Output {
1585 self.context
1586 .convert_op(self.masm, WasmValType::I32, |masm, dst, src, size| {
1587 masm.reinterpret_float_as_int(writable!(dst), src, size)
1588 })
1589 }
1590
1591 fn visit_i64_reinterpret_f64(&mut self) -> Self::Output {
1592 self.context
1593 .convert_op(self.masm, WasmValType::I64, |masm, dst, src, size| {
1594 masm.reinterpret_float_as_int(writable!(dst), src, size)
1595 })
1596 }
1597
1598 fn visit_local_get(&mut self, index: u32) -> Self::Output {
1599 use WasmValType::*;
1600 let context = &mut self.context;
1601 let slot = context.frame.get_wasm_local(index);
1602 match slot.ty {
1603 I32 | I64 | F32 | F64 | V128 => context.stack.push(Val::local(index, slot.ty)),
1604 Ref(rt) => match rt.heap_type {
1605 WasmHeapType::Func => context.stack.push(Val::local(index, slot.ty)),
1606 _ => bail!(CodeGenError::unsupported_wasm_type()),
1607 },
1608 }
1609
1610 Ok(())
1611 }
1612
1613 fn visit_local_set(&mut self, index: u32) -> Self::Output {
1614 let src = self.emit_set_local(index)?;
1615 self.context.free_reg(src);
1616 Ok(())
1617 }
1618
1619 fn visit_call(&mut self, index: u32) -> Self::Output {
1620 let callee = self.env.callee_from_index(FuncIndex::from_u32(index));
1621 FnCall::emit::<M>(&mut self.env, self.masm, &mut self.context, callee)?;
1622 Ok(())
1623 }
1624
1625 fn visit_call_indirect(&mut self, type_index: u32, table_index: u32) -> Self::Output {
1626 self.context.spill(self.masm)?;
1633
1634 let type_index = TypeIndex::from_u32(type_index);
1635 let table_index = TableIndex::from_u32(table_index);
1636
1637 self.emit_lazy_init_funcref(table_index)?;
1638
1639 let funcref_ptr = self
1643 .context
1644 .stack
1645 .peek()
1646 .map(|v| v.unwrap_reg())
1647 .ok_or_else(|| CodeGenError::missing_values_in_stack())?;
1648 self.masm
1649 .trapz(funcref_ptr.into(), TRAP_INDIRECT_CALL_TO_NULL)?;
1650 self.emit_typecheck_funcref(funcref_ptr.into(), type_index)?;
1651
1652 let callee = self.env.funcref(type_index);
1653 FnCall::emit::<M>(&mut self.env, self.masm, &mut self.context, callee)?;
1654 Ok(())
1655 }
1656
1657 fn visit_table_init(&mut self, elem: u32, table: u32) -> Self::Output {
1658 let at = self.context.stack.ensure_index_at(3)?;
1659
1660 self.context
1661 .stack
1662 .insert_many(at, &[table.try_into()?, elem.try_into()?]);
1663
1664 let builtin = self.env.builtins.table_init::<M::ABI>()?;
1665 FnCall::emit::<M>(
1666 &mut self.env,
1667 self.masm,
1668 &mut self.context,
1669 Callee::Builtin(builtin.clone()),
1670 )?;
1671 self.context.pop_and_free(self.masm)
1672 }
1673
1674 fn visit_table_copy(&mut self, dst: u32, src: u32) -> Self::Output {
1675 let at = self.context.stack.ensure_index_at(3)?;
1676 self.context
1677 .stack
1678 .insert_many(at, &[dst.try_into()?, src.try_into()?]);
1679
1680 let builtin = self.env.builtins.table_copy::<M::ABI>()?;
1681 FnCall::emit::<M>(
1682 &mut self.env,
1683 self.masm,
1684 &mut self.context,
1685 Callee::Builtin(builtin),
1686 )?;
1687 self.context.pop_and_free(self.masm)
1688 }
1689
1690 fn visit_table_get(&mut self, table: u32) -> Self::Output {
1691 let table_index = TableIndex::from_u32(table);
1692 let table = self.env.table(table_index);
1693 let heap_type = table.ref_type.heap_type;
1694
1695 match heap_type {
1696 WasmHeapType::Func => self.emit_lazy_init_funcref(table_index),
1697 _ => Err(format_err!(CodeGenError::unsupported_wasm_type())),
1698 }
1699 }
1700
1701 fn visit_table_grow(&mut self, table: u32) -> Self::Output {
1702 let table_index = TableIndex::from_u32(table);
1703 let table_ty = self.env.table(table_index);
1704 let builtin = match table_ty.ref_type.heap_type {
1705 WasmHeapType::Func => self.env.builtins.table_grow_func_ref::<M::ABI>()?,
1706 _ => bail!(CodeGenError::unsupported_wasm_type()),
1707 };
1708
1709 let len = self.context.stack.len();
1710 let at = self.context.stack.ensure_index_at(2)?;
1712
1713 self.context.stack.inner_mut().swap(len - 1, len - 2);
1720
1721 let builtin = self.prepare_builtin_defined_table_arg(table_index, at, builtin)?;
1722
1723 FnCall::emit::<M>(&mut self.env, self.masm, &mut self.context, builtin)?;
1724
1725 Ok(())
1726 }
1727
1728 fn visit_table_size(&mut self, table: u32) -> Self::Output {
1729 let table_index = TableIndex::from_u32(table);
1730 let table_data = self.env.resolve_table_data(table_index);
1731 self.emit_compute_table_size(&table_data)
1732 }
1733
1734 fn visit_table_fill(&mut self, table: u32) -> Self::Output {
1735 let table_index = TableIndex::from_u32(table);
1736 let table_ty = self.env.table(table_index);
1737
1738 ensure!(
1739 table_ty.ref_type.heap_type == WasmHeapType::Func,
1740 CodeGenError::unsupported_wasm_type()
1741 );
1742
1743 let builtin = self.env.builtins.table_fill_func_ref::<M::ABI>()?;
1744
1745 let at = self.context.stack.ensure_index_at(3)?;
1746
1747 self.context.stack.insert_many(at, &[table.try_into()?]);
1748 FnCall::emit::<M>(
1749 &mut self.env,
1750 self.masm,
1751 &mut self.context,
1752 Callee::Builtin(builtin.clone()),
1753 )?;
1754 self.context.pop_and_free(self.masm)
1755 }
1756
1757 fn visit_table_set(&mut self, table: u32) -> Self::Output {
1758 let ptr_type = self.env.ptr_type();
1759 let table_index = TableIndex::from_u32(table);
1760 let table_data = self.env.resolve_table_data(table_index);
1761 let table = self.env.table(table_index);
1762 match table.ref_type.heap_type {
1763 WasmHeapType::Func => {
1764 ensure!(
1765 self.tunables.table_lazy_init,
1766 CodeGenError::unsupported_table_eager_init()
1767 );
1768 let value = self.context.pop_to_reg(self.masm, None)?;
1769 let index = self.context.pop_to_reg(self.masm, None)?;
1770 let base = self.context.any_gpr(self.masm)?;
1771 let elem_addr =
1772 self.emit_compute_table_elem_addr(index.into(), base, &table_data)?;
1773 self.masm.or(
1775 writable!(value.into()),
1776 value.into(),
1777 RegImm::i64(FUNCREF_INIT_BIT as i64),
1778 ptr_type.try_into()?,
1779 )?;
1780
1781 self.masm.store_ptr(value.into(), elem_addr)?;
1782
1783 self.context.free_reg(value);
1784 self.context.free_reg(index);
1785 self.context.free_reg(base);
1786 Ok(())
1787 }
1788 _ => Err(format_err!(CodeGenError::unsupported_wasm_type())),
1789 }
1790 }
1791
1792 fn visit_elem_drop(&mut self, index: u32) -> Self::Output {
1793 let elem_drop = self.env.builtins.elem_drop::<M::ABI>()?;
1794 self.context.stack.extend([index.try_into()?]);
1795 FnCall::emit::<M>(
1796 &mut self.env,
1797 self.masm,
1798 &mut self.context,
1799 Callee::Builtin(elem_drop),
1800 )?;
1801 self.context.pop_and_free(self.masm)
1802 }
1803
1804 fn visit_memory_init(&mut self, data_index: u32, mem: u32) -> Self::Output {
1805 let at = self.context.stack.ensure_index_at(3)?;
1806 self.context
1807 .stack
1808 .insert_many(at, &[mem.try_into()?, data_index.try_into()?]);
1809 let builtin = self.env.builtins.memory_init::<M::ABI>()?;
1810 FnCall::emit::<M>(
1811 &mut self.env,
1812 self.masm,
1813 &mut self.context,
1814 Callee::Builtin(builtin),
1815 )?;
1816 self.context.pop_and_free(self.masm)
1817 }
1818
1819 fn visit_memory_copy(&mut self, dst_mem: u32, src_mem: u32) -> Self::Output {
1820 let _ = self.context.stack.ensure_index_at(3)?;
1826 let at = self.context.stack.ensure_index_at(2)?;
1827 self.context.stack.insert_many(at, &[src_mem.try_into()?]);
1828
1829 let at = self.context.stack.ensure_index_at(4)?;
1831 self.context.stack.insert_many(at, &[dst_mem.try_into()?]);
1832
1833 let builtin = self.env.builtins.memory_copy::<M::ABI>()?;
1834
1835 FnCall::emit::<M>(
1836 &mut self.env,
1837 self.masm,
1838 &mut self.context,
1839 Callee::Builtin(builtin),
1840 )?;
1841 self.context.pop_and_free(self.masm)
1842 }
1843
1844 fn visit_memory_fill(&mut self, mem: u32) -> Self::Output {
1845 let at = self.context.stack.ensure_index_at(3)?;
1846 let mem = MemoryIndex::from_u32(mem);
1847
1848 let builtin = self.env.builtins.memory_fill::<M::ABI>()?;
1849 let builtin = self.prepare_builtin_defined_memory_arg(mem, at, builtin)?;
1850
1851 FnCall::emit::<M>(&mut self.env, self.masm, &mut self.context, builtin)?;
1852 self.context.pop_and_free(self.masm)
1853 }
1854
1855 fn visit_memory_size(&mut self, mem: u32) -> Self::Output {
1856 let heap = self.env.resolve_heap(MemoryIndex::from_u32(mem));
1857 self.emit_compute_memory_size(&heap)
1858 }
1859
1860 fn visit_memory_grow(&mut self, mem: u32) -> Self::Output {
1861 let at = self.context.stack.ensure_index_at(1)?;
1862 let mem = MemoryIndex::from_u32(mem);
1863 let builtin = self.env.builtins.memory_grow::<M::ABI>()?;
1867 let builtin = self.prepare_builtin_defined_memory_arg(mem, at + 1, builtin)?;
1868
1869 let heap = self.env.resolve_heap(mem);
1870 FnCall::emit::<M>(&mut self.env, self.masm, &mut self.context, builtin)?;
1871
1872 match (self.env.ptr_type(), heap.index_type()) {
1876 (WasmValType::I64, WasmValType::I64) => Ok(()),
1877 (WasmValType::I64, WasmValType::I32) => {
1880 let top: Reg = self.context.pop_to_reg(self.masm, None)?.into();
1881 self.masm.wrap(writable!(top), top)?;
1882 self.context.stack.push(TypedReg::i32(top).into());
1883 Ok(())
1884 }
1885 _ => Err(format_err!(CodeGenError::unsupported_32_bit_platform())),
1886 }
1887 }
1888
1889 fn visit_data_drop(&mut self, data_index: u32) -> Self::Output {
1890 self.context.stack.extend([data_index.try_into()?]);
1891
1892 let builtin = self.env.builtins.data_drop::<M::ABI>()?;
1893 FnCall::emit::<M>(
1894 &mut self.env,
1895 self.masm,
1896 &mut self.context,
1897 Callee::Builtin(builtin),
1898 )?;
1899 self.context.pop_and_free(self.masm)
1900 }
1901
1902 fn visit_nop(&mut self) -> Self::Output {
1903 Ok(())
1904 }
1905
1906 fn visit_if(&mut self, blockty: BlockType) -> Self::Output {
1907 self.control_frames.push(ControlStackFrame::r#if(
1908 self.env.resolve_block_sig(blockty)?,
1909 self.masm,
1910 &mut self.context,
1911 )?);
1912
1913 Ok(())
1914 }
1915
1916 fn visit_else(&mut self) -> Self::Output {
1917 if !self.context.reachable {
1918 self.handle_unreachable_else()
1919 } else {
1920 let control = self
1921 .control_frames
1922 .last_mut()
1923 .ok_or_else(|| CodeGenError::control_frame_expected())?;
1924 control.emit_else(self.masm, &mut self.context)
1925 }
1926 }
1927
1928 fn visit_block(&mut self, blockty: BlockType) -> Self::Output {
1929 self.control_frames.push(ControlStackFrame::block(
1930 self.env.resolve_block_sig(blockty)?,
1931 self.masm,
1932 &mut self.context,
1933 )?);
1934
1935 Ok(())
1936 }
1937
1938 fn visit_loop(&mut self, blockty: BlockType) -> Self::Output {
1939 self.control_frames.push(ControlStackFrame::r#loop(
1940 self.env.resolve_block_sig(blockty)?,
1941 self.masm,
1942 &mut self.context,
1943 )?);
1944
1945 self.maybe_emit_epoch_check()?;
1946 self.maybe_emit_fuel_check()
1947 }
1948
1949 fn visit_br(&mut self, depth: u32) -> Self::Output {
1950 let index = control_index(depth, self.control_frames.len())?;
1951 let frame = &mut self.control_frames[index];
1952 self.context
1953 .br::<_, _, UnconditionalBranch>(frame, self.masm, |masm, cx, frame| {
1954 frame.pop_abi_results::<M, _>(cx, masm, |results, _, _| {
1955 Ok(results.ret_area().copied())
1956 })
1957 })
1958 }
1959
1960 fn visit_br_if(&mut self, depth: u32) -> Self::Output {
1961 let index = control_index(depth, self.control_frames.len())?;
1962 let frame = &mut self.control_frames[index];
1963 frame.set_as_target();
1964
1965 let top = {
1966 let top = self.context.without::<Result<TypedReg>, M, _>(
1967 frame.results::<M>()?.regs(),
1968 self.masm,
1969 |ctx, masm| ctx.pop_to_reg(masm, None),
1970 )??;
1971 self.context.spill(self.masm)?;
1976 frame.top_abi_results::<M, _>(
1977 &mut self.context,
1978 self.masm,
1979 |results, context, masm| {
1980 if results.on_stack() {
1987 let stack_consumed = context.stack.sizeof(results.stack_operands_len());
1988 let base = masm.sp_offset()?.as_u32() - stack_consumed;
1989 let offs = base + results.size();
1990 Ok(Some(RetArea::sp(SPOffset::from_u32(offs))))
1991 } else {
1992 Ok(None)
1993 }
1994 },
1995 )?;
1996 top
1997 };
1998
1999 let current_sp_offset = self.masm.sp_offset()?;
2001 let unbalanced = frame.unbalanced(self.masm)?;
2002 let (label, cmp) = if unbalanced {
2003 (self.masm.get_label()?, IntCmpKind::Eq)
2004 } else {
2005 (*frame.label(), IntCmpKind::Ne)
2006 };
2007
2008 self.masm
2009 .branch(cmp, top.reg, top.reg.into(), label, OperandSize::S32)?;
2010 self.context.free_reg(top);
2011
2012 if unbalanced {
2013 self.context
2014 .br::<_, _, ConditionalBranch>(frame, self.masm, |_, _, _| Ok(()))?;
2015
2016 self.masm.reset_stack_pointer(current_sp_offset)?;
2019 self.masm.bind(label)?;
2020 }
2021
2022 Ok(())
2023 }
2024
2025 fn visit_br_table(&mut self, targets: BrTable<'a>) -> Self::Output {
2026 let len = targets.len() + 1;
2028 let mut labels: SmallVec<[_; 5]> = smallvec![];
2032 for _ in 0..len {
2033 labels.push(self.masm.get_label()?);
2034 }
2035
2036 let mut innermost = targets.default();
2047 for target in targets.targets() {
2048 let target = target?;
2049 if target < innermost {
2050 innermost = target;
2051 }
2052 }
2053
2054 let innermost_index = control_index(innermost, self.control_frames.len())?;
2055 let innermost_frame = &mut self.control_frames[innermost_index];
2056 let innermost_result = innermost_frame.results::<M>()?;
2057
2058 let (index, tmp) = {
2059 let index_and_tmp = self.context.without::<Result<(TypedReg, _)>, M, _>(
2060 innermost_result.regs(),
2061 self.masm,
2062 |cx, masm| Ok((cx.pop_to_reg(masm, None)?, cx.any_gpr(masm)?)),
2063 )??;
2064
2065 innermost_frame.pop_abi_results::<M, _>(
2077 &mut self.context,
2078 self.masm,
2079 |results, _, _| Ok(results.ret_area().copied()),
2080 )?;
2081 index_and_tmp
2082 };
2083
2084 self.masm.jmp_table(&labels, index.into(), tmp)?;
2085 let current_sp = self.masm.sp_offset()?;
2090
2091 for (t, l) in targets
2092 .targets()
2093 .chain(std::iter::once(Ok(targets.default())))
2094 .zip(labels.iter())
2095 {
2096 let control_index = control_index(t?, self.control_frames.len())?;
2097 let frame = &mut self.control_frames[control_index];
2098 self.masm.reset_stack_pointer(current_sp)?;
2102
2103 self.masm.bind(*l)?;
2107 self.context
2110 .br::<_, _, UnconditionalBranch>(frame, self.masm, |_, _, _| Ok(()))?;
2111 }
2112 self.masm.reset_stack_pointer(current_sp)?;
2116 self.context.reachable = false;
2117 self.context.free_reg(index.reg);
2118 self.context.free_reg(tmp);
2119
2120 Ok(())
2121 }
2122
2123 fn visit_return(&mut self) -> Self::Output {
2124 let outermost = &mut self.control_frames[0];
2129 self.context
2130 .br::<_, _, UnconditionalBranch>(outermost, self.masm, |masm, cx, frame| {
2131 frame.pop_abi_results::<M, _>(cx, masm, |results, _, _| {
2132 Ok(results.ret_area().copied())
2133 })
2134 })
2135 }
2136
2137 fn visit_unreachable(&mut self) -> Self::Output {
2138 self.masm.unreachable()?;
2139 self.context.reachable = false;
2140 let outermost = &mut self.control_frames[0];
2143 outermost.set_as_target();
2144
2145 Ok(())
2146 }
2147
2148 fn visit_local_tee(&mut self, index: u32) -> Self::Output {
2149 let typed_reg = self.emit_set_local(index)?;
2150 self.context.stack.push(typed_reg.into());
2151
2152 Ok(())
2153 }
2154
2155 fn visit_global_get(&mut self, global_index: u32) -> Self::Output {
2156 let index = GlobalIndex::from_u32(global_index);
2157 let (ty, base, offset) = self.emit_get_global_addr(index)?;
2158 let addr = self.masm.address_at_reg(base, offset)?;
2159 let dst = self.context.reg_for_type(ty, self.masm)?;
2160 self.masm.load(addr, writable!(dst), ty.try_into()?)?;
2161 self.context.stack.push(Val::reg(dst, ty));
2162
2163 self.context.free_reg(base);
2164
2165 Ok(())
2166 }
2167
2168 fn visit_global_set(&mut self, global_index: u32) -> Self::Output {
2169 let index = GlobalIndex::from_u32(global_index);
2170 let (ty, base, offset) = self.emit_get_global_addr(index)?;
2171 let addr = self.masm.address_at_reg(base, offset)?;
2172
2173 let typed_reg = self.context.pop_to_reg(self.masm, None)?;
2174 self.masm
2175 .store(typed_reg.reg.into(), addr, ty.try_into()?)?;
2176 self.context.free_reg(typed_reg.reg);
2177 self.context.free_reg(base);
2178
2179 Ok(())
2180 }
2181
2182 fn visit_drop(&mut self) -> Self::Output {
2183 self.context.drop_last(1, |regalloc, val| match val {
2184 Val::Reg(tr) => Ok(regalloc.free(tr.reg)),
2185 Val::Memory(m) => self.masm.free_stack(m.slot.size),
2186 _ => Ok(()),
2187 })
2188 }
2189
2190 fn visit_select(&mut self) -> Self::Output {
2191 let cond = self.context.pop_to_reg(self.masm, None)?;
2192 let val2 = self.context.pop_to_reg(self.masm, None)?;
2193 let val1 = self.context.pop_to_reg(self.masm, None)?;
2194 self.masm.cmp(cond.reg, RegImm::i32(0), OperandSize::S32)?;
2195 self.masm.cmov(
2198 writable!(val2.into()),
2199 val1.into(),
2200 IntCmpKind::Ne,
2201 val1.ty.try_into()?,
2202 )?;
2203 self.context.stack.push(val2.into());
2204 self.context.free_reg(val1.reg);
2205 self.context.free_reg(cond);
2206
2207 Ok(())
2208 }
2209
2210 fn visit_i32_load(&mut self, memarg: MemArg) -> Self::Output {
2211 self.emit_wasm_load(
2212 &memarg,
2213 WasmValType::I32,
2214 LoadKind::Operand(OperandSize::S32),
2215 )
2216 }
2217
2218 fn visit_i32_load8_s(&mut self, memarg: MemArg) -> Self::Output {
2219 self.emit_wasm_load(
2220 &memarg,
2221 WasmValType::I32,
2222 LoadKind::ScalarExtend(Extend::<Signed>::I32Extend8.into()),
2223 )
2224 }
2225
2226 fn visit_i32_load8_u(&mut self, memarg: MemArg) -> Self::Output {
2227 self.emit_wasm_load(
2228 &memarg,
2229 WasmValType::I32,
2230 LoadKind::ScalarExtend(Extend::<Zero>::I32Extend8.into()),
2231 )
2232 }
2233
2234 fn visit_i32_load16_s(&mut self, memarg: MemArg) -> Self::Output {
2235 self.emit_wasm_load(
2236 &memarg,
2237 WasmValType::I32,
2238 LoadKind::ScalarExtend(Extend::<Signed>::I32Extend16.into()),
2239 )
2240 }
2241
2242 fn visit_i32_load16_u(&mut self, memarg: MemArg) -> Self::Output {
2243 self.emit_wasm_load(
2244 &memarg,
2245 WasmValType::I32,
2246 LoadKind::ScalarExtend(Extend::<Zero>::I32Extend16.into()),
2247 )
2248 }
2249
2250 fn visit_i32_store(&mut self, memarg: MemArg) -> Self::Output {
2251 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S32))
2252 }
2253
2254 fn visit_i32_store8(&mut self, memarg: MemArg) -> Self::Output {
2255 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S8))
2256 }
2257
2258 fn visit_i32_store16(&mut self, memarg: MemArg) -> Self::Output {
2259 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S16))
2260 }
2261
2262 fn visit_i64_load8_s(&mut self, memarg: MemArg) -> Self::Output {
2263 self.emit_wasm_load(
2264 &memarg,
2265 WasmValType::I64,
2266 LoadKind::ScalarExtend(Extend::<Signed>::I64Extend8.into()),
2267 )
2268 }
2269
2270 fn visit_i64_load8_u(&mut self, memarg: MemArg) -> Self::Output {
2271 self.emit_wasm_load(
2272 &memarg,
2273 WasmValType::I64,
2274 LoadKind::ScalarExtend(Extend::<Zero>::I64Extend8.into()),
2275 )
2276 }
2277
2278 fn visit_i64_load16_u(&mut self, memarg: MemArg) -> Self::Output {
2279 self.emit_wasm_load(
2280 &memarg,
2281 WasmValType::I64,
2282 LoadKind::ScalarExtend(Extend::<Zero>::I64Extend16.into()),
2283 )
2284 }
2285
2286 fn visit_i64_load16_s(&mut self, memarg: MemArg) -> Self::Output {
2287 self.emit_wasm_load(
2288 &memarg,
2289 WasmValType::I64,
2290 LoadKind::ScalarExtend(Extend::<Signed>::I64Extend16.into()),
2291 )
2292 }
2293
2294 fn visit_i64_load32_u(&mut self, memarg: MemArg) -> Self::Output {
2295 self.emit_wasm_load(
2296 &memarg,
2297 WasmValType::I64,
2298 LoadKind::ScalarExtend(Extend::<Zero>::I64Extend32.into()),
2299 )
2300 }
2301
2302 fn visit_i64_load32_s(&mut self, memarg: MemArg) -> Self::Output {
2303 self.emit_wasm_load(
2304 &memarg,
2305 WasmValType::I64,
2306 LoadKind::ScalarExtend(Extend::<Signed>::I64Extend32.into()),
2307 )
2308 }
2309
2310 fn visit_i64_load(&mut self, memarg: MemArg) -> Self::Output {
2311 self.emit_wasm_load(
2312 &memarg,
2313 WasmValType::I64,
2314 LoadKind::Operand(OperandSize::S64),
2315 )
2316 }
2317
2318 fn visit_i64_store(&mut self, memarg: MemArg) -> Self::Output {
2319 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S64))
2320 }
2321
2322 fn visit_i64_store8(&mut self, memarg: MemArg) -> Self::Output {
2323 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S8))
2324 }
2325
2326 fn visit_i64_store16(&mut self, memarg: MemArg) -> Self::Output {
2327 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S16))
2328 }
2329
2330 fn visit_i64_store32(&mut self, memarg: MemArg) -> Self::Output {
2331 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S32))
2332 }
2333
2334 fn visit_f32_load(&mut self, memarg: MemArg) -> Self::Output {
2335 self.emit_wasm_load(
2336 &memarg,
2337 WasmValType::F32,
2338 LoadKind::Operand(OperandSize::S32),
2339 )
2340 }
2341
2342 fn visit_f32_store(&mut self, memarg: MemArg) -> Self::Output {
2343 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S32))
2344 }
2345
2346 fn visit_f64_load(&mut self, memarg: MemArg) -> Self::Output {
2347 self.emit_wasm_load(
2348 &memarg,
2349 WasmValType::F64,
2350 LoadKind::Operand(OperandSize::S64),
2351 )
2352 }
2353
2354 fn visit_f64_store(&mut self, memarg: MemArg) -> Self::Output {
2355 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S64))
2356 }
2357
2358 fn visit_i32_trunc_sat_f32_s(&mut self) -> Self::Output {
2359 use OperandSize::*;
2360
2361 self.context
2362 .convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
2363 masm.signed_truncate(writable!(dst), src, S32, dst_size, TruncKind::Checked)
2364 })
2365 }
2366
2367 fn visit_i32_trunc_sat_f32_u(&mut self) -> Self::Output {
2368 use OperandSize::*;
2369
2370 self.masm
2371 .unsigned_truncate(&mut self.context, S32, S32, TruncKind::Checked)
2372 }
2373
2374 fn visit_i32_trunc_sat_f64_s(&mut self) -> Self::Output {
2375 use OperandSize::*;
2376
2377 self.context
2378 .convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
2379 masm.signed_truncate(writable!(dst), src, S64, dst_size, TruncKind::Checked)
2380 })
2381 }
2382
2383 fn visit_i32_trunc_sat_f64_u(&mut self) -> Self::Output {
2384 use OperandSize::*;
2385
2386 self.masm
2387 .unsigned_truncate(&mut self.context, S64, S32, TruncKind::Checked)
2388 }
2389
2390 fn visit_i64_trunc_sat_f32_s(&mut self) -> Self::Output {
2391 use OperandSize::*;
2392
2393 self.context
2394 .convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
2395 masm.signed_truncate(writable!(dst), src, S32, dst_size, TruncKind::Checked)
2396 })
2397 }
2398
2399 fn visit_i64_trunc_sat_f32_u(&mut self) -> Self::Output {
2400 use OperandSize::*;
2401
2402 self.masm
2403 .unsigned_truncate(&mut self.context, S32, S64, TruncKind::Checked)
2404 }
2405
2406 fn visit_i64_trunc_sat_f64_s(&mut self) -> Self::Output {
2407 use OperandSize::*;
2408
2409 self.context
2410 .convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
2411 masm.signed_truncate(writable!(dst), src, S64, dst_size, TruncKind::Checked)
2412 })
2413 }
2414
2415 fn visit_i64_trunc_sat_f64_u(&mut self) -> Self::Output {
2416 use OperandSize::*;
2417
2418 self.masm
2419 .unsigned_truncate(&mut self.context, S64, S64, TruncKind::Checked)
2420 }
2421
2422 fn visit_i64_add128(&mut self) -> Self::Output {
2423 self.context
2424 .binop128(self.masm, |masm, lhs_lo, lhs_hi, rhs_lo, rhs_hi| {
2425 masm.add128(
2426 writable!(lhs_lo),
2427 writable!(lhs_hi),
2428 lhs_lo,
2429 lhs_hi,
2430 rhs_lo,
2431 rhs_hi,
2432 )?;
2433 Ok((TypedReg::i64(lhs_lo), TypedReg::i64(lhs_hi)))
2434 })
2435 }
2436
2437 fn visit_i64_sub128(&mut self) -> Self::Output {
2438 self.context
2439 .binop128(self.masm, |masm, lhs_lo, lhs_hi, rhs_lo, rhs_hi| {
2440 masm.sub128(
2441 writable!(lhs_lo),
2442 writable!(lhs_hi),
2443 lhs_lo,
2444 lhs_hi,
2445 rhs_lo,
2446 rhs_hi,
2447 )?;
2448 Ok((TypedReg::i64(lhs_lo), TypedReg::i64(lhs_hi)))
2449 })
2450 }
2451
2452 fn visit_i64_mul_wide_s(&mut self) -> Self::Output {
2453 self.masm.mul_wide(&mut self.context, MulWideKind::Signed)
2454 }
2455
2456 fn visit_i64_mul_wide_u(&mut self) -> Self::Output {
2457 self.masm.mul_wide(&mut self.context, MulWideKind::Unsigned)
2458 }
2459
2460 fn visit_i32_atomic_load8_u(&mut self, memarg: MemArg) -> Self::Output {
2461 self.emit_wasm_load(
2462 &memarg,
2463 WasmValType::I32,
2464 LoadKind::Atomic(OperandSize::S8, Some(Extend::<Zero>::I32Extend8.into())),
2465 )
2466 }
2467
2468 fn visit_i32_atomic_load16_u(&mut self, memarg: MemArg) -> Self::Output {
2469 self.emit_wasm_load(
2470 &memarg,
2471 WasmValType::I32,
2472 LoadKind::Atomic(OperandSize::S16, Some(Extend::<Zero>::I32Extend16.into())),
2473 )
2474 }
2475
2476 fn visit_i32_atomic_load(&mut self, memarg: MemArg) -> Self::Output {
2477 self.emit_wasm_load(
2478 &memarg,
2479 WasmValType::I32,
2480 LoadKind::Atomic(OperandSize::S32, None),
2481 )
2482 }
2483
2484 fn visit_i64_atomic_load8_u(&mut self, memarg: MemArg) -> Self::Output {
2485 self.emit_wasm_load(
2486 &memarg,
2487 WasmValType::I64,
2488 LoadKind::Atomic(OperandSize::S8, Some(Extend::<Zero>::I64Extend8.into())),
2489 )
2490 }
2491
2492 fn visit_i64_atomic_load16_u(&mut self, memarg: MemArg) -> Self::Output {
2493 self.emit_wasm_load(
2494 &memarg,
2495 WasmValType::I64,
2496 LoadKind::Atomic(OperandSize::S16, Some(Extend::<Zero>::I64Extend16.into())),
2497 )
2498 }
2499
2500 fn visit_i64_atomic_load32_u(&mut self, memarg: MemArg) -> Self::Output {
2501 self.emit_wasm_load(
2502 &memarg,
2503 WasmValType::I64,
2504 LoadKind::Atomic(OperandSize::S32, Some(Extend::<Zero>::I64Extend32.into())),
2505 )
2506 }
2507
2508 fn visit_i64_atomic_load(&mut self, memarg: MemArg) -> Self::Output {
2509 self.emit_wasm_load(
2510 &memarg,
2511 WasmValType::I64,
2512 LoadKind::Atomic(OperandSize::S64, None),
2513 )
2514 }
2515
2516 fn visit_i32_atomic_store(&mut self, memarg: MemArg) -> Self::Output {
2517 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S32))
2518 }
2519
2520 fn visit_i64_atomic_store(&mut self, memarg: MemArg) -> Self::Output {
2521 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S64))
2522 }
2523
2524 fn visit_i32_atomic_store8(&mut self, memarg: MemArg) -> Self::Output {
2525 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S8))
2526 }
2527
2528 fn visit_i32_atomic_store16(&mut self, memarg: MemArg) -> Self::Output {
2529 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S16))
2530 }
2531
2532 fn visit_i64_atomic_store8(&mut self, memarg: MemArg) -> Self::Output {
2533 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S8))
2534 }
2535
2536 fn visit_i64_atomic_store16(&mut self, memarg: MemArg) -> Self::Output {
2537 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S16))
2538 }
2539
2540 fn visit_i64_atomic_store32(&mut self, memarg: MemArg) -> Self::Output {
2541 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S32))
2542 }
2543
2544 fn visit_i32_atomic_rmw8_add_u(&mut self, arg: MemArg) -> Self::Output {
2545 self.emit_atomic_rmw(
2546 &arg,
2547 RmwOp::Add,
2548 OperandSize::S8,
2549 Some(Extend::<Zero>::I32Extend8),
2550 )
2551 }
2552
2553 fn visit_i32_atomic_rmw16_add_u(&mut self, arg: MemArg) -> Self::Output {
2554 self.emit_atomic_rmw(
2555 &arg,
2556 RmwOp::Add,
2557 OperandSize::S16,
2558 Some(Extend::<Zero>::I32Extend16),
2559 )
2560 }
2561
2562 fn visit_i32_atomic_rmw_add(&mut self, arg: MemArg) -> Self::Output {
2563 self.emit_atomic_rmw(&arg, RmwOp::Add, OperandSize::S32, None)
2564 }
2565
2566 fn visit_i64_atomic_rmw8_add_u(&mut self, arg: MemArg) -> Self::Output {
2567 self.emit_atomic_rmw(
2568 &arg,
2569 RmwOp::Add,
2570 OperandSize::S8,
2571 Some(Extend::<Zero>::I64Extend8),
2572 )
2573 }
2574
2575 fn visit_i64_atomic_rmw16_add_u(&mut self, arg: MemArg) -> Self::Output {
2576 self.emit_atomic_rmw(
2577 &arg,
2578 RmwOp::Add,
2579 OperandSize::S16,
2580 Some(Extend::<Zero>::I64Extend16),
2581 )
2582 }
2583
2584 fn visit_i64_atomic_rmw32_add_u(&mut self, arg: MemArg) -> Self::Output {
2585 self.emit_atomic_rmw(
2586 &arg,
2587 RmwOp::Add,
2588 OperandSize::S32,
2589 Some(Extend::<Zero>::I64Extend32),
2590 )
2591 }
2592
2593 fn visit_i64_atomic_rmw_add(&mut self, arg: MemArg) -> Self::Output {
2594 self.emit_atomic_rmw(&arg, RmwOp::Add, OperandSize::S64, None)
2595 }
2596
2597 fn visit_i32_atomic_rmw8_sub_u(&mut self, arg: MemArg) -> Self::Output {
2598 self.emit_atomic_rmw(
2599 &arg,
2600 RmwOp::Sub,
2601 OperandSize::S8,
2602 Some(Extend::<Zero>::I32Extend8),
2603 )
2604 }
2605 fn visit_i32_atomic_rmw16_sub_u(&mut self, arg: MemArg) -> Self::Output {
2606 self.emit_atomic_rmw(
2607 &arg,
2608 RmwOp::Sub,
2609 OperandSize::S16,
2610 Some(Extend::<Zero>::I32Extend16),
2611 )
2612 }
2613
2614 fn visit_i32_atomic_rmw_sub(&mut self, arg: MemArg) -> Self::Output {
2615 self.emit_atomic_rmw(&arg, RmwOp::Sub, OperandSize::S32, None)
2616 }
2617
2618 fn visit_i64_atomic_rmw8_sub_u(&mut self, arg: MemArg) -> Self::Output {
2619 self.emit_atomic_rmw(
2620 &arg,
2621 RmwOp::Sub,
2622 OperandSize::S8,
2623 Some(Extend::<Zero>::I64Extend8),
2624 )
2625 }
2626
2627 fn visit_i64_atomic_rmw16_sub_u(&mut self, arg: MemArg) -> Self::Output {
2628 self.emit_atomic_rmw(
2629 &arg,
2630 RmwOp::Sub,
2631 OperandSize::S16,
2632 Some(Extend::<Zero>::I64Extend16),
2633 )
2634 }
2635
2636 fn visit_i64_atomic_rmw32_sub_u(&mut self, arg: MemArg) -> Self::Output {
2637 self.emit_atomic_rmw(
2638 &arg,
2639 RmwOp::Sub,
2640 OperandSize::S32,
2641 Some(Extend::<Zero>::I64Extend32),
2642 )
2643 }
2644
2645 fn visit_i64_atomic_rmw_sub(&mut self, arg: MemArg) -> Self::Output {
2646 self.emit_atomic_rmw(&arg, RmwOp::Sub, OperandSize::S64, None)
2647 }
2648
2649 fn visit_i32_atomic_rmw8_xchg_u(&mut self, arg: MemArg) -> Self::Output {
2650 self.emit_atomic_rmw(
2651 &arg,
2652 RmwOp::Xchg,
2653 OperandSize::S8,
2654 Some(Extend::<Zero>::I32Extend8),
2655 )
2656 }
2657
2658 fn visit_i32_atomic_rmw16_xchg_u(&mut self, arg: MemArg) -> Self::Output {
2659 self.emit_atomic_rmw(
2660 &arg,
2661 RmwOp::Xchg,
2662 OperandSize::S16,
2663 Some(Extend::<Zero>::I32Extend16),
2664 )
2665 }
2666
2667 fn visit_i32_atomic_rmw_xchg(&mut self, arg: MemArg) -> Self::Output {
2668 self.emit_atomic_rmw(&arg, RmwOp::Xchg, OperandSize::S32, None)
2669 }
2670
2671 fn visit_i64_atomic_rmw8_xchg_u(&mut self, arg: MemArg) -> Self::Output {
2672 self.emit_atomic_rmw(
2673 &arg,
2674 RmwOp::Xchg,
2675 OperandSize::S8,
2676 Some(Extend::<Zero>::I64Extend8),
2677 )
2678 }
2679
2680 fn visit_i64_atomic_rmw16_xchg_u(&mut self, arg: MemArg) -> Self::Output {
2681 self.emit_atomic_rmw(
2682 &arg,
2683 RmwOp::Xchg,
2684 OperandSize::S16,
2685 Some(Extend::<Zero>::I64Extend16),
2686 )
2687 }
2688
2689 fn visit_i64_atomic_rmw32_xchg_u(&mut self, arg: MemArg) -> Self::Output {
2690 self.emit_atomic_rmw(
2691 &arg,
2692 RmwOp::Xchg,
2693 OperandSize::S32,
2694 Some(Extend::<Zero>::I64Extend32),
2695 )
2696 }
2697
2698 fn visit_i64_atomic_rmw_xchg(&mut self, arg: MemArg) -> Self::Output {
2699 self.emit_atomic_rmw(&arg, RmwOp::Xchg, OperandSize::S64, None)
2700 }
2701
2702 fn visit_i32_atomic_rmw8_and_u(&mut self, arg: MemArg) -> Self::Output {
2703 self.emit_atomic_rmw(
2704 &arg,
2705 RmwOp::And,
2706 OperandSize::S8,
2707 Some(Extend::<Zero>::I32Extend8),
2708 )
2709 }
2710
2711 fn visit_i32_atomic_rmw16_and_u(&mut self, arg: MemArg) -> Self::Output {
2712 self.emit_atomic_rmw(
2713 &arg,
2714 RmwOp::And,
2715 OperandSize::S16,
2716 Some(Extend::<Zero>::I32Extend16),
2717 )
2718 }
2719
2720 fn visit_i32_atomic_rmw_and(&mut self, arg: MemArg) -> Self::Output {
2721 self.emit_atomic_rmw(&arg, RmwOp::And, OperandSize::S32, None)
2722 }
2723
2724 fn visit_i64_atomic_rmw8_and_u(&mut self, arg: MemArg) -> Self::Output {
2725 self.emit_atomic_rmw(
2726 &arg,
2727 RmwOp::And,
2728 OperandSize::S8,
2729 Some(Extend::<Zero>::I64Extend8),
2730 )
2731 }
2732
2733 fn visit_i64_atomic_rmw16_and_u(&mut self, arg: MemArg) -> Self::Output {
2734 self.emit_atomic_rmw(
2735 &arg,
2736 RmwOp::And,
2737 OperandSize::S16,
2738 Some(Extend::<Zero>::I64Extend16),
2739 )
2740 }
2741
2742 fn visit_i64_atomic_rmw32_and_u(&mut self, arg: MemArg) -> Self::Output {
2743 self.emit_atomic_rmw(
2744 &arg,
2745 RmwOp::And,
2746 OperandSize::S32,
2747 Some(Extend::<Zero>::I64Extend32),
2748 )
2749 }
2750
2751 fn visit_i64_atomic_rmw_and(&mut self, arg: MemArg) -> Self::Output {
2752 self.emit_atomic_rmw(&arg, RmwOp::And, OperandSize::S64, None)
2753 }
2754
2755 fn visit_i32_atomic_rmw8_or_u(&mut self, arg: MemArg) -> Self::Output {
2756 self.emit_atomic_rmw(
2757 &arg,
2758 RmwOp::Or,
2759 OperandSize::S8,
2760 Some(Extend::<Zero>::I32Extend8),
2761 )
2762 }
2763
2764 fn visit_i32_atomic_rmw16_or_u(&mut self, arg: MemArg) -> Self::Output {
2765 self.emit_atomic_rmw(
2766 &arg,
2767 RmwOp::Or,
2768 OperandSize::S16,
2769 Some(Extend::<Zero>::I32Extend16),
2770 )
2771 }
2772
2773 fn visit_i32_atomic_rmw_or(&mut self, arg: MemArg) -> Self::Output {
2774 self.emit_atomic_rmw(&arg, RmwOp::Or, OperandSize::S32, None)
2775 }
2776
2777 fn visit_i64_atomic_rmw8_or_u(&mut self, arg: MemArg) -> Self::Output {
2778 self.emit_atomic_rmw(
2779 &arg,
2780 RmwOp::Or,
2781 OperandSize::S8,
2782 Some(Extend::<Zero>::I64Extend8),
2783 )
2784 }
2785
2786 fn visit_i64_atomic_rmw16_or_u(&mut self, arg: MemArg) -> Self::Output {
2787 self.emit_atomic_rmw(
2788 &arg,
2789 RmwOp::Or,
2790 OperandSize::S16,
2791 Some(Extend::<Zero>::I64Extend16),
2792 )
2793 }
2794
2795 fn visit_i64_atomic_rmw32_or_u(&mut self, arg: MemArg) -> Self::Output {
2796 self.emit_atomic_rmw(
2797 &arg,
2798 RmwOp::Or,
2799 OperandSize::S32,
2800 Some(Extend::<Zero>::I64Extend32),
2801 )
2802 }
2803
2804 fn visit_i64_atomic_rmw_or(&mut self, arg: MemArg) -> Self::Output {
2805 self.emit_atomic_rmw(&arg, RmwOp::Or, OperandSize::S64, None)
2806 }
2807
2808 fn visit_i32_atomic_rmw8_xor_u(&mut self, arg: MemArg) -> Self::Output {
2809 self.emit_atomic_rmw(
2810 &arg,
2811 RmwOp::Xor,
2812 OperandSize::S8,
2813 Some(Extend::<Zero>::I32Extend8),
2814 )
2815 }
2816
2817 fn visit_i32_atomic_rmw16_xor_u(&mut self, arg: MemArg) -> Self::Output {
2818 self.emit_atomic_rmw(
2819 &arg,
2820 RmwOp::Xor,
2821 OperandSize::S16,
2822 Some(Extend::<Zero>::I32Extend16),
2823 )
2824 }
2825
2826 fn visit_i32_atomic_rmw_xor(&mut self, arg: MemArg) -> Self::Output {
2827 self.emit_atomic_rmw(&arg, RmwOp::Xor, OperandSize::S32, None)
2828 }
2829
2830 fn visit_i64_atomic_rmw8_xor_u(&mut self, arg: MemArg) -> Self::Output {
2831 self.emit_atomic_rmw(
2832 &arg,
2833 RmwOp::Xor,
2834 OperandSize::S8,
2835 Some(Extend::<Zero>::I64Extend8),
2836 )
2837 }
2838
2839 fn visit_i64_atomic_rmw16_xor_u(&mut self, arg: MemArg) -> Self::Output {
2840 self.emit_atomic_rmw(
2841 &arg,
2842 RmwOp::Xor,
2843 OperandSize::S16,
2844 Some(Extend::<Zero>::I64Extend16),
2845 )
2846 }
2847
2848 fn visit_i64_atomic_rmw32_xor_u(&mut self, arg: MemArg) -> Self::Output {
2849 self.emit_atomic_rmw(
2850 &arg,
2851 RmwOp::Xor,
2852 OperandSize::S32,
2853 Some(Extend::<Zero>::I64Extend32),
2854 )
2855 }
2856
2857 fn visit_i64_atomic_rmw_xor(&mut self, arg: MemArg) -> Self::Output {
2858 self.emit_atomic_rmw(&arg, RmwOp::Xor, OperandSize::S64, None)
2859 }
2860
2861 fn visit_i32_atomic_rmw8_cmpxchg_u(&mut self, arg: MemArg) -> Self::Output {
2862 self.emit_atomic_cmpxchg(&arg, OperandSize::S8, Some(Extend::I32Extend8))
2863 }
2864
2865 fn visit_i32_atomic_rmw16_cmpxchg_u(&mut self, arg: MemArg) -> Self::Output {
2866 self.emit_atomic_cmpxchg(&arg, OperandSize::S16, Some(Extend::I32Extend16))
2867 }
2868
2869 fn visit_i32_atomic_rmw_cmpxchg(&mut self, arg: MemArg) -> Self::Output {
2870 self.emit_atomic_cmpxchg(&arg, OperandSize::S32, None)
2871 }
2872
2873 fn visit_i64_atomic_rmw8_cmpxchg_u(&mut self, arg: MemArg) -> Self::Output {
2874 self.emit_atomic_cmpxchg(&arg, OperandSize::S8, Some(Extend::I64Extend8))
2875 }
2876
2877 fn visit_i64_atomic_rmw16_cmpxchg_u(&mut self, arg: MemArg) -> Self::Output {
2878 self.emit_atomic_cmpxchg(&arg, OperandSize::S16, Some(Extend::I64Extend16))
2879 }
2880
2881 fn visit_i64_atomic_rmw32_cmpxchg_u(&mut self, arg: MemArg) -> Self::Output {
2882 self.emit_atomic_cmpxchg(&arg, OperandSize::S32, Some(Extend::I64Extend32))
2883 }
2884
2885 fn visit_i64_atomic_rmw_cmpxchg(&mut self, arg: MemArg) -> Self::Output {
2886 self.emit_atomic_cmpxchg(&arg, OperandSize::S64, None)
2887 }
2888
2889 fn visit_memory_atomic_wait32(&mut self, arg: MemArg) -> Self::Output {
2890 self.emit_atomic_wait(&arg, AtomicWaitKind::Wait32)
2891 }
2892
2893 fn visit_memory_atomic_wait64(&mut self, arg: MemArg) -> Self::Output {
2894 self.emit_atomic_wait(&arg, AtomicWaitKind::Wait64)
2895 }
2896
2897 fn visit_memory_atomic_notify(&mut self, arg: MemArg) -> Self::Output {
2898 self.emit_atomic_notify(&arg)
2899 }
2900
2901 fn visit_atomic_fence(&mut self) -> Self::Output {
2902 self.masm.fence()
2903 }
2904
2905 wasmparser::for_each_visit_operator!(def_unsupported);
2906}
2907
2908impl<'a, 'translation, 'data, M> VisitSimdOperator<'a>
2909 for CodeGen<'a, 'translation, 'data, M, Emission>
2910where
2911 M: MacroAssembler,
2912{
2913 fn visit_v128_const(&mut self, val: V128) -> Self::Output {
2914 self.context.stack.push(Val::v128(val.i128()));
2915 Ok(())
2916 }
2917
2918 fn visit_v128_load(&mut self, memarg: MemArg) -> Self::Output {
2919 self.emit_wasm_load(
2920 &memarg,
2921 WasmValType::V128,
2922 LoadKind::Operand(OperandSize::S128),
2923 )
2924 }
2925
2926 fn visit_v128_store(&mut self, memarg: MemArg) -> Self::Output {
2927 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S128))
2928 }
2929
2930 fn visit_v128_load8x8_s(&mut self, memarg: MemArg) -> Self::Output {
2931 self.emit_wasm_load(
2932 &memarg,
2933 WasmValType::V128,
2934 LoadKind::VectorExtend(V128LoadExtendKind::E8x8S),
2935 )
2936 }
2937
2938 fn visit_v128_load8x8_u(&mut self, memarg: MemArg) -> Self::Output {
2939 self.emit_wasm_load(
2940 &memarg,
2941 WasmValType::V128,
2942 LoadKind::VectorExtend(V128LoadExtendKind::E8x8U),
2943 )
2944 }
2945
2946 fn visit_v128_load16x4_s(&mut self, memarg: MemArg) -> Self::Output {
2947 self.emit_wasm_load(
2948 &memarg,
2949 WasmValType::V128,
2950 LoadKind::VectorExtend(V128LoadExtendKind::E16x4S),
2951 )
2952 }
2953
2954 fn visit_v128_load16x4_u(&mut self, memarg: MemArg) -> Self::Output {
2955 self.emit_wasm_load(
2956 &memarg,
2957 WasmValType::V128,
2958 LoadKind::VectorExtend(V128LoadExtendKind::E16x4U),
2959 )
2960 }
2961
2962 fn visit_v128_load32x2_s(&mut self, memarg: MemArg) -> Self::Output {
2963 self.emit_wasm_load(
2964 &memarg,
2965 WasmValType::V128,
2966 LoadKind::VectorExtend(V128LoadExtendKind::E32x2S),
2967 )
2968 }
2969
2970 fn visit_v128_load32x2_u(&mut self, memarg: MemArg) -> Self::Output {
2971 self.emit_wasm_load(
2972 &memarg,
2973 WasmValType::V128,
2974 LoadKind::VectorExtend(V128LoadExtendKind::E32x2U),
2975 )
2976 }
2977
2978 fn visit_v128_load8_splat(&mut self, memarg: MemArg) -> Self::Output {
2979 self.emit_wasm_load(
2980 &memarg,
2981 WasmValType::V128,
2982 LoadKind::Splat(SplatLoadKind::S8),
2983 )
2984 }
2985
2986 fn visit_v128_load16_splat(&mut self, memarg: MemArg) -> Self::Output {
2987 self.emit_wasm_load(
2988 &memarg,
2989 WasmValType::V128,
2990 LoadKind::Splat(SplatLoadKind::S16),
2991 )
2992 }
2993
2994 fn visit_v128_load32_splat(&mut self, memarg: MemArg) -> Self::Output {
2995 self.emit_wasm_load(
2996 &memarg,
2997 WasmValType::V128,
2998 LoadKind::Splat(SplatLoadKind::S32),
2999 )
3000 }
3001
3002 fn visit_v128_load64_splat(&mut self, memarg: MemArg) -> Self::Output {
3003 self.emit_wasm_load(
3004 &memarg,
3005 WasmValType::V128,
3006 LoadKind::Splat(SplatLoadKind::S64),
3007 )
3008 }
3009
3010 fn visit_i8x16_splat(&mut self) -> Self::Output {
3011 self.masm.splat(&mut self.context, SplatKind::I8x16)
3012 }
3013
3014 fn visit_i16x8_splat(&mut self) -> Self::Output {
3015 self.masm.splat(&mut self.context, SplatKind::I16x8)
3016 }
3017
3018 fn visit_i32x4_splat(&mut self) -> Self::Output {
3019 self.masm.splat(&mut self.context, SplatKind::I32x4)
3020 }
3021
3022 fn visit_i64x2_splat(&mut self) -> Self::Output {
3023 self.masm.splat(&mut self.context, SplatKind::I64x2)
3024 }
3025
3026 fn visit_f32x4_splat(&mut self) -> Self::Output {
3027 self.masm.splat(&mut self.context, SplatKind::F32x4)
3028 }
3029
3030 fn visit_f64x2_splat(&mut self) -> Self::Output {
3031 self.masm.splat(&mut self.context, SplatKind::F64x2)
3032 }
3033
3034 fn visit_i8x16_shuffle(&mut self, lanes: [u8; 16]) -> Self::Output {
3035 let rhs = self.context.pop_to_reg(self.masm, None)?;
3036 let lhs = self.context.pop_to_reg(self.masm, None)?;
3037 self.masm
3038 .shuffle(writable!(lhs.into()), lhs.into(), rhs.into(), lanes)?;
3039 self.context.stack.push(TypedReg::v128(lhs.into()).into());
3040 self.context.free_reg(rhs);
3041 Ok(())
3042 }
3043
3044 fn visit_i8x16_swizzle(&mut self) -> Self::Output {
3045 let rhs = self.context.pop_to_reg(self.masm, None)?;
3046 let lhs = self.context.pop_to_reg(self.masm, None)?;
3047 self.masm
3048 .swizzle(writable!(lhs.into()), lhs.into(), rhs.into())?;
3049 self.context.stack.push(TypedReg::v128(lhs.into()).into());
3050 self.context.free_reg(rhs);
3051 Ok(())
3052 }
3053
3054 fn visit_i8x16_extract_lane_s(&mut self, lane: u8) -> Self::Output {
3055 self.context.extract_lane_op(
3056 self.masm,
3057 ExtractLaneKind::I8x16S,
3058 |masm, src, dst, kind| masm.extract_lane(src, dst, lane, kind),
3059 )
3060 }
3061
3062 fn visit_i8x16_extract_lane_u(&mut self, lane: u8) -> Self::Output {
3063 self.context.extract_lane_op(
3064 self.masm,
3065 ExtractLaneKind::I8x16U,
3066 |masm, src, dst, kind| masm.extract_lane(src, dst, lane, kind),
3067 )
3068 }
3069
3070 fn visit_i16x8_extract_lane_s(&mut self, lane: u8) -> Self::Output {
3071 self.context.extract_lane_op(
3072 self.masm,
3073 ExtractLaneKind::I16x8S,
3074 |masm, src, dst, kind| masm.extract_lane(src, dst, lane, kind),
3075 )
3076 }
3077
3078 fn visit_i16x8_extract_lane_u(&mut self, lane: u8) -> Self::Output {
3079 self.context.extract_lane_op(
3080 self.masm,
3081 ExtractLaneKind::I16x8U,
3082 |masm, src, dst, kind| masm.extract_lane(src, dst, lane, kind),
3083 )
3084 }
3085
3086 fn visit_i32x4_extract_lane(&mut self, lane: u8) -> Self::Output {
3087 self.context
3088 .extract_lane_op(self.masm, ExtractLaneKind::I32x4, |masm, src, dst, kind| {
3089 masm.extract_lane(src, dst, lane, kind)
3090 })
3091 }
3092
3093 fn visit_i64x2_extract_lane(&mut self, lane: u8) -> Self::Output {
3094 self.context
3095 .extract_lane_op(self.masm, ExtractLaneKind::I64x2, |masm, src, dst, kind| {
3096 masm.extract_lane(src, dst, lane, kind)
3097 })
3098 }
3099
3100 fn visit_f32x4_extract_lane(&mut self, lane: u8) -> Self::Output {
3101 self.context
3102 .extract_lane_op(self.masm, ExtractLaneKind::F32x4, |masm, src, dst, kind| {
3103 masm.extract_lane(src, dst, lane, kind)
3104 })
3105 }
3106
3107 fn visit_f64x2_extract_lane(&mut self, lane: u8) -> Self::Output {
3108 self.context
3109 .extract_lane_op(self.masm, ExtractLaneKind::F64x2, |masm, src, dst, kind| {
3110 masm.extract_lane(src, dst, lane, kind)
3111 })
3112 }
3113
3114 fn visit_i8x16_eq(&mut self) -> Self::Output {
3115 self.context
3116 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3117 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::I8x16)?;
3118 Ok(TypedReg::v128(dst))
3119 })
3120 }
3121
3122 fn visit_i16x8_eq(&mut self) -> Self::Output {
3123 self.context
3124 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3125 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::I16x8)?;
3126 Ok(TypedReg::v128(dst))
3127 })
3128 }
3129
3130 fn visit_i32x4_eq(&mut self) -> Self::Output {
3131 self.context
3132 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3133 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::I32x4)?;
3134 Ok(TypedReg::v128(dst))
3135 })
3136 }
3137
3138 fn visit_i64x2_eq(&mut self) -> Self::Output {
3139 self.context
3140 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3141 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::I64x2)?;
3142 Ok(TypedReg::v128(dst))
3143 })
3144 }
3145
3146 fn visit_f32x4_eq(&mut self) -> Self::Output {
3147 self.context
3148 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3149 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::F32x4)?;
3150 Ok(TypedReg::v128(dst))
3151 })
3152 }
3153
3154 fn visit_f64x2_eq(&mut self) -> Self::Output {
3155 self.context
3156 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3157 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::F64x2)?;
3158 Ok(TypedReg::v128(dst))
3159 })
3160 }
3161
3162 fn visit_i8x16_ne(&mut self) -> Self::Output {
3163 self.context
3164 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3165 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::I8x16)?;
3166 Ok(TypedReg::v128(dst))
3167 })
3168 }
3169
3170 fn visit_i16x8_ne(&mut self) -> Self::Output {
3171 self.context
3172 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3173 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::I16x8)?;
3174 Ok(TypedReg::v128(dst))
3175 })
3176 }
3177
3178 fn visit_i32x4_ne(&mut self) -> Self::Output {
3179 self.context
3180 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3181 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::I32x4)?;
3182 Ok(TypedReg::v128(dst))
3183 })
3184 }
3185
3186 fn visit_i64x2_ne(&mut self) -> Self::Output {
3187 self.context
3188 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3189 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::I64x2)?;
3190 Ok(TypedReg::v128(dst))
3191 })
3192 }
3193
3194 fn visit_f32x4_ne(&mut self) -> Self::Output {
3195 self.context
3196 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3197 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::F32x4)?;
3198 Ok(TypedReg::v128(dst))
3199 })
3200 }
3201
3202 fn visit_f64x2_ne(&mut self) -> Self::Output {
3203 self.context
3204 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3205 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::F64x2)?;
3206 Ok(TypedReg::v128(dst))
3207 })
3208 }
3209
3210 fn visit_i8x16_lt_s(&mut self) -> Self::Output {
3211 self.context
3212 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3213 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I8x16S)?;
3214 Ok(TypedReg::v128(dst))
3215 })
3216 }
3217
3218 fn visit_i8x16_lt_u(&mut self) -> Self::Output {
3219 self.context
3220 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3221 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I8x16U)?;
3222 Ok(TypedReg::v128(dst))
3223 })
3224 }
3225
3226 fn visit_i16x8_lt_s(&mut self) -> Self::Output {
3227 self.context
3228 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3229 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I16x8S)?;
3230 Ok(TypedReg::v128(dst))
3231 })
3232 }
3233
3234 fn visit_i16x8_lt_u(&mut self) -> Self::Output {
3235 self.context
3236 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3237 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I16x8U)?;
3238 Ok(TypedReg::v128(dst))
3239 })
3240 }
3241
3242 fn visit_i32x4_lt_s(&mut self) -> Self::Output {
3243 self.context
3244 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3245 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I32x4S)?;
3246 Ok(TypedReg::v128(dst))
3247 })
3248 }
3249
3250 fn visit_i32x4_lt_u(&mut self) -> Self::Output {
3251 self.context
3252 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3253 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I32x4U)?;
3254 Ok(TypedReg::v128(dst))
3255 })
3256 }
3257
3258 fn visit_i64x2_lt_s(&mut self) -> Self::Output {
3259 self.context
3260 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3261 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I64x2S)?;
3262 Ok(TypedReg::v128(dst))
3263 })
3264 }
3265
3266 fn visit_f32x4_lt(&mut self) -> Self::Output {
3267 self.context
3268 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3269 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::F32x4)?;
3270 Ok(TypedReg::v128(dst))
3271 })
3272 }
3273
3274 fn visit_f64x2_lt(&mut self) -> Self::Output {
3275 self.context
3276 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3277 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::F64x2)?;
3278 Ok(TypedReg::v128(dst))
3279 })
3280 }
3281
3282 fn visit_i8x16_le_s(&mut self) -> Self::Output {
3283 self.context
3284 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3285 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I8x16S)?;
3286 Ok(TypedReg::v128(dst))
3287 })
3288 }
3289
3290 fn visit_i8x16_le_u(&mut self) -> Self::Output {
3291 self.context
3292 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3293 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I8x16U)?;
3294 Ok(TypedReg::v128(dst))
3295 })
3296 }
3297
3298 fn visit_i16x8_le_s(&mut self) -> Self::Output {
3299 self.context
3300 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3301 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I16x8S)?;
3302 Ok(TypedReg::v128(dst))
3303 })
3304 }
3305
3306 fn visit_i16x8_le_u(&mut self) -> Self::Output {
3307 self.context
3308 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3309 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I16x8U)?;
3310 Ok(TypedReg::v128(dst))
3311 })
3312 }
3313
3314 fn visit_i32x4_le_s(&mut self) -> Self::Output {
3315 self.context
3316 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3317 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I32x4S)?;
3318 Ok(TypedReg::v128(dst))
3319 })
3320 }
3321
3322 fn visit_i32x4_le_u(&mut self) -> Self::Output {
3323 self.context
3324 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3325 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I32x4U)?;
3326 Ok(TypedReg::v128(dst))
3327 })
3328 }
3329
3330 fn visit_i64x2_le_s(&mut self) -> Self::Output {
3331 self.context
3332 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3333 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I64x2S)?;
3334 Ok(TypedReg::v128(dst))
3335 })
3336 }
3337
3338 fn visit_f32x4_le(&mut self) -> Self::Output {
3339 self.context
3340 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3341 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::F32x4)?;
3342 Ok(TypedReg::v128(dst))
3343 })
3344 }
3345
3346 fn visit_f64x2_le(&mut self) -> Self::Output {
3347 self.context
3348 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3349 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::F64x2)?;
3350 Ok(TypedReg::v128(dst))
3351 })
3352 }
3353
3354 fn visit_i8x16_gt_s(&mut self) -> Self::Output {
3355 self.context
3356 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3357 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I8x16S)?;
3358 Ok(TypedReg::v128(dst))
3359 })
3360 }
3361
3362 fn visit_i8x16_gt_u(&mut self) -> Self::Output {
3363 self.context
3364 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3365 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I8x16U)?;
3366 Ok(TypedReg::v128(dst))
3367 })
3368 }
3369
3370 fn visit_i16x8_gt_s(&mut self) -> Self::Output {
3371 self.context
3372 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3373 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I16x8S)?;
3374 Ok(TypedReg::v128(dst))
3375 })
3376 }
3377
3378 fn visit_i16x8_gt_u(&mut self) -> Self::Output {
3379 self.context
3380 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3381 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I16x8U)?;
3382 Ok(TypedReg::v128(dst))
3383 })
3384 }
3385
3386 fn visit_i32x4_gt_s(&mut self) -> Self::Output {
3387 self.context
3388 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3389 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I32x4S)?;
3390 Ok(TypedReg::v128(dst))
3391 })
3392 }
3393
3394 fn visit_i32x4_gt_u(&mut self) -> Self::Output {
3395 self.context
3396 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3397 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I32x4U)?;
3398 Ok(TypedReg::v128(dst))
3399 })
3400 }
3401
3402 fn visit_i64x2_gt_s(&mut self) -> Self::Output {
3403 self.context
3404 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3405 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I64x2S)?;
3406 Ok(TypedReg::v128(dst))
3407 })
3408 }
3409
3410 fn visit_f32x4_gt(&mut self) -> Self::Output {
3411 self.context
3412 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3413 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::F32x4)?;
3414 Ok(TypedReg::v128(dst))
3415 })
3416 }
3417
3418 fn visit_f64x2_gt(&mut self) -> Self::Output {
3419 self.context
3420 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3421 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::F64x2)?;
3422 Ok(TypedReg::v128(dst))
3423 })
3424 }
3425
3426 fn visit_i8x16_ge_s(&mut self) -> Self::Output {
3427 self.context
3428 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3429 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I8x16S)?;
3430 Ok(TypedReg::v128(dst))
3431 })
3432 }
3433
3434 fn visit_i8x16_ge_u(&mut self) -> Self::Output {
3435 self.context
3436 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3437 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I8x16U)?;
3438 Ok(TypedReg::v128(dst))
3439 })
3440 }
3441
3442 fn visit_i16x8_ge_s(&mut self) -> Self::Output {
3443 self.context
3444 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3445 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I16x8S)?;
3446 Ok(TypedReg::v128(dst))
3447 })
3448 }
3449
3450 fn visit_i16x8_ge_u(&mut self) -> Self::Output {
3451 self.context
3452 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3453 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I16x8U)?;
3454 Ok(TypedReg::v128(dst))
3455 })
3456 }
3457
3458 fn visit_i32x4_ge_s(&mut self) -> Self::Output {
3459 self.context
3460 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3461 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I32x4S)?;
3462 Ok(TypedReg::v128(dst))
3463 })
3464 }
3465
3466 fn visit_i32x4_ge_u(&mut self) -> Self::Output {
3467 self.context
3468 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3469 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I32x4U)?;
3470 Ok(TypedReg::v128(dst))
3471 })
3472 }
3473
3474 fn visit_i64x2_ge_s(&mut self) -> Self::Output {
3475 self.context
3476 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3477 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I64x2S)?;
3478 Ok(TypedReg::v128(dst))
3479 })
3480 }
3481
3482 fn visit_f32x4_ge(&mut self) -> Self::Output {
3483 self.context
3484 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3485 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::F32x4)?;
3486 Ok(TypedReg::v128(dst))
3487 })
3488 }
3489
3490 fn visit_f64x2_ge(&mut self) -> Self::Output {
3491 self.context
3492 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3493 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::F64x2)?;
3494 Ok(TypedReg::v128(dst))
3495 })
3496 }
3497
3498 fn visit_i8x16_replace_lane(&mut self, lane: u8) -> Self::Output {
3499 self.context
3500 .replace_lane_op(self.masm, ReplaceLaneKind::I8x16, |masm, src, dst, kind| {
3501 masm.replace_lane(src, dst, lane, kind)
3502 })
3503 }
3504
3505 fn visit_i16x8_replace_lane(&mut self, lane: u8) -> Self::Output {
3506 self.context
3507 .replace_lane_op(self.masm, ReplaceLaneKind::I16x8, |masm, src, dst, kind| {
3508 masm.replace_lane(src, dst, lane, kind)
3509 })
3510 }
3511
3512 fn visit_i32x4_replace_lane(&mut self, lane: u8) -> Self::Output {
3513 self.context
3514 .replace_lane_op(self.masm, ReplaceLaneKind::I32x4, |masm, src, dst, kind| {
3515 masm.replace_lane(src, dst, lane, kind)
3516 })
3517 }
3518
3519 fn visit_i64x2_replace_lane(&mut self, lane: u8) -> Self::Output {
3520 self.context
3521 .replace_lane_op(self.masm, ReplaceLaneKind::I64x2, |masm, src, dst, kind| {
3522 masm.replace_lane(src, dst, lane, kind)
3523 })
3524 }
3525
3526 fn visit_f32x4_replace_lane(&mut self, lane: u8) -> Self::Output {
3527 self.context
3528 .replace_lane_op(self.masm, ReplaceLaneKind::F32x4, |masm, src, dst, kind| {
3529 masm.replace_lane(src, dst, lane, kind)
3530 })
3531 }
3532
3533 fn visit_f64x2_replace_lane(&mut self, lane: u8) -> Self::Output {
3534 self.context
3535 .replace_lane_op(self.masm, ReplaceLaneKind::F64x2, |masm, src, dst, kind| {
3536 masm.replace_lane(src, dst, lane, kind)
3537 })
3538 }
3539
3540 fn visit_v128_not(&mut self) -> Self::Output {
3541 self.context.unop(self.masm, |masm, reg| {
3542 masm.v128_not(writable!(reg))?;
3543 Ok(TypedReg::new(WasmValType::V128, reg))
3544 })
3545 }
3546
3547 fn visit_v128_and(&mut self) -> Self::Output {
3548 self.context
3549 .binop(self.masm, OperandSize::S128, |masm, dst, src, _size| {
3550 masm.v128_and(dst, src, writable!(dst))?;
3551 Ok(TypedReg::new(WasmValType::V128, dst))
3552 })
3553 }
3554
3555 fn visit_v128_andnot(&mut self) -> Self::Output {
3556 self.context
3557 .binop(self.masm, OperandSize::S128, |masm, dst, src, _size| {
3558 masm.v128_and_not(src, dst, writable!(dst))?;
3560 Ok(TypedReg::new(WasmValType::V128, dst))
3561 })
3562 }
3563
3564 fn visit_v128_or(&mut self) -> Self::Output {
3565 self.context
3566 .binop(self.masm, OperandSize::S128, |masm, dst, src, _size| {
3567 masm.v128_or(src, dst, writable!(dst))?;
3569 Ok(TypedReg::new(WasmValType::V128, dst))
3570 })
3571 }
3572
3573 fn visit_v128_xor(&mut self) -> Self::Output {
3574 self.context
3575 .binop(self.masm, OperandSize::S128, |masm, dst, src, _size| {
3576 masm.v128_xor(src, dst, writable!(dst))?;
3578 Ok(TypedReg::new(WasmValType::V128, dst))
3579 })
3580 }
3581
3582 fn visit_v128_bitselect(&mut self) -> Self::Output {
3583 let mask = self.context.pop_to_reg(self.masm, None)?;
3584 let op2 = self.context.pop_to_reg(self.masm, None)?;
3585 let op1 = self.context.pop_to_reg(self.masm, None)?;
3586 let dst = self.context.any_fpr(self.masm)?;
3587
3588 self.masm
3590 .v128_bitselect(op1.reg, op2.reg, mask.reg, writable!(dst))?;
3591
3592 self.context
3593 .stack
3594 .push(TypedReg::new(WasmValType::V128, dst).into());
3595 self.context.free_reg(op1);
3596 self.context.free_reg(op2);
3597 self.context.free_reg(mask);
3598
3599 Ok(())
3600 }
3601
3602 fn visit_v128_any_true(&mut self) -> Self::Output {
3603 let src = self.context.pop_to_reg(self.masm, None)?;
3604 let dst = self.context.any_gpr(self.masm)?;
3605
3606 self.masm.v128_any_true(src.reg, writable!(dst))?;
3607
3608 self.context
3609 .stack
3610 .push(TypedReg::new(WasmValType::I32, dst).into());
3611 self.context.free_reg(src);
3612
3613 Ok(())
3614 }
3615
3616 fn visit_v128_load8_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3617 self.emit_wasm_load(
3618 &arg,
3619 WasmValType::V128,
3620 LoadKind::vector_lane(lane, OperandSize::S8),
3621 )
3622 }
3623
3624 fn visit_v128_load16_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3625 self.emit_wasm_load(
3626 &arg,
3627 WasmValType::V128,
3628 LoadKind::vector_lane(lane, OperandSize::S16),
3629 )
3630 }
3631
3632 fn visit_v128_load32_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3633 self.emit_wasm_load(
3634 &arg,
3635 WasmValType::V128,
3636 LoadKind::vector_lane(lane, OperandSize::S32),
3637 )
3638 }
3639
3640 fn visit_v128_load64_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3641 self.emit_wasm_load(
3642 &arg,
3643 WasmValType::V128,
3644 LoadKind::vector_lane(lane, OperandSize::S64),
3645 )
3646 }
3647
3648 fn visit_v128_store8_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3649 self.emit_wasm_store(&arg, StoreKind::vector_lane(lane, OperandSize::S8))
3650 }
3651
3652 fn visit_v128_store16_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3653 self.emit_wasm_store(&arg, StoreKind::vector_lane(lane, OperandSize::S16))
3654 }
3655
3656 fn visit_v128_store32_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3657 self.emit_wasm_store(&arg, StoreKind::vector_lane(lane, OperandSize::S32))
3658 }
3659
3660 fn visit_v128_store64_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3661 self.emit_wasm_store(&arg, StoreKind::vector_lane(lane, OperandSize::S64))
3662 }
3663
3664 fn visit_f32x4_convert_i32x4_s(&mut self) -> Self::Output {
3665 self.context.unop(self.masm, |masm, reg| {
3666 masm.v128_convert(reg, writable!(reg), V128ConvertKind::I32x4S)?;
3667 Ok(TypedReg::v128(reg))
3668 })
3669 }
3670
3671 fn visit_f32x4_convert_i32x4_u(&mut self) -> Self::Output {
3672 self.context.unop(self.masm, |masm, reg| {
3673 masm.v128_convert(reg, writable!(reg), V128ConvertKind::I32x4U)?;
3674 Ok(TypedReg::v128(reg))
3675 })
3676 }
3677
3678 fn visit_f64x2_convert_low_i32x4_s(&mut self) -> Self::Output {
3679 self.context.unop(self.masm, |masm, reg| {
3680 masm.v128_convert(reg, writable!(reg), V128ConvertKind::I32x4LowS)?;
3681 Ok(TypedReg::v128(reg))
3682 })
3683 }
3684
3685 fn visit_f64x2_convert_low_i32x4_u(&mut self) -> Self::Output {
3686 self.context.unop(self.masm, |masm, reg| {
3687 masm.v128_convert(reg, writable!(reg), V128ConvertKind::I32x4LowU)?;
3688 Ok(TypedReg::v128(reg))
3689 })
3690 }
3691
3692 fn visit_i8x16_narrow_i16x8_s(&mut self) -> Self::Output {
3693 self.context
3694 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3695 masm.v128_narrow(dst, src, writable!(dst), V128NarrowKind::I16x8S)?;
3696 Ok(TypedReg::v128(dst))
3697 })
3698 }
3699
3700 fn visit_i8x16_narrow_i16x8_u(&mut self) -> Self::Output {
3701 self.context
3702 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3703 masm.v128_narrow(dst, src, writable!(dst), V128NarrowKind::I16x8U)?;
3704 Ok(TypedReg::v128(dst))
3705 })
3706 }
3707
3708 fn visit_i16x8_narrow_i32x4_s(&mut self) -> Self::Output {
3709 self.context
3710 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3711 masm.v128_narrow(dst, src, writable!(dst), V128NarrowKind::I32x4S)?;
3712 Ok(TypedReg::v128(dst))
3713 })
3714 }
3715
3716 fn visit_i16x8_narrow_i32x4_u(&mut self) -> Self::Output {
3717 self.context
3718 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3719 masm.v128_narrow(dst, src, writable!(dst), V128NarrowKind::I32x4U)?;
3720 Ok(TypedReg::v128(dst))
3721 })
3722 }
3723
3724 fn visit_f32x4_demote_f64x2_zero(&mut self) -> Self::Output {
3725 self.context.unop(self.masm, |masm, reg| {
3726 masm.v128_demote(reg, writable!(reg))?;
3727 Ok(TypedReg::v128(reg))
3728 })
3729 }
3730
3731 fn visit_f64x2_promote_low_f32x4(&mut self) -> Self::Output {
3732 self.context.unop(self.masm, |masm, reg| {
3733 masm.v128_promote(reg, writable!(reg))?;
3734 Ok(TypedReg::v128(reg))
3735 })
3736 }
3737
3738 fn visit_i16x8_extend_low_i8x16_s(&mut self) -> Self::Output {
3739 self.context.unop(self.masm, |masm, reg| {
3740 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI8x16S)?;
3741 Ok(TypedReg::v128(reg))
3742 })
3743 }
3744
3745 fn visit_i16x8_extend_high_i8x16_s(&mut self) -> Self::Output {
3746 self.context.unop(self.masm, |masm, reg| {
3747 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI8x16S)?;
3748 Ok(TypedReg::v128(reg))
3749 })
3750 }
3751
3752 fn visit_i16x8_extend_low_i8x16_u(&mut self) -> Self::Output {
3753 self.context.unop(self.masm, |masm, reg| {
3754 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI8x16U)?;
3755 Ok(TypedReg::v128(reg))
3756 })
3757 }
3758
3759 fn visit_i16x8_extend_high_i8x16_u(&mut self) -> Self::Output {
3760 self.context.unop(self.masm, |masm, reg| {
3761 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI8x16U)?;
3762 Ok(TypedReg::v128(reg))
3763 })
3764 }
3765
3766 fn visit_i32x4_extend_low_i16x8_s(&mut self) -> Self::Output {
3767 self.context.unop(self.masm, |masm, reg| {
3768 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI16x8S)?;
3769 Ok(TypedReg::v128(reg))
3770 })
3771 }
3772
3773 fn visit_i32x4_extend_high_i16x8_s(&mut self) -> Self::Output {
3774 self.context.unop(self.masm, |masm, reg| {
3775 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI16x8S)?;
3776 Ok(TypedReg::v128(reg))
3777 })
3778 }
3779
3780 fn visit_i32x4_extend_low_i16x8_u(&mut self) -> Self::Output {
3781 self.context.unop(self.masm, |masm, reg| {
3782 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI16x8U)?;
3783 Ok(TypedReg::v128(reg))
3784 })
3785 }
3786
3787 fn visit_i32x4_extend_high_i16x8_u(&mut self) -> Self::Output {
3788 self.context.unop(self.masm, |masm, reg| {
3789 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI16x8U)?;
3790 Ok(TypedReg::v128(reg))
3791 })
3792 }
3793
3794 fn visit_i64x2_extend_low_i32x4_s(&mut self) -> Self::Output {
3795 self.context.unop(self.masm, |masm, reg| {
3796 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI32x4S)?;
3797 Ok(TypedReg::v128(reg))
3798 })
3799 }
3800
3801 fn visit_i64x2_extend_high_i32x4_s(&mut self) -> Self::Output {
3802 self.context.unop(self.masm, |masm, reg| {
3803 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI32x4S)?;
3804 Ok(TypedReg::v128(reg))
3805 })
3806 }
3807
3808 fn visit_i64x2_extend_low_i32x4_u(&mut self) -> Self::Output {
3809 self.context.unop(self.masm, |masm, reg| {
3810 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI32x4U)?;
3811 Ok(TypedReg::v128(reg))
3812 })
3813 }
3814
3815 fn visit_i64x2_extend_high_i32x4_u(&mut self) -> Self::Output {
3816 self.context.unop(self.masm, |masm, reg| {
3817 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI32x4U)?;
3818 Ok(TypedReg::v128(reg))
3819 })
3820 }
3821
3822 fn visit_i8x16_add(&mut self) -> Self::Output {
3823 self.context
3824 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3825 masm.v128_add(dst, src, writable!(dst), V128AddKind::I8x16)?;
3826 Ok(TypedReg::new(WasmValType::V128, dst))
3827 })
3828 }
3829
3830 fn visit_i16x8_add(&mut self) -> Self::Output {
3831 self.context
3832 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3833 masm.v128_add(dst, src, writable!(dst), V128AddKind::I16x8)?;
3834 Ok(TypedReg::new(WasmValType::V128, dst))
3835 })
3836 }
3837
3838 fn visit_i32x4_add(&mut self) -> Self::Output {
3839 self.context
3840 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3841 masm.v128_add(dst, src, writable!(dst), V128AddKind::I32x4)?;
3842 Ok(TypedReg::new(WasmValType::V128, dst))
3843 })
3844 }
3845
3846 fn visit_i64x2_add(&mut self) -> Self::Output {
3847 self.context
3848 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3849 masm.v128_add(dst, src, writable!(dst), V128AddKind::I64x2)?;
3850 Ok(TypedReg::new(WasmValType::V128, dst))
3851 })
3852 }
3853
3854 fn visit_i8x16_sub(&mut self) -> Self::Output {
3855 self.context
3856 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3857 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I8x16)?;
3858 Ok(TypedReg::new(WasmValType::V128, dst))
3859 })
3860 }
3861
3862 fn visit_i16x8_sub(&mut self) -> Self::Output {
3863 self.context
3864 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3865 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I16x8)?;
3866 Ok(TypedReg::new(WasmValType::V128, dst))
3867 })
3868 }
3869
3870 fn visit_i32x4_sub(&mut self) -> Self::Output {
3871 self.context
3872 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3873 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I32x4)?;
3874 Ok(TypedReg::new(WasmValType::V128, dst))
3875 })
3876 }
3877
3878 fn visit_i64x2_sub(&mut self) -> Self::Output {
3879 self.context
3880 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3881 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I64x2)?;
3882 Ok(TypedReg::new(WasmValType::V128, dst))
3883 })
3884 }
3885
3886 fn visit_i16x8_mul(&mut self) -> Self::Output {
3887 self.masm.v128_mul(&mut self.context, V128MulKind::I16x8)
3888 }
3889
3890 fn visit_i32x4_mul(&mut self) -> Self::Output {
3891 self.masm.v128_mul(&mut self.context, V128MulKind::I32x4)
3892 }
3893
3894 fn visit_i64x2_mul(&mut self) -> Self::Output {
3895 self.masm.v128_mul(&mut self.context, V128MulKind::I64x2)
3896 }
3897
3898 fn visit_i8x16_add_sat_s(&mut self) -> Self::Output {
3899 self.context
3900 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3901 masm.v128_add(dst, src, writable!(dst), V128AddKind::I8x16SatS)?;
3902 Ok(TypedReg::new(WasmValType::V128, dst))
3903 })
3904 }
3905
3906 fn visit_i16x8_add_sat_s(&mut self) -> Self::Output {
3907 self.context
3908 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3909 masm.v128_add(dst, src, writable!(dst), V128AddKind::I16x8SatS)?;
3910 Ok(TypedReg::new(WasmValType::V128, dst))
3911 })
3912 }
3913
3914 fn visit_i8x16_add_sat_u(&mut self) -> Self::Output {
3915 self.context
3916 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3917 masm.v128_add(dst, src, writable!(dst), V128AddKind::I8x16SatU)?;
3918 Ok(TypedReg::new(WasmValType::V128, dst))
3919 })
3920 }
3921
3922 fn visit_i16x8_add_sat_u(&mut self) -> Self::Output {
3923 self.context
3924 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3925 masm.v128_add(dst, src, writable!(dst), V128AddKind::I16x8SatU)?;
3926 Ok(TypedReg::new(WasmValType::V128, dst))
3927 })
3928 }
3929
3930 fn visit_i8x16_sub_sat_s(&mut self) -> Self::Output {
3931 self.context
3932 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3933 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I8x16SatS)?;
3934 Ok(TypedReg::new(WasmValType::V128, dst))
3935 })
3936 }
3937
3938 fn visit_i16x8_sub_sat_s(&mut self) -> Self::Output {
3939 self.context
3940 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3941 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I16x8SatS)?;
3942 Ok(TypedReg::new(WasmValType::V128, dst))
3943 })
3944 }
3945
3946 fn visit_i8x16_sub_sat_u(&mut self) -> Self::Output {
3947 self.context
3948 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3949 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I8x16SatU)?;
3950 Ok(TypedReg::new(WasmValType::V128, dst))
3951 })
3952 }
3953
3954 fn visit_i16x8_sub_sat_u(&mut self) -> Self::Output {
3955 self.context
3956 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3957 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I16x8SatU)?;
3958 Ok(TypedReg::new(WasmValType::V128, dst))
3959 })
3960 }
3961
3962 fn visit_i8x16_abs(&mut self) -> Self::Output {
3963 self.context.unop(self.masm, |masm, reg| {
3964 masm.v128_abs(reg, writable!(reg), V128AbsKind::I8x16)?;
3965 Ok(TypedReg::new(WasmValType::V128, reg))
3966 })
3967 }
3968
3969 fn visit_i16x8_abs(&mut self) -> Self::Output {
3970 self.context.unop(self.masm, |masm, reg| {
3971 masm.v128_abs(reg, writable!(reg), V128AbsKind::I16x8)?;
3972 Ok(TypedReg::new(WasmValType::V128, reg))
3973 })
3974 }
3975
3976 fn visit_i32x4_abs(&mut self) -> Self::Output {
3977 self.context.unop(self.masm, |masm, reg| {
3978 masm.v128_abs(reg, writable!(reg), V128AbsKind::I32x4)?;
3979 Ok(TypedReg::new(WasmValType::V128, reg))
3980 })
3981 }
3982
3983 fn visit_i64x2_abs(&mut self) -> Self::Output {
3984 self.context.unop(self.masm, |masm, reg| {
3985 masm.v128_abs(reg, writable!(reg), V128AbsKind::I64x2)?;
3986 Ok(TypedReg::new(WasmValType::V128, reg))
3987 })
3988 }
3989
3990 fn visit_f32x4_abs(&mut self) -> Self::Output {
3991 self.context.unop(self.masm, |masm, reg| {
3992 masm.v128_abs(reg, writable!(reg), V128AbsKind::F32x4)?;
3993 Ok(TypedReg::new(WasmValType::V128, reg))
3994 })
3995 }
3996
3997 fn visit_f64x2_abs(&mut self) -> Self::Output {
3998 self.context.unop(self.masm, |masm, reg| {
3999 masm.v128_abs(reg, writable!(reg), V128AbsKind::F64x2)?;
4000 Ok(TypedReg::new(WasmValType::V128, reg))
4001 })
4002 }
4003
4004 fn visit_i8x16_neg(&mut self) -> Self::Output {
4005 self.context.unop(self.masm, |masm, op| {
4006 masm.v128_neg(writable!(op), V128NegKind::I8x16)?;
4007 Ok(TypedReg::new(WasmValType::V128, op))
4008 })
4009 }
4010
4011 fn visit_i16x8_neg(&mut self) -> Self::Output {
4012 self.context.unop(self.masm, |masm, op| {
4013 masm.v128_neg(writable!(op), V128NegKind::I16x8)?;
4014 Ok(TypedReg::new(WasmValType::V128, op))
4015 })
4016 }
4017
4018 fn visit_i32x4_neg(&mut self) -> Self::Output {
4019 self.context.unop(self.masm, |masm, op| {
4020 masm.v128_neg(writable!(op), V128NegKind::I32x4)?;
4021 Ok(TypedReg::new(WasmValType::V128, op))
4022 })
4023 }
4024
4025 fn visit_i64x2_neg(&mut self) -> Self::Output {
4026 self.context.unop(self.masm, |masm, op| {
4027 masm.v128_neg(writable!(op), V128NegKind::I64x2)?;
4028 Ok(TypedReg::new(WasmValType::V128, op))
4029 })
4030 }
4031
4032 fn visit_i8x16_shl(&mut self) -> Self::Output {
4033 self.masm
4034 .v128_shift(&mut self.context, OperandSize::S8, ShiftKind::Shl)
4035 }
4036
4037 fn visit_i16x8_shl(&mut self) -> Self::Output {
4038 self.masm
4039 .v128_shift(&mut self.context, OperandSize::S16, ShiftKind::Shl)
4040 }
4041
4042 fn visit_i32x4_shl(&mut self) -> Self::Output {
4043 self.masm
4044 .v128_shift(&mut self.context, OperandSize::S32, ShiftKind::Shl)
4045 }
4046
4047 fn visit_i64x2_shl(&mut self) -> Self::Output {
4048 self.masm
4049 .v128_shift(&mut self.context, OperandSize::S64, ShiftKind::Shl)
4050 }
4051
4052 fn visit_i8x16_shr_u(&mut self) -> Self::Output {
4053 self.masm
4054 .v128_shift(&mut self.context, OperandSize::S8, ShiftKind::ShrU)
4055 }
4056
4057 fn visit_i16x8_shr_u(&mut self) -> Self::Output {
4058 self.masm
4059 .v128_shift(&mut self.context, OperandSize::S16, ShiftKind::ShrU)
4060 }
4061
4062 fn visit_i32x4_shr_u(&mut self) -> Self::Output {
4063 self.masm
4064 .v128_shift(&mut self.context, OperandSize::S32, ShiftKind::ShrU)
4065 }
4066
4067 fn visit_i64x2_shr_u(&mut self) -> Self::Output {
4068 self.masm
4069 .v128_shift(&mut self.context, OperandSize::S64, ShiftKind::ShrU)
4070 }
4071
4072 fn visit_i8x16_shr_s(&mut self) -> Self::Output {
4073 self.masm
4074 .v128_shift(&mut self.context, OperandSize::S8, ShiftKind::ShrS)
4075 }
4076
4077 fn visit_i16x8_shr_s(&mut self) -> Self::Output {
4078 self.masm
4079 .v128_shift(&mut self.context, OperandSize::S16, ShiftKind::ShrS)
4080 }
4081
4082 fn visit_i32x4_shr_s(&mut self) -> Self::Output {
4083 self.masm
4084 .v128_shift(&mut self.context, OperandSize::S32, ShiftKind::ShrS)
4085 }
4086
4087 fn visit_i64x2_shr_s(&mut self) -> Self::Output {
4088 self.masm
4089 .v128_shift(&mut self.context, OperandSize::S64, ShiftKind::ShrS)
4090 }
4091
4092 fn visit_i16x8_q15mulr_sat_s(&mut self) -> Self::Output {
4093 self.context
4094 .binop(self.masm, OperandSize::S16, |masm, dst, src, size| {
4095 masm.v128_q15mulr_sat_s(dst, src, writable!(dst), size)?;
4096 Ok(TypedReg::v128(dst))
4097 })
4098 }
4099
4100 fn visit_i8x16_min_s(&mut self) -> Self::Output {
4101 self.context
4102 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
4103 masm.v128_min(src, dst, writable!(dst), V128MinKind::I8x16S)?;
4104 Ok(TypedReg::v128(dst))
4105 })
4106 }
4107
4108 fn visit_i8x16_all_true(&mut self) -> Self::Output {
4109 self.context.v128_all_true_op(self.masm, |masm, src, dst| {
4110 masm.v128_all_true(src, writable!(dst), OperandSize::S8)
4111 })
4112 }
4113
4114 fn visit_i16x8_all_true(&mut self) -> Self::Output {
4115 self.context.v128_all_true_op(self.masm, |masm, src, dst| {
4116 masm.v128_all_true(src, writable!(dst), OperandSize::S16)
4117 })
4118 }
4119
4120 fn visit_i32x4_all_true(&mut self) -> Self::Output {
4121 self.context.v128_all_true_op(self.masm, |masm, src, dst| {
4122 masm.v128_all_true(src, writable!(dst), OperandSize::S32)
4123 })
4124 }
4125
4126 fn visit_i64x2_all_true(&mut self) -> Self::Output {
4127 self.context.v128_all_true_op(self.masm, |masm, src, dst| {
4128 masm.v128_all_true(src, writable!(dst), OperandSize::S64)
4129 })
4130 }
4131
4132 fn visit_i8x16_bitmask(&mut self) -> Self::Output {
4133 self.context.v128_bitmask_op(self.masm, |masm, src, dst| {
4134 masm.v128_bitmask(src, writable!(dst), OperandSize::S8)
4135 })
4136 }
4137
4138 fn visit_i16x8_bitmask(&mut self) -> Self::Output {
4139 self.context.v128_bitmask_op(self.masm, |masm, src, dst| {
4140 masm.v128_bitmask(src, writable!(dst), OperandSize::S16)
4141 })
4142 }
4143
4144 fn visit_i32x4_bitmask(&mut self) -> Self::Output {
4145 self.context.v128_bitmask_op(self.masm, |masm, src, dst| {
4146 masm.v128_bitmask(src, writable!(dst), OperandSize::S32)
4147 })
4148 }
4149
4150 fn visit_i64x2_bitmask(&mut self) -> Self::Output {
4151 self.context.v128_bitmask_op(self.masm, |masm, src, dst| {
4152 masm.v128_bitmask(src, writable!(dst), OperandSize::S64)
4153 })
4154 }
4155
4156 fn visit_i32x4_trunc_sat_f32x4_s(&mut self) -> Self::Output {
4157 self.masm
4158 .v128_trunc(&mut self.context, V128TruncKind::I32x4FromF32x4S)
4159 }
4160
4161 fn visit_i32x4_trunc_sat_f32x4_u(&mut self) -> Self::Output {
4162 self.masm
4163 .v128_trunc(&mut self.context, V128TruncKind::I32x4FromF32x4U)
4164 }
4165
4166 fn visit_i32x4_trunc_sat_f64x2_s_zero(&mut self) -> Self::Output {
4167 self.masm
4168 .v128_trunc(&mut self.context, V128TruncKind::I32x4FromF64x2SZero)
4169 }
4170
4171 fn visit_i32x4_trunc_sat_f64x2_u_zero(&mut self) -> Self::Output {
4172 self.masm
4173 .v128_trunc(&mut self.context, V128TruncKind::I32x4FromF64x2UZero)
4174 }
4175
4176 fn visit_i16x8_min_s(&mut self) -> Self::Output {
4177 self.context
4178 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
4179 masm.v128_min(src, dst, writable!(dst), V128MinKind::I16x8S)?;
4180 Ok(TypedReg::v128(dst))
4181 })
4182 }
4183
4184 fn visit_i32x4_dot_i16x8_s(&mut self) -> Self::Output {
4185 self.context
4186 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4187 masm.v128_dot(dst, src, writable!(dst))?;
4188 Ok(TypedReg::v128(dst))
4189 })
4190 }
4191
4192 fn visit_i8x16_popcnt(&mut self) -> Self::Output {
4193 self.masm.v128_popcnt(&mut self.context)
4194 }
4195
4196 fn visit_i8x16_avgr_u(&mut self) -> Self::Output {
4197 self.context
4198 .binop(self.masm, OperandSize::S8, |masm, dst, src, size| {
4199 masm.v128_avgr(dst, src, writable!(dst), size)?;
4200 Ok(TypedReg::v128(dst))
4201 })
4202 }
4203
4204 fn visit_i32x4_min_s(&mut self) -> Self::Output {
4205 self.context
4206 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4207 masm.v128_min(src, dst, writable!(dst), V128MinKind::I32x4S)?;
4208 Ok(TypedReg::v128(dst))
4209 })
4210 }
4211
4212 fn visit_i8x16_min_u(&mut self) -> Self::Output {
4213 self.context
4214 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
4215 masm.v128_min(src, dst, writable!(dst), V128MinKind::I8x16U)?;
4216 Ok(TypedReg::v128(dst))
4217 })
4218 }
4219
4220 fn visit_i16x8_avgr_u(&mut self) -> Self::Output {
4221 self.context
4222 .binop(self.masm, OperandSize::S16, |masm, dst, src, size| {
4223 masm.v128_avgr(dst, src, writable!(dst), size)?;
4224 Ok(TypedReg::v128(dst))
4225 })
4226 }
4227
4228 fn visit_i16x8_min_u(&mut self) -> Self::Output {
4229 self.context
4230 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
4231 masm.v128_min(src, dst, writable!(dst), V128MinKind::I16x8U)?;
4232 Ok(TypedReg::v128(dst))
4233 })
4234 }
4235
4236 fn visit_i32x4_min_u(&mut self) -> Self::Output {
4237 self.context
4238 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4239 masm.v128_min(src, dst, writable!(dst), V128MinKind::I32x4U)?;
4240 Ok(TypedReg::v128(dst))
4241 })
4242 }
4243
4244 fn visit_i8x16_max_s(&mut self) -> Self::Output {
4245 self.context
4246 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
4247 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I8x16S)?;
4248 Ok(TypedReg::v128(dst))
4249 })
4250 }
4251
4252 fn visit_i16x8_max_s(&mut self) -> Self::Output {
4253 self.context
4254 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
4255 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I16x8S)?;
4256 Ok(TypedReg::v128(dst))
4257 })
4258 }
4259
4260 fn visit_i32x4_max_s(&mut self) -> Self::Output {
4261 self.context
4262 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4263 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I32x4S)?;
4264 Ok(TypedReg::v128(dst))
4265 })
4266 }
4267
4268 fn visit_i8x16_max_u(&mut self) -> Self::Output {
4269 self.context
4270 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
4271 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I8x16U)?;
4272 Ok(TypedReg::v128(dst))
4273 })
4274 }
4275
4276 fn visit_i16x8_max_u(&mut self) -> Self::Output {
4277 self.context
4278 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
4279 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I16x8U)?;
4280 Ok(TypedReg::v128(dst))
4281 })
4282 }
4283
4284 fn visit_i32x4_max_u(&mut self) -> Self::Output {
4285 self.context
4286 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4287 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I32x4U)?;
4288 Ok(TypedReg::v128(dst))
4289 })
4290 }
4291
4292 fn visit_i16x8_extmul_low_i8x16_s(&mut self) -> Self::Output {
4293 self.masm
4294 .v128_extmul(&mut self.context, V128ExtMulKind::LowI8x16S)
4295 }
4296
4297 fn visit_i32x4_extmul_low_i16x8_s(&mut self) -> Self::Output {
4298 self.masm
4299 .v128_extmul(&mut self.context, V128ExtMulKind::LowI16x8S)
4300 }
4301
4302 fn visit_i64x2_extmul_low_i32x4_s(&mut self) -> Self::Output {
4303 self.masm
4304 .v128_extmul(&mut self.context, V128ExtMulKind::LowI32x4S)
4305 }
4306
4307 fn visit_i16x8_extmul_low_i8x16_u(&mut self) -> Self::Output {
4308 self.masm
4309 .v128_extmul(&mut self.context, V128ExtMulKind::LowI8x16U)
4310 }
4311
4312 fn visit_i32x4_extmul_low_i16x8_u(&mut self) -> Self::Output {
4313 self.masm
4314 .v128_extmul(&mut self.context, V128ExtMulKind::LowI16x8U)
4315 }
4316
4317 fn visit_i64x2_extmul_low_i32x4_u(&mut self) -> Self::Output {
4318 self.masm
4319 .v128_extmul(&mut self.context, V128ExtMulKind::LowI32x4U)
4320 }
4321
4322 fn visit_i16x8_extmul_high_i8x16_u(&mut self) -> Self::Output {
4323 self.masm
4324 .v128_extmul(&mut self.context, V128ExtMulKind::HighI8x16U)
4325 }
4326
4327 fn visit_i32x4_extmul_high_i16x8_u(&mut self) -> Self::Output {
4328 self.masm
4329 .v128_extmul(&mut self.context, V128ExtMulKind::HighI16x8U)
4330 }
4331
4332 fn visit_i64x2_extmul_high_i32x4_u(&mut self) -> Self::Output {
4333 self.masm
4334 .v128_extmul(&mut self.context, V128ExtMulKind::HighI32x4U)
4335 }
4336
4337 fn visit_i16x8_extmul_high_i8x16_s(&mut self) -> Self::Output {
4338 self.masm
4339 .v128_extmul(&mut self.context, V128ExtMulKind::HighI8x16S)
4340 }
4341
4342 fn visit_i32x4_extmul_high_i16x8_s(&mut self) -> Self::Output {
4343 self.masm
4344 .v128_extmul(&mut self.context, V128ExtMulKind::HighI16x8S)
4345 }
4346
4347 fn visit_i64x2_extmul_high_i32x4_s(&mut self) -> Self::Output {
4348 self.masm
4349 .v128_extmul(&mut self.context, V128ExtMulKind::HighI32x4S)
4350 }
4351
4352 fn visit_i16x8_extadd_pairwise_i8x16_s(&mut self) -> Self::Output {
4353 self.context.unop(self.masm, |masm, op| {
4354 masm.v128_extadd_pairwise(op, writable!(op), V128ExtAddKind::I8x16S)?;
4355 Ok(TypedReg::v128(op))
4356 })
4357 }
4358
4359 fn visit_i16x8_extadd_pairwise_i8x16_u(&mut self) -> Self::Output {
4360 self.context.unop(self.masm, |masm, op| {
4361 masm.v128_extadd_pairwise(op, writable!(op), V128ExtAddKind::I8x16U)?;
4362 Ok(TypedReg::v128(op))
4363 })
4364 }
4365
4366 fn visit_i32x4_extadd_pairwise_i16x8_s(&mut self) -> Self::Output {
4367 self.context.unop(self.masm, |masm, op| {
4368 masm.v128_extadd_pairwise(op, writable!(op), V128ExtAddKind::I16x8S)?;
4369 Ok(TypedReg::v128(op))
4370 })
4371 }
4372
4373 fn visit_i32x4_extadd_pairwise_i16x8_u(&mut self) -> Self::Output {
4374 self.context.unop(self.masm, |masm, op| {
4375 masm.v128_extadd_pairwise(op, writable!(op), V128ExtAddKind::I16x8U)?;
4376 Ok(TypedReg::v128(op))
4377 })
4378 }
4379
4380 fn visit_f32x4_add(&mut self) -> Self::Output {
4381 self.context
4382 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4383 masm.v128_add(dst, src, writable!(dst), V128AddKind::F32x4)?;
4384 Ok(TypedReg::v128(dst))
4385 })
4386 }
4387
4388 fn visit_f64x2_add(&mut self) -> Self::Output {
4389 self.context
4390 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
4391 masm.v128_add(dst, src, writable!(dst), V128AddKind::F64x2)?;
4392 Ok(TypedReg::v128(dst))
4393 })
4394 }
4395
4396 fn visit_f32x4_sub(&mut self) -> Self::Output {
4397 self.context
4398 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4399 masm.v128_sub(dst, src, writable!(dst), V128SubKind::F32x4)?;
4400 Ok(TypedReg::v128(dst))
4401 })
4402 }
4403
4404 fn visit_f64x2_sub(&mut self) -> Self::Output {
4405 self.context
4406 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
4407 masm.v128_sub(dst, src, writable!(dst), V128SubKind::F64x2)?;
4408 Ok(TypedReg::v128(dst))
4409 })
4410 }
4411
4412 fn visit_f32x4_mul(&mut self) -> Self::Output {
4413 self.masm.v128_mul(&mut self.context, V128MulKind::F32x4)
4414 }
4415
4416 fn visit_f64x2_mul(&mut self) -> Self::Output {
4417 self.masm.v128_mul(&mut self.context, V128MulKind::F64x2)
4418 }
4419
4420 fn visit_f32x4_div(&mut self) -> Self::Output {
4421 self.context
4422 .binop(self.masm, OperandSize::S32, |masm, dst, src, size| {
4423 masm.v128_div(dst, src, writable!(dst), size)?;
4424 Ok(TypedReg::v128(dst))
4425 })
4426 }
4427
4428 fn visit_f64x2_div(&mut self) -> Self::Output {
4429 self.context
4430 .binop(self.masm, OperandSize::S64, |masm, dst, src, size| {
4431 masm.v128_div(dst, src, writable!(dst), size)?;
4432 Ok(TypedReg::v128(dst))
4433 })
4434 }
4435
4436 fn visit_f32x4_neg(&mut self) -> Self::Output {
4437 self.context.unop(self.masm, |masm, reg| {
4438 masm.v128_neg(writable!(reg), V128NegKind::F32x4)?;
4439 Ok(TypedReg::v128(reg))
4440 })
4441 }
4442
4443 fn visit_f32x4_ceil(&mut self) -> Self::Output {
4444 self.context.unop(self.masm, |masm, reg| {
4445 masm.v128_ceil(reg, writable!(reg), OperandSize::S32)?;
4446 Ok(TypedReg::v128(reg))
4447 })
4448 }
4449
4450 fn visit_f64x2_neg(&mut self) -> Self::Output {
4451 self.context.unop(self.masm, |masm, reg| {
4452 masm.v128_neg(writable!(reg), V128NegKind::F64x2)?;
4453 Ok(TypedReg::v128(reg))
4454 })
4455 }
4456
4457 fn visit_f64x2_ceil(&mut self) -> Self::Output {
4458 self.context.unop(self.masm, |masm, reg| {
4459 masm.v128_ceil(reg, writable!(reg), OperandSize::S64)?;
4460 Ok(TypedReg::v128(reg))
4461 })
4462 }
4463
4464 fn visit_f32x4_sqrt(&mut self) -> Self::Output {
4465 self.context.unop(self.masm, |masm, reg| {
4466 masm.v128_sqrt(reg, writable!(reg), OperandSize::S32)?;
4467 Ok(TypedReg::v128(reg))
4468 })
4469 }
4470
4471 fn visit_f32x4_floor(&mut self) -> Self::Output {
4472 self.context.unop(self.masm, |masm, reg| {
4473 masm.v128_floor(reg, writable!(reg), OperandSize::S32)?;
4474 Ok(TypedReg::v128(reg))
4475 })
4476 }
4477
4478 fn visit_f64x2_sqrt(&mut self) -> Self::Output {
4479 self.context.unop(self.masm, |masm, reg| {
4480 masm.v128_sqrt(reg, writable!(reg), OperandSize::S64)?;
4481 Ok(TypedReg::v128(reg))
4482 })
4483 }
4484
4485 fn visit_f64x2_floor(&mut self) -> Self::Output {
4486 self.context.unop(self.masm, |masm, reg| {
4487 masm.v128_floor(reg, writable!(reg), OperandSize::S64)?;
4488 Ok(TypedReg::v128(reg))
4489 })
4490 }
4491
4492 fn visit_f32x4_nearest(&mut self) -> Self::Output {
4493 self.context.unop(self.masm, |masm, reg| {
4494 masm.v128_nearest(reg, writable!(reg), OperandSize::S32)?;
4495 Ok(TypedReg::v128(reg))
4496 })
4497 }
4498
4499 fn visit_f64x2_nearest(&mut self) -> Self::Output {
4500 self.context.unop(self.masm, |masm, reg| {
4501 masm.v128_nearest(reg, writable!(reg), OperandSize::S64)?;
4502 Ok(TypedReg::v128(reg))
4503 })
4504 }
4505
4506 fn visit_f32x4_trunc(&mut self) -> Self::Output {
4507 self.masm
4508 .v128_trunc(&mut self.context, V128TruncKind::F32x4)
4509 }
4510
4511 fn visit_f64x2_trunc(&mut self) -> Self::Output {
4512 self.masm
4513 .v128_trunc(&mut self.context, V128TruncKind::F64x2)
4514 }
4515
4516 fn visit_v128_load32_zero(&mut self, memarg: MemArg) -> Self::Output {
4517 self.emit_wasm_load(
4518 &memarg,
4519 WasmValType::V128,
4520 LoadKind::VectorZero(OperandSize::S32),
4521 )
4522 }
4523
4524 fn visit_v128_load64_zero(&mut self, memarg: MemArg) -> Self::Output {
4525 self.emit_wasm_load(
4526 &memarg,
4527 WasmValType::V128,
4528 LoadKind::VectorZero(OperandSize::S64),
4529 )
4530 }
4531
4532 fn visit_f32x4_pmin(&mut self) -> Self::Output {
4533 self.context
4534 .binop(self.masm, OperandSize::S32, |masm, dst, src, size| {
4535 masm.v128_pmin(dst, src, writable!(dst), size)?;
4536 Ok(TypedReg::v128(dst))
4537 })
4538 }
4539
4540 fn visit_f64x2_pmin(&mut self) -> Self::Output {
4541 self.context
4542 .binop(self.masm, OperandSize::S64, |masm, dst, src, size| {
4543 masm.v128_pmin(dst, src, writable!(dst), size)?;
4544 Ok(TypedReg::v128(dst))
4545 })
4546 }
4547
4548 fn visit_f32x4_pmax(&mut self) -> Self::Output {
4549 self.context
4550 .binop(self.masm, OperandSize::S32, |masm, dst, src, size| {
4551 masm.v128_pmax(dst, src, writable!(dst), size)?;
4552 Ok(TypedReg::v128(dst))
4553 })
4554 }
4555
4556 fn visit_f64x2_pmax(&mut self) -> Self::Output {
4557 self.context
4558 .binop(self.masm, OperandSize::S64, |masm, dst, src, size| {
4559 masm.v128_pmax(dst, src, writable!(dst), size)?;
4560 Ok(TypedReg::v128(dst))
4561 })
4562 }
4563
4564 fn visit_f32x4_min(&mut self) -> Self::Output {
4565 self.context
4566 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4567 masm.v128_min(dst, src, writable!(dst), V128MinKind::F32x4)?;
4568 Ok(TypedReg::v128(dst))
4569 })
4570 }
4571
4572 fn visit_f64x2_min(&mut self) -> Self::Output {
4573 self.context
4574 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
4575 masm.v128_min(dst, src, writable!(dst), V128MinKind::F64x2)?;
4576 Ok(TypedReg::v128(dst))
4577 })
4578 }
4579
4580 fn visit_f32x4_max(&mut self) -> Self::Output {
4581 self.context
4582 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4583 masm.v128_max(dst, src, writable!(dst), V128MaxKind::F32x4)?;
4584 Ok(TypedReg::v128(dst))
4585 })
4586 }
4587
4588 fn visit_f64x2_max(&mut self) -> Self::Output {
4589 self.context
4590 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
4591 masm.v128_max(dst, src, writable!(dst), V128MaxKind::F64x2)?;
4592 Ok(TypedReg::v128(dst))
4593 })
4594 }
4595
4596 wasmparser::for_each_visit_simd_operator!(def_unsupported);
4597}
4598
4599impl<'a, 'translation, 'data, M> CodeGen<'a, 'translation, 'data, M, Emission>
4600where
4601 M: MacroAssembler,
4602{
4603 fn cmp_i32s(&mut self, kind: IntCmpKind) -> Result<()> {
4604 self.context.i32_binop(self.masm, |masm, dst, src, size| {
4605 masm.cmp_with_set(writable!(dst), src, kind, size)?;
4606 Ok(TypedReg::i32(dst))
4607 })
4608 }
4609
4610 fn cmp_i64s(&mut self, kind: IntCmpKind) -> Result<()> {
4611 self.context
4612 .i64_binop(self.masm, move |masm, dst, src, size| {
4613 masm.cmp_with_set(writable!(dst), src, kind, size)?;
4614 Ok(TypedReg::i32(dst)) })
4616 }
4617}
4618
4619impl TryFrom<WasmValType> for OperandSize {
4620 type Error = crate::Error;
4621 fn try_from(ty: WasmValType) -> Result<OperandSize> {
4622 let ty = match ty {
4623 WasmValType::I32 | WasmValType::F32 => OperandSize::S32,
4624 WasmValType::I64 | WasmValType::F64 => OperandSize::S64,
4625 WasmValType::V128 => OperandSize::S128,
4626 WasmValType::Ref(rt) => {
4627 match rt.heap_type {
4628 WasmHeapType::Func => OperandSize::S64,
4633 WasmHeapType::Extern => OperandSize::S64,
4634 _ => bail!(CodeGenError::unsupported_wasm_type()),
4635 }
4636 }
4637 };
4638 Ok(ty)
4639 }
4640}