1use crate::*;
2use ::core::marker::PhantomData;
3
4#[derive(Default)]
5pub struct Compiler<'a, const MAX_CONTROL_FRAMES: usize, const MAX_STACK_DEPTH: usize> {
6 _marker: PhantomData<&'a ()>,
7}
8
9macro_rules! validate {
10 ($state:expr, ($($in_ty:ident)*) -> ($($out_ty:ident)*)) => {
11 $(
12 let _ = $state.pop_stack(ValType::$in_ty)?;
13 )*
14
15 $(
16 $state.push_stack(ValType::$out_ty)?;
17 )*
18 };
19}
20
21macro_rules! alignment {
22 (8) => {
23 0
24 };
25 (16) => {
26 1
27 };
28 (32) => {
29 2
30 };
31 (64) => {
32 3
33 };
34}
35
36macro_rules! instruction {
37 ($name:ident, $opcode:expr, ($($in_ty:ident)*) -> ($($out_ty:ident)*)) => {
39 fn $name(&self, state: &mut Self::State) -> Result<(), Self::Error> {
40 validate!(state, ($($in_ty)*) -> ($($out_ty)*));
41 state.instr($opcode)?;
42 Ok(())
43 }
44 };
45
46 ($name:ident, $opcode:expr, mem, $ty_align:tt, ($($in_ty:ident)*) -> ($($out_ty:ident)*)) => {
48 fn $name(&self, m: MemArg, state: &mut Self::State) -> Result<(), Self::Error> {
49 state.module().check_memory_defined()?;
50 validate!(state, ($($in_ty)*) -> ($($out_ty)*));
51 if m.align > alignment!($ty_align) {
52 return Err(ValidationError::AlignmentLargerThanType);
53 }
54
55 state.instr_mem($opcode, m)?;
56 Ok(())
57 }
58 };
59}
60
61impl<'a, const MAX_CONTROL_FRAMES: usize, const MAX_STACK_DEPTH: usize> WasmVisitor
62 for Compiler<'a, MAX_CONTROL_FRAMES, MAX_STACK_DEPTH>
63{
64 fn drop(&self, state: &mut Self::State) -> Result<(), Self::Error> {
65 let ty = state.pop_stack_t()?;
66 state.instr_imm_8(
67 DROP,
68 match ty {
69 OperandType::Unknown => ValType::I32,
70 OperandType::Known(t) => t,
71 } as u8,
72 )?;
73 Ok(())
74 }
75
76 fn select(&self, state: &mut Self::State) -> Result<(), Self::Error> {
77 let _ = state.pop_stack(ValType::I32)?;
78 let t1 = state.pop_stack_t()?;
79 let t2 = state.pop_stack(t1)?;
80 state.push_stack(t2)?;
81 state.instr_imm_8(SELECT, t2.into())?;
82 Ok(())
83 }
84
85 fn enter_block(
86 &self,
87 block_type: ResultType,
88 state: &mut Self::State,
89 ) -> Result<(), Self::Error> {
90 state.push_control(BlockKind::Block, block_type, block_type)
91 }
92
93 fn exit_block(&self, state: &mut Self::State) -> Result<(), Self::Error> {
94 let results = state.pop_control()?;
95 state.push_result_type(results)?;
96 Ok(())
97 }
98
99 fn finish(&self, state: &mut Self::State) -> Result<(), Self::Error> {
100 let ty = state.pop_control()?;
103
104 if let Some(ty) = ty.0 {
106 state.instr_imm_8(RETURN, ty.size() as u8 / 4)?;
107 } else {
108 state.instr(RETURN)?;
109 }
110
111 Ok(())
112 }
113
114 fn loop_(&self, block_type: ResultType, state: &mut Self::State) -> Result<(), Self::Error> {
115 state.push_control(BlockKind::Loop, ResultType(None), block_type)?;
116 state.set_control_target(state.pc())?;
118 Ok(())
119 }
120
121 fn if_(&self, block_type: ResultType, state: &mut Self::State) -> Result<(), Self::Error> {
122 let _ = state.pop_stack(ValType::I32)?;
123 state.instr(IF)?;
124 state.push_control(BlockKind::If, block_type, block_type)?;
125 state.write_if_else_target()?;
127 Ok(())
128 }
129
130 fn else_(&self, state: &mut Self::State) -> Result<(), Self::Error> {
131 state.instr(BR)?;
134 state.write_label_target(LabelIdx(0))?;
135
136 let (results, br_chain) = state.pop_control_and_patch_if()?;
139
140 state.push_control(BlockKind::Block, results, results)?;
142 state.set_control_target(br_chain)?;
143
144 Ok(())
145 }
146
147 fn br(&self, l: LabelIdx, state: &mut Self::State) -> Result<(), Self::Error> {
148 state.instr(BR)?;
149 let lbl_types = state.write_label_target(l)?;
150 state.pop_result_type(lbl_types)?;
151 state.mark_unreachable();
152 Ok(())
153 }
154
155 fn br_if(&self, l: LabelIdx, state: &mut Self::State) -> Result<(), Self::Error> {
156 let _ = state.pop_stack(ValType::I32)?;
157 state.instr(BR_IF)?;
158 let lbl_types = state.write_label_target(l)?;
159 state.pop_result_type(lbl_types)?;
160 state.push_result_type(lbl_types)?;
161 Ok(())
162 }
163
164 fn br_table_start(&self, len: u32, state: &mut Self::State) -> Result<(), Self::Error> {
165 let _ = state.pop_stack(ValType::I32)?;
166 state.instr_imm_8_or_16(BR_TABLE, len)?;
167 Ok(())
168 }
169
170 fn br_table_branch(&self, br: LabelIdx, state: &mut Self::State) -> Result<(), Self::Error> {
171 let case_return = state.write_label_target(br)?;
172 state.check_br_table_result(case_return)?;
173 Ok(())
174 }
175
176 fn br_table_finish(
177 &self,
178 default_: LabelIdx,
179 state: &mut Self::State,
180 ) -> Result<(), Self::Error> {
181 let def_result = state.write_label_target(default_)?;
182 state.check_and_clear_br_table_result(def_result)?;
183 state.pop_result_type(def_result)?;
184 state.mark_unreachable();
185 Ok(())
186 }
187
188 fn return_(&self, state: &mut Self::State) -> Result<(), Self::Error> {
189 let ty = state.func().return_ty;
191 if let Some(ty) = ty {
192 let _ = state.pop_stack(ty)?;
193 state.instr_imm_8(RETURN, ty.size() as u8 / 4)?;
194 } else {
195 state.instr(RETURN)?;
196 }
197
198 state.mark_unreachable();
199 Ok(())
200 }
201
202 fn call(&self, x: FuncIdx, state: &mut Self::State) -> Result<(), Self::Error> {
203 let f_ref = state
204 .module()
205 .get_func_ref(x)
206 .ok_or(ValidationError::FunctionIdxOutOfRange)?;
207
208 match f_ref {
209 Ref::Module(index) => {
210 let f = &state.module().functions[index as usize];
212 let ty = &state.module().types[f.ty.0 as usize];
213
214 for p in ty.params.iter().rev() {
215 let _ = state.pop_stack(*p)?;
216 }
217
218 for r in ty.returns.iter().rev() {
219 state.push_stack(r)?;
220 }
221
222 state.instr_imm_8(CALL, 0)?;
223 state.write_16(index)?;
224 Ok(())
225 }
226 Ref::Host { module, index } => {
227 let hm = &state.store().host_modules()[module.0 as usize];
228 let f = &hm.functions[index as usize];
229 for p in f.params().iter().rev() {
230 let _ = state.pop_stack(p)?;
231 }
232
233 if let Some(r) = f.returns().0 {
234 state.push_stack(r)?;
235 }
236
237 state.instr_imm_8(CALL_HOST, module.0)?;
238 state.write_16(index)?;
239 Ok(())
240 }
241 Ref::Extern { module, index } => {
242 let m = &state.store().modules()[module.0 as usize];
244 let f = &m.functions[index as usize];
245 let ty = &m.types[f.ty.0 as usize];
246
247 for p in ty.params.iter().rev() {
248 let _ = state.pop_stack(p)?;
249 }
250
251 for r in ty.returns.iter().rev() {
252 state.push_stack(*r)?;
253 }
254
255 state.instr_imm_8(CALL_EXTERN, module.0)?;
256 state.write_16(index)?;
257 Ok(())
258 }
259 }
260 }
261
262 fn call_indirect(&self, x: TypeIdx, state: &mut Self::State) -> Result<(), Self::Error> {
263 if state.module().table.is_none() {
264 return Err(ValidationError::TableNotDefined);
265 }
266
267 let _ = state.pop_stack(ValType::I32)?;
268 let ty = state
269 .module()
270 .types
271 .get(x.0 as usize)
272 .ok_or(ValidationError::TypeIdxOutOfRange)?;
273
274 for p in ty.params.iter().rev() {
275 let _ = state.pop_stack(p)?;
276 }
277
278 for r in &ty.returns {
279 state.push_stack(*r)?;
280 }
281
282 if x.0 > u16::MAX as u32 {
283 return Err(ValidationError::IdxTooLarge);
284 }
285
286 state.instr(CALL_INDIRECT)?;
287 state.write_16(x.0 as u16)?;
288 Ok(())
289 }
290
291 fn local_get(&self, x: LocalIdx, state: &mut Self::State) -> Result<(), Self::Error> {
292 let l = state.get_local(x)?;
293 state.push_stack(l.ty)?;
294 state.instr_imm_8(LOCAL_GET, l.ty as u8)?;
295 state.write_16(l.frame_offset as u16)?;
296 Ok(())
297 }
298
299 fn local_set(&self, x: LocalIdx, state: &mut Self::State) -> Result<(), Self::Error> {
300 let l = state.get_local(x)?;
301 let _ = state.pop_stack(l.ty)?;
302 state.instr_imm_8(LOCAL_SET, l.ty as u8)?;
303 state.write_16(l.frame_offset as u16)?;
304 Ok(())
305 }
306
307 fn local_tee(&self, x: LocalIdx, state: &mut Self::State) -> Result<(), Self::Error> {
308 let l = state.get_local(x)?;
309 let _ = state.pop_stack(l.ty)?;
310 state.push_stack(l.ty)?;
311 state.instr_imm_8(LOCAL_TEE, l.ty as u8)?;
312 state.write_16(l.frame_offset as u16)?;
313 Ok(())
314 }
315
316 fn global_get(&self, x: GlobalIdx, state: &mut Self::State) -> Result<(), Self::Error> {
317 let g = state.get_global(x)?;
318 state.push_stack(g.ty)?;
319 match g.reference {
320 Ref::Module(idx) => {
321 state.instr_imm_8_or_16(GLOBAL_GET, idx as u32)?;
322 Ok(())
323 }
324 Ref::Extern { module, index } => {
325 state.instr_imm_8(GLOBAL_GET_EXTERN, module.0)?;
326 state.write_16(index)?;
327 Ok(())
328 }
329 Ref::Host { module, index } => {
330 state.instr_imm_8(GLOBAL_GET_HOST, module.0)?;
331 state.write_16(index)?;
332 Ok(())
333 }
334 }
335 }
336
337 fn global_set(&self, x: GlobalIdx, state: &mut Self::State) -> Result<(), Self::Error> {
338 let g = state.get_global(x)?;
339 if !g.mutable {
340 Err(ValidationError::GlobalNotMutable)
341 } else {
342 let _ = state.pop_stack(g.ty)?;
343 match g.reference {
344 Ref::Module(idx) => {
345 state.instr_imm_8_or_16(GLOBAL_SET, idx as u32)?;
346 Ok(())
347 }
348 Ref::Extern { module, index } => {
349 state.instr_imm_8(GLOBAL_SET_EXTERN, module.0)?;
350 state.write_16(index)?;
351 Ok(())
352 }
353 Ref::Host { module, index } => {
354 state.instr_imm_8(GLOBAL_SET_HOST, module.0)?;
355 state.write_16(index)?;
356 Ok(())
357 }
358 }
359 }
360 }
361
362 fn i32_reinterpret_f32(&self, state: &mut Self::State) -> Result<(), Self::Error> {
366 validate!(state, (F32) -> (I32));
367 Ok(())
368 }
369
370 fn f64_reinterpret_i64(&self, state: &mut Self::State) -> Result<(), Self::Error> {
371 validate!(state, (I64) -> (F64));
372 Ok(())
373 }
374
375 fn f32_reinterpret_i32(&self, state: &mut Self::State) -> Result<(), Self::Error> {
376 validate!(state, (I32) -> (F32));
377 Ok(())
378 }
379
380 fn i64_reinterpret_f64(&self, state: &mut Self::State) -> Result<(), Self::Error> {
381 validate!(state, (F64) -> (I64));
382 Ok(())
383 }
384}
385
386impl<'a, const MAX_CONTROL_FRAMES: usize, const MAX_STACK_DEPTH: usize> BaseVisitor
387 for Compiler<'a, MAX_CONTROL_FRAMES, MAX_STACK_DEPTH>
388{
389 type Error = ValidationError;
390 type State = TextBuilder<'a, MAX_CONTROL_FRAMES, MAX_STACK_DEPTH>;
391
392 fn unreachable(&self, state: &mut Self::State) -> Result<(), Self::Error> {
393 state.instr_imm_8(UNREACHABLE, 0)?;
394 state.mark_unreachable();
395 Ok(())
396 }
397
398 fn nop(&self, state: &mut Self::State) -> Result<(), Self::Error> {
399 let _ = state;
401 Ok(())
402 }
403
404 instruction!(i32_load, I32_LOAD, mem, 32, (I32) -> (I32));
405 instruction!(i64_load, I64_LOAD, mem, 64, (I32) -> (I64));
406 instruction!(f32_load, F32_LOAD, mem, 32, (I32) -> (F32));
407 instruction!(f64_load, F64_LOAD, mem, 64, (I32) -> (F64));
408 instruction!(i32_load8_s, I32_LOAD8_S, mem, 8, (I32) -> (I32));
409 instruction!(i32_load8_u, I32_LOAD8_U, mem, 8, (I32) -> (I32));
410 instruction!(i32_load16_s, I32_LOAD16_S, mem, 16, (I32) -> (I32));
411 instruction!(i32_load16_u, I32_LOAD16_U, mem, 16, (I32) -> (I32));
412 instruction!(i64_load8_s, I64_LOAD8_S, mem, 8, (I32) -> (I64));
413 instruction!(i64_load8_u, I64_LOAD8_U, mem, 8, (I32) -> (I64));
414 instruction!(i64_load16_s, I64_LOAD16_S, mem, 16, (I32) -> (I64));
415 instruction!(i64_load16_u, I64_LOAD16_U, mem, 16, (I32) -> (I64));
416 instruction!(i64_load32_s, I64_LOAD32_S, mem, 32, (I32) -> (I64));
417 instruction!(i64_load32_u, I64_LOAD32_U, mem, 32, (I32) -> (I64));
418
419 instruction!(i32_store, I32_STORE, mem, 32, (I32 I32) -> ());
420 instruction!(i64_store, I64_STORE, mem, 64, (I64 I32) -> ());
421 instruction!(f32_store, F32_STORE, mem, 32, (F32 I32) -> ());
422 instruction!(f64_store, F64_STORE, mem, 64, (F64 I32) -> ());
423 instruction!(i32_store8, I32_STORE8, mem, 8, (I32 I32) -> ());
424 instruction!(i32_store16, I32_STORE16, mem, 16, (I32 I32) -> ());
425 instruction!(i64_store8, I64_STORE8, mem, 8, (I64 I32) -> ());
426 instruction!(i64_store16, I64_STORE16, mem, 16, (I64 I32) -> ());
427 instruction!(i64_store32, I64_STORE32, mem, 32, (I64 I32) -> ());
428
429 fn memory_size(&self, state: &mut Self::State) -> Result<(), Self::Error> {
430 state.module().check_memory_defined()?;
431 validate!(state, () -> (I32));
432 state.instr(MEMORY_SIZE)?;
433 Ok(())
434 }
435
436 fn memory_grow(&self, state: &mut Self::State) -> Result<(), Self::Error> {
437 state.module().check_memory_defined()?;
438 validate!(state, (I32) -> (I32));
439 if state.options().allow_memory_grow {
440 state.instr(MEMORY_GROW)?;
441 Ok(())
442 } else {
443 Err(ValidationError::IllegalMemoryGrow)
444 }
445 }
446
447 fn i32_const(&self, n: i32, state: &mut Self::State) -> Result<(), Self::Error> {
448 validate!(state, () -> (I32));
449 state.instr_imm_8_or_32(I32_CONST, n as u32)?;
450 Ok(())
451 }
452
453 fn i64_const(&self, n: i64, state: &mut Self::State) -> Result<(), Self::Error> {
454 validate!(state, () -> (I64));
455 state.instr_imm_8_or_64(I64_CONST, n as u64)?;
456 Ok(())
457 }
458
459 fn f32_const(&self, z: f32, state: &mut Self::State) -> Result<(), Self::Error> {
460 validate!(state, () -> (F32));
461 state.instr(F32_CONST)?;
462 state.write_32(z.to_bits())?;
463 Ok(())
464 }
465
466 fn f64_const(&self, z: f64, state: &mut Self::State) -> Result<(), Self::Error> {
467 validate!(state, () -> (F64));
468 state.instr(F64_CONST)?;
469 state.write_64(z.to_bits())?;
470 Ok(())
471 }
472
473 instruction!(i32_eqz, I32_EQZ, (I32) -> (I32));
474 instruction!(i32_eq, I32_EQ, (I32 I32) -> (I32));
475 instruction!(i32_ne, I32_NE, (I32 I32) -> (I32));
476 instruction!(i32_lt_s, I32_LT_S, (I32 I32) -> (I32));
477 instruction!(i32_lt_u, I32_LT_U, (I32 I32) -> (I32));
478 instruction!(i32_gt_s, I32_GT_S, (I32 I32) -> (I32));
479 instruction!(i32_gt_u, I32_GT_U, (I32 I32) -> (I32));
480 instruction!(i32_le_s, I32_LE_S, (I32 I32) -> (I32));
481 instruction!(i32_le_u, I32_LE_U, (I32 I32) -> (I32));
482 instruction!(i32_ge_s, I32_GE_S, (I32 I32) -> (I32));
483 instruction!(i32_ge_u, I32_GE_U, (I32 I32) -> (I32));
484
485 instruction!(i64_eqz, I64_EQZ, (I64) -> (I32));
486 instruction!(i64_eq, I64_EQ, (I64 I64) -> (I32));
487 instruction!(i64_ne, I64_NE, (I64 I64) -> (I32));
488 instruction!(i64_lt_s, I64_LT_S, (I64 I64) -> (I32));
489 instruction!(i64_lt_u, I64_LT_U, (I64 I64) -> (I32));
490 instruction!(i64_gt_s, I64_GT_S, (I64 I64) -> (I32));
491 instruction!(i64_gt_u, I64_GT_U, (I64 I64) -> (I32));
492 instruction!(i64_le_s, I64_LE_S, (I64 I64) -> (I32));
493 instruction!(i64_le_u, I64_LE_U, (I64 I64) -> (I32));
494 instruction!(i64_ge_s, I64_GE_S, (I64 I64) -> (I32));
495 instruction!(i64_ge_u, I64_GE_U, (I64 I64) -> (I32));
496
497 instruction!(f32_eq, F32_EQ, (F32 F32) -> (I32));
498 instruction!(f32_ne, F32_NE, (F32 F32) -> (I32));
499 instruction!(f32_lt, F32_LT, (F32 F32) -> (I32));
500 instruction!(f32_gt, F32_GT, (F32 F32) -> (I32));
501 instruction!(f32_le, F32_LE, (F32 F32) -> (I32));
502 instruction!(f32_ge, F32_GE, (F32 F32) -> (I32));
503
504 instruction!(f64_eq, F64_EQ, (F64 F64) -> (I32));
505 instruction!(f64_ne, F64_NE, (F64 F64) -> (I32));
506 instruction!(f64_lt, F64_LT, (F64 F64) -> (I32));
507 instruction!(f64_gt, F64_GT, (F64 F64) -> (I32));
508 instruction!(f64_le, F64_LE, (F64 F64) -> (I32));
509 instruction!(f64_ge, F64_GE, (F64 F64) -> (I32));
510
511 instruction!(i32_clz, I32_CLZ, (I32) -> (I32));
512 instruction!(i32_ctz, I32_CTZ, (I32) -> (I32));
513 instruction!(i32_popcnt, I32_POPCNT, (I32) -> (I32));
514 instruction!(i32_add, I32_ADD, (I32 I32) -> (I32));
515 instruction!(i32_sub, I32_SUB, (I32 I32) -> (I32));
516 instruction!(i32_mul, I32_MUL, (I32 I32) -> (I32));
517 instruction!(i32_div_s, I32_DIV_S, (I32 I32) -> (I32));
518 instruction!(i32_div_u, I32_DIV_U, (I32 I32) -> (I32));
519 instruction!(i32_rem_s, I32_REM_S, (I32 I32) -> (I32));
520 instruction!(i32_rem_u, I32_REM_U, (I32 I32) -> (I32));
521 instruction!(i32_and, I32_AND, (I32 I32) -> (I32));
522 instruction!(i32_or, I32_OR, (I32 I32) -> (I32));
523 instruction!(i32_xor, I32_XOR, (I32 I32) -> (I32));
524 instruction!(i32_shl, I32_SHL, (I32 I32) -> (I32));
525 instruction!(i32_shr_s, I32_SHR_S, (I32 I32) -> (I32));
526 instruction!(i32_shr_u, I32_SHR_U, (I32 I32) -> (I32));
527 instruction!(i32_rotl, I32_ROTL, (I32 I32) -> (I32));
528 instruction!(i32_rotr, I32_ROTR, (I32 I32) -> (I32));
529
530 instruction!(i64_clz, I64_CLZ, (I64) -> (I64));
531 instruction!(i64_ctz, I64_CTZ, (I64) -> (I64));
532 instruction!(i64_popcnt, I64_POPCNT, (I64) -> (I64));
533 instruction!(i64_add, I64_ADD, (I64 I64) -> (I64));
534 instruction!(i64_sub, I64_SUB, (I64 I64) -> (I64));
535 instruction!(i64_mul, I64_MUL, (I64 I64) -> (I64));
536 instruction!(i64_div_s, I64_DIV_S, (I64 I64) -> (I64));
537 instruction!(i64_div_u, I64_DIV_U, (I64 I64) -> (I64));
538 instruction!(i64_rem_s, I64_REM_S, (I64 I64) -> (I64));
539 instruction!(i64_rem_u, I64_REM_U, (I64 I64) -> (I64));
540 instruction!(i64_and, I64_AND, (I64 I64) -> (I64));
541 instruction!(i64_or, I64_OR, (I64 I64) -> (I64));
542 instruction!(i64_xor, I64_XOR, (I64 I64) -> (I64));
543 instruction!(i64_shl, I64_SHL, (I64 I64) -> (I64));
544 instruction!(i64_shr_s, I64_SHR_S, (I64 I64) -> (I64));
545 instruction!(i64_shr_u, I64_SHR_U, (I64 I64) -> (I64));
546 instruction!(i64_rotl, I64_ROTL, (I64 I64) -> (I64));
547 instruction!(i64_rotr, I64_ROTR, (I64 I64) -> (I64));
548
549 instruction!(f32_abs, F32_ABS, (F32) -> (F32));
550 instruction!(f32_neg, F32_NEG, (F32) -> (F32));
551 instruction!(f32_ceil, F32_CEIL, (F32) -> (F32));
552 instruction!(f32_floor, F32_FLOOR, (F32) -> (F32));
553 instruction!(f32_trunc, F32_TRUNC, (F32) -> (F32));
554 instruction!(f32_nearest, F32_NEAREST, (F32) -> (F32));
555 instruction!(f32_sqrt, F32_SQRT, (F32) -> (F32));
556 instruction!(f32_add, F32_ADD, (F32 F32) -> (F32));
557 instruction!(f32_sub, F32_SUB, (F32 F32) -> (F32));
558 instruction!(f32_mul, F32_MUL, (F32 F32) -> (F32));
559 instruction!(f32_div, F32_DIV, (F32 F32) -> (F32));
560 instruction!(f32_min, F32_MIN, (F32 F32) -> (F32));
561 instruction!(f32_max, F32_MAX, (F32 F32) -> (F32));
562 instruction!(f32_copysign, F32_COPYSIGN, (F32 F32) -> (F32));
563
564 instruction!(f64_abs, F64_ABS, (F64) -> (F64));
565 instruction!(f64_neg, F64_NEG, (F64) -> (F64));
566 instruction!(f64_ceil, F64_CEIL, (F64) -> (F64));
567 instruction!(f64_floor, F64_FLOOR, (F64) -> (F64));
568 instruction!(f64_trunc, F64_TRUNC, (F64) -> (F64));
569 instruction!(f64_nearest, F64_NEAREST, (F64) -> (F64));
570 instruction!(f64_sqrt, F64_SQRT, (F64) -> (F64));
571 instruction!(f64_add, F64_ADD, (F64 F64) -> (F64));
572 instruction!(f64_sub, F64_SUB, (F64 F64) -> (F64));
573 instruction!(f64_mul, F64_MUL, (F64 F64) -> (F64));
574 instruction!(f64_div, F64_DIV, (F64 F64) -> (F64));
575 instruction!(f64_min, F64_MIN, (F64 F64) -> (F64));
576 instruction!(f64_max, F64_MAX, (F64 F64) -> (F64));
577 instruction!(f64_copysign, F64_COPYSIGN, (F64 F64) -> (F64));
578
579 instruction!(i32_wrap_i64, I32_WRAP_I64, (I64) -> (I32));
580 instruction!(i32_trunc_f32_s, I32_TRUNC_F32_S, (F32) -> (I32));
581 instruction!(i32_trunc_f32_u, I32_TRUNC_F32_U, (F32) -> (I32));
582 instruction!(i32_trunc_f64_s, I32_TRUNC_F64_S, (F64) -> (I32));
583 instruction!(i32_trunc_f64_u, I32_TRUNC_F64_U, (F64) -> (I32));
584 instruction!(i64_extend_i32_s, I64_EXTEND_I32_S, (I32) -> (I64));
585 instruction!(i64_extend_i32_u, I64_EXTEND_I32_U, (I32) -> (I64));
586 instruction!(i64_trunc_f32_s, I64_TRUNC_F32_S, (F32) -> (I64));
587 instruction!(i64_trunc_f32_u, I64_TRUNC_F32_U, (F32) -> (I64));
588 instruction!(i64_trunc_f64_s, I64_TRUNC_F64_S, (F64) -> (I64));
589 instruction!(i64_trunc_f64_u, I64_TRUNC_F64_U, (F64) -> (I64));
590 instruction!(f32_convert_i32_s, F32_CONVERT_I32_S, (I32) -> (F32));
591 instruction!(f32_convert_i32_u, F32_CONVERT_I32_U, (I32) -> (F32));
592 instruction!(f32_convert_i64_s, F32_CONVERT_I64_S, (I64) -> (F32));
593 instruction!(f32_convert_i64_u, F32_CONVERT_I64_U, (I64) -> (F32));
594 instruction!(f32_demote_f64, F32_DEMOTE_F64, (F64) -> (F32));
595 instruction!(f64_convert_i32_s, F64_CONVERT_I32_S, (I32) -> (F64));
596 instruction!(f64_convert_i32_u, F64_CONVERT_I32_U, (I32) -> (F64));
597 instruction!(f64_convert_i64_s, F64_CONVERT_I64_S, (I64) -> (F64));
598 instruction!(f64_convert_i64_u, F64_CONVERT_I64_U, (I64) -> (F64));
599 instruction!(f64_promote_f32, F64_PROMOTE_F32, (F32) -> (F64));
600}