Skip to main content

wasmer_compiler_singlepass/
machine.rs

1use crate::{
2    common_decl::*,
3    elf::{self, CompileOutput},
4    location::{Location, Reg},
5    machine_arm64::MachineARM64,
6    machine_riscv::MachineRiscv,
7    machine_x64::MachineX86_64,
8    unwind::UnwindInstructions,
9};
10
11use dynasmrt::{AssemblyOffset, DynamicLabel};
12use std::{
13    collections::{BTreeMap, HashMap},
14    fmt::Debug,
15};
16use wasmer_compiler::{
17    misc::CompiledKind,
18    types::{
19        address_map::InstructionAddressMap,
20        function::FunctionBody,
21        relocation::{Relocation, RelocationTarget},
22        section::CustomSection,
23    },
24    wasmparser::MemArg,
25};
26use wasmer_types::{
27    CompileError, FunctionIndex, FunctionType, TrapCode, TrapInformation, VMOffsets,
28    target::{Architecture, CallingConvention, Target},
29};
30pub type Label = DynamicLabel;
31pub type Offset = AssemblyOffset;
32
33#[allow(dead_code)]
34#[derive(Clone, PartialEq)]
35pub enum Value {
36    I8(i8),
37    I32(i32),
38    I64(i64),
39    F32(f32),
40    F64(f64),
41}
42
43#[macro_export]
44macro_rules! codegen_error {
45    ($($arg:tt)*) => {return Err(CompileError::Codegen(format!($($arg)*)))}
46}
47
48#[allow(unused)]
49pub trait MaybeImmediate {
50    fn imm_value(&self) -> Option<Value>;
51    fn is_imm(&self) -> bool {
52        self.imm_value().is_some()
53    }
54    fn imm_value_scalar(&self) -> Option<i64>;
55}
56
57/// A trap table for a `RunnableModuleInfo`.
58#[derive(Clone, Debug, Default)]
59pub struct TrapTable {
60    /// Mappings from offsets in generated machine code to the corresponding trap code.
61    pub offset_to_code: BTreeMap<usize, TrapCode>,
62}
63
64// all machine seems to have a page this size, so not per arch for now
65pub const NATIVE_PAGE_SIZE: usize = 4096;
66
67#[allow(dead_code)]
68pub enum UnsignedCondition {
69    Equal,
70    NotEqual,
71    Above,
72    AboveEqual,
73    Below,
74    BelowEqual,
75}
76
77#[derive(Debug, Clone)]
78pub enum AssemblyComment {
79    FunctionPrologue,
80    InitializeLocals,
81    TrapHandlersTable,
82    RedZone,
83    FunctionBody,
84}
85
86impl std::fmt::Display for AssemblyComment {
87    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88        match self {
89            AssemblyComment::FunctionPrologue => write!(f, "function prologue"),
90            AssemblyComment::InitializeLocals => write!(f, "initialize locals"),
91            AssemblyComment::TrapHandlersTable => write!(f, "trap handlers table"),
92            AssemblyComment::RedZone => write!(f, "red zone"),
93            AssemblyComment::FunctionBody => write!(f, "body"),
94        }
95    }
96}
97
98pub(crate) struct FinalizedAssembly {
99    pub(crate) body: Vec<u8>,
100    pub(crate) assembly_comments: HashMap<usize, AssemblyComment>,
101}
102
103#[allow(unused)]
104pub trait Machine {
105    type GPR: Copy + Eq + Debug + Reg;
106    type SIMD: Copy + Eq + Debug + Reg;
107    /// Get current assembler offset
108    fn assembler_get_offset(&self) -> Offset;
109    /// Get the GPR that hold vmctx
110    fn get_vmctx_reg(&self) -> Self::GPR;
111    /// Picks an unused general purpose register for local/stack/argument use.
112    ///
113    /// This method does not mark the register as used
114    fn pick_gpr(&self) -> Option<Self::GPR>;
115    /// Picks an unused general purpose register for internal temporary use.
116    ///
117    /// This method does not mark the register as used
118    fn pick_temp_gpr(&self) -> Option<Self::GPR>;
119    /// Get all used GPR
120    fn get_used_gprs(&self) -> Vec<Self::GPR>;
121    /// Get all used SIMD regs
122    fn get_used_simd(&self) -> Vec<Self::SIMD>;
123    /// Picks an unused general purpose register and mark it as used
124    fn acquire_temp_gpr(&mut self) -> Option<Self::GPR>;
125    /// Releases a temporary GPR.
126    fn release_gpr(&mut self, gpr: Self::GPR);
127    /// Specify that a given register is in use.
128    fn reserve_unused_temp_gpr(&mut self, gpr: Self::GPR) -> Self::GPR;
129    /// reserve a GPR
130    fn reserve_gpr(&mut self, gpr: Self::GPR);
131    /// Push used gpr to the stack. Return the bytes taken on the stack.
132    fn push_used_gpr(&mut self, gprs: &[Self::GPR]) -> Result<usize, CompileError>;
133    /// Pop used gpr from the stack.
134    fn pop_used_gpr(&mut self, gprs: &[Self::GPR]) -> Result<(), CompileError>;
135    /// Picks an unused SIMD register.
136    ///
137    /// This method does not mark the register as used
138    fn pick_simd(&self) -> Option<Self::SIMD>;
139    /// Picks an unused SIMD register for internal temporary use.
140    ///
141    /// This method does not mark the register as used
142    fn pick_temp_simd(&self) -> Option<Self::SIMD>;
143    /// Acquires a temporary XMM register.
144    fn acquire_temp_simd(&mut self) -> Option<Self::SIMD>;
145    /// reserve a SIMD register
146    fn reserve_simd(&mut self, simd: Self::SIMD);
147    /// Releases a temporary XMM register.
148    fn release_simd(&mut self, simd: Self::SIMD);
149    /// Push used simd regs to the stack. Return bytes taken on the stack
150    fn push_used_simd(&mut self, simds: &[Self::SIMD]) -> Result<usize, CompileError>;
151    /// Pop used simd regs to the stack
152    fn pop_used_simd(&mut self, simds: &[Self::SIMD]) -> Result<(), CompileError>;
153    /// Return a rounded stack adjustment value (must be multiple of 16bytes on ARM64 for example)
154    fn round_stack_adjust(&self, value: usize) -> usize;
155    /// Set the source location of the Wasm to the given offset.
156    fn set_srcloc(&mut self, offset: u32);
157    /// Marks each address in the code range emitted by `f` with the trap code `code`.
158    fn mark_address_range_with_trap_code(&mut self, code: TrapCode, begin: usize, end: usize);
159    /// Marks one address as trappable with trap code `code`.
160    fn mark_address_with_trap_code(&mut self, code: TrapCode);
161    /// Marks the instruction as trappable with trap code `code`. return "begin" offset
162    fn mark_instruction_with_trap_code(&mut self, code: TrapCode) -> usize;
163    /// Pushes the instruction to the address map, calculating the offset from a
164    /// provided beginning address.
165    fn mark_instruction_address_end(&mut self, begin: usize);
166    /// Insert a StackOverflow (at offset 0)
167    fn insert_stackoverflow(&mut self);
168    /// Get all current TrapInformation
169    fn collect_trap_information(&self) -> Vec<TrapInformation>;
170    // Get all instructions address map
171    fn instructions_address_map(&self) -> Vec<InstructionAddressMap>;
172    /// Memory location for a local on the stack
173    /// Like Location::Memory(GPR::RBP, -(self.stack_offset.0 as i32)) for x86_64
174    fn local_on_stack(&mut self, stack_offset: i32) -> Location<Self::GPR, Self::SIMD>;
175    /// Allocate an extra space on the stack.
176    fn extend_stack(&mut self, delta_stack_offset: u32) -> Result<(), CompileError>;
177    /// Truncate stack space by the `delta_stack_offset`.
178    fn truncate_stack(&mut self, delta_stack_offset: u32) -> Result<(), CompileError>;
179    /// Zero a location that is 32bits
180    fn zero_location(
181        &mut self,
182        size: Size,
183        location: Location<Self::GPR, Self::SIMD>,
184    ) -> Result<(), CompileError>;
185    /// GPR Reg used for local pointer on the stack
186    fn local_pointer(&self) -> Self::GPR;
187    /// push a value on the stack for a native call
188    fn move_location_for_native(
189        &mut self,
190        size: Size,
191        loc: Location<Self::GPR, Self::SIMD>,
192        dest: Location<Self::GPR, Self::SIMD>,
193    ) -> Result<(), CompileError>;
194    /// Determine whether a local should be allocated on the stack.
195    fn is_local_on_stack(&self, idx: usize) -> bool;
196    /// Determine a local's location.
197    fn get_local_location(
198        &self,
199        idx: usize,
200        callee_saved_regs_size: usize,
201    ) -> Location<Self::GPR, Self::SIMD>;
202    /// Move a local to the stack
203    /// Like emit_mov(Size::S64, location, Location::Memory(GPR::RBP, -(self.stack_offset.0 as i32)));
204    fn move_local(
205        &mut self,
206        stack_offset: i32,
207        location: Location<Self::GPR, Self::SIMD>,
208    ) -> Result<(), CompileError>;
209    /// List of register to save, depending on the CallingConvention
210    fn list_to_save(
211        &self,
212        calling_convention: CallingConvention,
213    ) -> Vec<Location<Self::GPR, Self::SIMD>>;
214    /// Get registers for first N function call parameters.
215    fn get_param_registers(&self, calling_convention: CallingConvention) -> &'static [Self::GPR];
216    /// Get param location (to build a call, using SP for stack args)
217    fn get_param_location(
218        &self,
219        idx: usize,
220        sz: Size,
221        stack_offset: &mut usize,
222        calling_convention: CallingConvention,
223    ) -> Location<Self::GPR, Self::SIMD>;
224    /// Get call param location (from a call, using FP for stack args)
225    fn get_call_param_location(
226        &self,
227        result_slots: usize,
228        idx: usize,
229        sz: Size,
230        stack_offset: &mut usize,
231        calling_convention: CallingConvention,
232    ) -> Location<Self::GPR, Self::SIMD>;
233    /// Get param location (idx must point to an argument that is passed in a GPR).
234    fn get_simple_param_location(
235        &self,
236        idx: usize,
237        calling_convention: CallingConvention,
238    ) -> Self::GPR;
239    /// Adjust GPR param for calling convention ABI purpose.
240    fn adjust_gpr_param_location(
241        &mut self,
242        register: Self::GPR,
243        size: Size,
244    ) -> Result<(), CompileError>;
245    /// Get return value location (to build a call, using SP for stack return values).
246    fn get_return_value_location(
247        &self,
248        idx: usize,
249        stack_location: &mut usize,
250        calling_convention: CallingConvention,
251    ) -> Location<Self::GPR, Self::SIMD>;
252    /// Get return value location (from a call, using FP for stack return values).
253    fn get_call_return_value_location(
254        &self,
255        idx: usize,
256        calling_convention: CallingConvention,
257    ) -> Location<Self::GPR, Self::SIMD>;
258    /// move a location to another
259    fn move_location(
260        &mut self,
261        size: Size,
262        source: Location<Self::GPR, Self::SIMD>,
263        dest: Location<Self::GPR, Self::SIMD>,
264    ) -> Result<(), CompileError>;
265    /// move a location to another, with zero or sign extension
266    fn move_location_extend(
267        &mut self,
268        size_val: Size,
269        signed: bool,
270        source: Location<Self::GPR, Self::SIMD>,
271        size_op: Size,
272        dest: Location<Self::GPR, Self::SIMD>,
273    ) -> Result<(), CompileError>;
274    /// Init the stack loc counter
275    fn init_stack_loc(
276        &mut self,
277        init_stack_loc_cnt: u64,
278        last_stack_loc: Location<Self::GPR, Self::SIMD>,
279    ) -> Result<(), CompileError>;
280    /// Restore save_area
281    fn restore_saved_area(&mut self, saved_area_offset: i32) -> Result<(), CompileError>;
282    /// Pop a location
283    fn pop_location(
284        &mut self,
285        location: Location<Self::GPR, Self::SIMD>,
286    ) -> Result<(), CompileError>;
287
288    /// Finalize the assembler
289    fn assembler_finalize(
290        self,
291        assembly_comments: HashMap<usize, AssemblyComment>,
292    ) -> Result<FinalizedAssembly, CompileError>;
293
294    /// get_offset of Assembler
295    fn get_offset(&self) -> Offset;
296
297    /// finalize a function
298    fn finalize_function(&mut self) -> Result<(), CompileError>;
299
300    /// emit native function prolog (depending on the calling Convention, like "PUSH RBP / MOV RSP, RBP")
301    fn emit_function_prolog(&mut self) -> Result<(), CompileError>;
302    /// emit native function epilog (depending on the calling Convention, like "MOV RBP, RSP / POP RBP")
303    fn emit_function_epilog(&mut self) -> Result<(), CompileError>;
304    /// Handle copy to SIMD register from ret value (if needed by the arch/calling convention)
305    fn emit_function_return_float(&mut self) -> Result<(), CompileError>;
306    /// Canonicalize a NaN (or panic if not supported)
307    fn canonicalize_nan(
308        &mut self,
309        sz: Size,
310        input: Location<Self::GPR, Self::SIMD>,
311        output: Location<Self::GPR, Self::SIMD>,
312    ) -> Result<(), CompileError>;
313
314    /// emit an Illegal Opcode, associated with a trapcode
315    fn emit_illegal_op(&mut self, trp: TrapCode) -> Result<(), CompileError>;
316    /// create a new label
317    fn get_label(&mut self) -> Label;
318    /// emit a label
319    fn emit_label(&mut self, label: Label) -> Result<(), CompileError>;
320
321    /// get the gpr used for call. like RAX on x86_64
322    fn get_gpr_for_call(&self) -> Self::GPR;
323    /// Emit a call using the value in register
324    fn emit_call_register(&mut self, register: Self::GPR) -> Result<(), CompileError>;
325    /// Emit a call to a label
326    fn emit_call_label(&mut self, label: Label) -> Result<(), CompileError>;
327    /// indirect call with trampoline
328    fn arch_emit_indirect_call_with_trampoline(
329        &mut self,
330        location: Location<Self::GPR, Self::SIMD>,
331    ) -> Result<(), CompileError>;
332    /// emit a call to a location
333    fn emit_call_location(
334        &mut self,
335        location: Location<Self::GPR, Self::SIMD>,
336    ) -> Result<(), CompileError>;
337
338    /// Emit a debug breakpoint
339    fn emit_debug_breakpoint(&mut self) -> Result<(), CompileError>;
340
341    /// Add src+dst -> dst (with or without flags)
342    fn location_add(
343        &mut self,
344        size: Size,
345        source: Location<Self::GPR, Self::SIMD>,
346        dest: Location<Self::GPR, Self::SIMD>,
347        flags: bool,
348    ) -> Result<(), CompileError>;
349
350    /// Cmp src - dst and set flags
351    fn location_cmp(
352        &mut self,
353        size: Size,
354        source: Location<Self::GPR, Self::SIMD>,
355        dest: Location<Self::GPR, Self::SIMD>,
356    ) -> Result<(), CompileError>;
357
358    /// jmp without condition
359    fn jmp_unconditional(&mut self, label: Label) -> Result<(), CompileError>;
360
361    /// jmp to label if the provided condition is true (when comparing loc_a and loc_b)
362    fn jmp_on_condition(
363        &mut self,
364        cond: UnsignedCondition,
365        size: Size,
366        loc_a: Location<Self::GPR, Self::SIMD>,
367        loc_b: Location<Self::GPR, Self::SIMD>,
368        label: Label,
369    ) -> Result<(), CompileError>;
370
371    /// jmp using a jump table at label with cond as the indice
372    fn emit_jmp_to_jumptable(
373        &mut self,
374        label: Label,
375        cond: Location<Self::GPR, Self::SIMD>,
376    ) -> Result<(), CompileError>;
377
378    /// Align for Loop (may do nothing, depending on the arch)
379    fn align_for_loop(&mut self) -> Result<(), CompileError>;
380
381    /// ret (from a Call)
382    fn emit_ret(&mut self) -> Result<(), CompileError>;
383
384    /// Stack push of a location
385    fn emit_push(
386        &mut self,
387        size: Size,
388        loc: Location<Self::GPR, Self::SIMD>,
389    ) -> Result<(), CompileError>;
390    /// Stack pop of a location
391    fn emit_pop(
392        &mut self,
393        size: Size,
394        loc: Location<Self::GPR, Self::SIMD>,
395    ) -> Result<(), CompileError>;
396    /// relaxed mov: move from anywhere to anywhere
397    fn emit_relaxed_mov(
398        &mut self,
399        sz: Size,
400        src: Location<Self::GPR, Self::SIMD>,
401        dst: Location<Self::GPR, Self::SIMD>,
402    ) -> Result<(), CompileError>;
403    /// relaxed cmp: compare from anywhere and anywhere
404    fn emit_relaxed_cmp(
405        &mut self,
406        sz: Size,
407        src: Location<Self::GPR, Self::SIMD>,
408        dst: Location<Self::GPR, Self::SIMD>,
409    ) -> Result<(), CompileError>;
410    /// Emit a memory fence. Can be nothing for x86_64 or a DMB on ARM64 for example
411    fn emit_memory_fence(&mut self) -> Result<(), CompileError>;
412    /// relaxed move with sign extension
413    fn emit_relaxed_sign_extension(
414        &mut self,
415        sz_src: Size,
416        src: Location<Self::GPR, Self::SIMD>,
417        sz_dst: Size,
418        dst: Location<Self::GPR, Self::SIMD>,
419    ) -> Result<(), CompileError>;
420    /// Multiply location with immediate
421    fn emit_imul_imm32(
422        &mut self,
423        size: Size,
424        imm32: u32,
425        gpr: Self::GPR,
426    ) -> Result<(), CompileError>;
427    /// Add with location directly from the stack
428    fn emit_binop_add32(
429        &mut self,
430        loc_a: Location<Self::GPR, Self::SIMD>,
431        loc_b: Location<Self::GPR, Self::SIMD>,
432        ret: Location<Self::GPR, Self::SIMD>,
433    ) -> Result<(), CompileError>;
434    /// Sub with location directly from the stack
435    fn emit_binop_sub32(
436        &mut self,
437        loc_a: Location<Self::GPR, Self::SIMD>,
438        loc_b: Location<Self::GPR, Self::SIMD>,
439        ret: Location<Self::GPR, Self::SIMD>,
440    ) -> Result<(), CompileError>;
441    /// Multiply with location directly from the stack
442    fn emit_binop_mul32(
443        &mut self,
444        loc_a: Location<Self::GPR, Self::SIMD>,
445        loc_b: Location<Self::GPR, Self::SIMD>,
446        ret: Location<Self::GPR, Self::SIMD>,
447    ) -> Result<(), CompileError>;
448    /// Unsigned Division with location directly from the stack. return the offset of the DIV opcode, to mark as trappable.
449    fn emit_binop_udiv32(
450        &mut self,
451        loc_a: Location<Self::GPR, Self::SIMD>,
452        loc_b: Location<Self::GPR, Self::SIMD>,
453        ret: Location<Self::GPR, Self::SIMD>,
454        integer_division_by_zero: Label,
455    ) -> Result<usize, CompileError>;
456    /// Signed Division with location directly from the stack. return the offset of the DIV opcode, to mark as trappable.
457    fn emit_binop_sdiv32(
458        &mut self,
459        loc_a: Location<Self::GPR, Self::SIMD>,
460        loc_b: Location<Self::GPR, Self::SIMD>,
461        ret: Location<Self::GPR, Self::SIMD>,
462        integer_division_by_zero: Label,
463        integer_overflow: Label,
464    ) -> Result<usize, CompileError>;
465    /// Unsigned Reminder (of a division) with location directly from the stack. return the offset of the DIV opcode, to mark as trappable.
466    fn emit_binop_urem32(
467        &mut self,
468        loc_a: Location<Self::GPR, Self::SIMD>,
469        loc_b: Location<Self::GPR, Self::SIMD>,
470        ret: Location<Self::GPR, Self::SIMD>,
471        integer_division_by_zero: Label,
472    ) -> Result<usize, CompileError>;
473    /// Signed Reminder (of a Division) with location directly from the stack. return the offset of the DIV opcode, to mark as trappable.
474    fn emit_binop_srem32(
475        &mut self,
476        loc_a: Location<Self::GPR, Self::SIMD>,
477        loc_b: Location<Self::GPR, Self::SIMD>,
478        ret: Location<Self::GPR, Self::SIMD>,
479        integer_division_by_zero: Label,
480    ) -> Result<usize, CompileError>;
481    /// And with location directly from the stack
482    fn emit_binop_and32(
483        &mut self,
484        loc_a: Location<Self::GPR, Self::SIMD>,
485        loc_b: Location<Self::GPR, Self::SIMD>,
486        ret: Location<Self::GPR, Self::SIMD>,
487    ) -> Result<(), CompileError>;
488    /// Or with location directly from the stack
489    fn emit_binop_or32(
490        &mut self,
491        loc_a: Location<Self::GPR, Self::SIMD>,
492        loc_b: Location<Self::GPR, Self::SIMD>,
493        ret: Location<Self::GPR, Self::SIMD>,
494    ) -> Result<(), CompileError>;
495    /// Xor with location directly from the stack
496    fn emit_binop_xor32(
497        &mut self,
498        loc_a: Location<Self::GPR, Self::SIMD>,
499        loc_b: Location<Self::GPR, Self::SIMD>,
500        ret: Location<Self::GPR, Self::SIMD>,
501    ) -> Result<(), CompileError>;
502    /// Signed Greater of Equal Compare 2 i32, result in a GPR
503    fn i32_cmp_ge_s(
504        &mut self,
505        loc_a: Location<Self::GPR, Self::SIMD>,
506        loc_b: Location<Self::GPR, Self::SIMD>,
507        ret: Location<Self::GPR, Self::SIMD>,
508    ) -> Result<(), CompileError>;
509    /// Signed Greater Than Compare 2 i32, result in a GPR
510    fn i32_cmp_gt_s(
511        &mut self,
512        loc_a: Location<Self::GPR, Self::SIMD>,
513        loc_b: Location<Self::GPR, Self::SIMD>,
514        ret: Location<Self::GPR, Self::SIMD>,
515    ) -> Result<(), CompileError>;
516    /// Signed Less of Equal Compare 2 i32, result in a GPR
517    fn i32_cmp_le_s(
518        &mut self,
519        loc_a: Location<Self::GPR, Self::SIMD>,
520        loc_b: Location<Self::GPR, Self::SIMD>,
521        ret: Location<Self::GPR, Self::SIMD>,
522    ) -> Result<(), CompileError>;
523    /// Signed Less Than Compare 2 i32, result in a GPR
524    fn i32_cmp_lt_s(
525        &mut self,
526        loc_a: Location<Self::GPR, Self::SIMD>,
527        loc_b: Location<Self::GPR, Self::SIMD>,
528        ret: Location<Self::GPR, Self::SIMD>,
529    ) -> Result<(), CompileError>;
530    /// Unsigned Greater of Equal Compare 2 i32, result in a GPR
531    fn i32_cmp_ge_u(
532        &mut self,
533        loc_a: Location<Self::GPR, Self::SIMD>,
534        loc_b: Location<Self::GPR, Self::SIMD>,
535        ret: Location<Self::GPR, Self::SIMD>,
536    ) -> Result<(), CompileError>;
537    /// Unsigned Greater Than Compare 2 i32, result in a GPR
538    fn i32_cmp_gt_u(
539        &mut self,
540        loc_a: Location<Self::GPR, Self::SIMD>,
541        loc_b: Location<Self::GPR, Self::SIMD>,
542        ret: Location<Self::GPR, Self::SIMD>,
543    ) -> Result<(), CompileError>;
544    /// Unsigned Less of Equal Compare 2 i32, result in a GPR
545    fn i32_cmp_le_u(
546        &mut self,
547        loc_a: Location<Self::GPR, Self::SIMD>,
548        loc_b: Location<Self::GPR, Self::SIMD>,
549        ret: Location<Self::GPR, Self::SIMD>,
550    ) -> Result<(), CompileError>;
551    /// Unsigned Less Than Compare 2 i32, result in a GPR
552    fn i32_cmp_lt_u(
553        &mut self,
554        loc_a: Location<Self::GPR, Self::SIMD>,
555        loc_b: Location<Self::GPR, Self::SIMD>,
556        ret: Location<Self::GPR, Self::SIMD>,
557    ) -> Result<(), CompileError>;
558    /// Not Equal Compare 2 i32, result in a GPR
559    fn i32_cmp_ne(
560        &mut self,
561        loc_a: Location<Self::GPR, Self::SIMD>,
562        loc_b: Location<Self::GPR, Self::SIMD>,
563        ret: Location<Self::GPR, Self::SIMD>,
564    ) -> Result<(), CompileError>;
565    /// Equal Compare 2 i32, result in a GPR
566    fn i32_cmp_eq(
567        &mut self,
568        loc_a: Location<Self::GPR, Self::SIMD>,
569        loc_b: Location<Self::GPR, Self::SIMD>,
570        ret: Location<Self::GPR, Self::SIMD>,
571    ) -> Result<(), CompileError>;
572    /// Count Leading 0 bit of an i32
573    fn i32_clz(
574        &mut self,
575        loc: Location<Self::GPR, Self::SIMD>,
576        ret: Location<Self::GPR, Self::SIMD>,
577    ) -> Result<(), CompileError>;
578    /// Count Trailing 0 bit of an i32
579    fn i32_ctz(
580        &mut self,
581        loc: Location<Self::GPR, Self::SIMD>,
582        ret: Location<Self::GPR, Self::SIMD>,
583    ) -> Result<(), CompileError>;
584    /// Count the number of 1 bit of an i32
585    fn i32_popcnt(
586        &mut self,
587        loc: Location<Self::GPR, Self::SIMD>,
588        ret: Location<Self::GPR, Self::SIMD>,
589    ) -> Result<(), CompileError>;
590    /// i32 Logical Shift Left
591    fn i32_shl(
592        &mut self,
593        loc_a: Location<Self::GPR, Self::SIMD>,
594        loc_b: Location<Self::GPR, Self::SIMD>,
595        ret: Location<Self::GPR, Self::SIMD>,
596    ) -> Result<(), CompileError>;
597    /// i32 Logical Shift Right
598    fn i32_shr(
599        &mut self,
600        loc_a: Location<Self::GPR, Self::SIMD>,
601        loc_b: Location<Self::GPR, Self::SIMD>,
602        ret: Location<Self::GPR, Self::SIMD>,
603    ) -> Result<(), CompileError>;
604    /// i32 Arithmetic Shift Right
605    fn i32_sar(
606        &mut self,
607        loc_a: Location<Self::GPR, Self::SIMD>,
608        loc_b: Location<Self::GPR, Self::SIMD>,
609        ret: Location<Self::GPR, Self::SIMD>,
610    ) -> Result<(), CompileError>;
611    /// i32 Roll Left
612    fn i32_rol(
613        &mut self,
614        loc_a: Location<Self::GPR, Self::SIMD>,
615        loc_b: Location<Self::GPR, Self::SIMD>,
616        ret: Location<Self::GPR, Self::SIMD>,
617    ) -> Result<(), CompileError>;
618    /// i32 Roll Right
619    fn i32_ror(
620        &mut self,
621        loc_a: Location<Self::GPR, Self::SIMD>,
622        loc_b: Location<Self::GPR, Self::SIMD>,
623        ret: Location<Self::GPR, Self::SIMD>,
624    ) -> Result<(), CompileError>;
625    /// i32 load
626    #[allow(clippy::too_many_arguments)]
627    fn i32_load(
628        &mut self,
629        addr: Location<Self::GPR, Self::SIMD>,
630        memarg: &MemArg,
631        ret: Location<Self::GPR, Self::SIMD>,
632        need_check: bool,
633        imported_memories: bool,
634        offset: i32,
635        heap_access_oob: Label,
636        unaligned_atomic: Label,
637    ) -> Result<(), CompileError>;
638    /// i32 load of an unsigned 8bits
639    #[allow(clippy::too_many_arguments)]
640    fn i32_load_8u(
641        &mut self,
642        addr: Location<Self::GPR, Self::SIMD>,
643        memarg: &MemArg,
644        ret: Location<Self::GPR, Self::SIMD>,
645        need_check: bool,
646        imported_memories: bool,
647        offset: i32,
648        heap_access_oob: Label,
649        unaligned_atomic: Label,
650    ) -> Result<(), CompileError>;
651    /// i32 load of an signed 8bits
652    #[allow(clippy::too_many_arguments)]
653    fn i32_load_8s(
654        &mut self,
655        addr: Location<Self::GPR, Self::SIMD>,
656        memarg: &MemArg,
657        ret: Location<Self::GPR, Self::SIMD>,
658        need_check: bool,
659        imported_memories: bool,
660        offset: i32,
661        heap_access_oob: Label,
662        unaligned_atomic: Label,
663    ) -> Result<(), CompileError>;
664    /// i32 load of an unsigned 16bits
665    #[allow(clippy::too_many_arguments)]
666    fn i32_load_16u(
667        &mut self,
668        addr: Location<Self::GPR, Self::SIMD>,
669        memarg: &MemArg,
670        ret: Location<Self::GPR, Self::SIMD>,
671        need_check: bool,
672        imported_memories: bool,
673        offset: i32,
674        heap_access_oob: Label,
675        unaligned_atomic: Label,
676    ) -> Result<(), CompileError>;
677    /// i32 load of an signed 16bits
678    #[allow(clippy::too_many_arguments)]
679    fn i32_load_16s(
680        &mut self,
681        addr: Location<Self::GPR, Self::SIMD>,
682        memarg: &MemArg,
683        ret: Location<Self::GPR, Self::SIMD>,
684        need_check: bool,
685        imported_memories: bool,
686        offset: i32,
687        heap_access_oob: Label,
688        unaligned_atomic: Label,
689    ) -> Result<(), CompileError>;
690    /// i32 atomic load
691    #[allow(clippy::too_many_arguments)]
692    fn i32_atomic_load(
693        &mut self,
694        addr: Location<Self::GPR, Self::SIMD>,
695        memarg: &MemArg,
696        ret: Location<Self::GPR, Self::SIMD>,
697        need_check: bool,
698        imported_memories: bool,
699        offset: i32,
700        heap_access_oob: Label,
701        unaligned_atomic: Label,
702    ) -> Result<(), CompileError>;
703    /// i32 atomic load of an unsigned 8bits
704    #[allow(clippy::too_many_arguments)]
705    fn i32_atomic_load_8u(
706        &mut self,
707        addr: Location<Self::GPR, Self::SIMD>,
708        memarg: &MemArg,
709        ret: Location<Self::GPR, Self::SIMD>,
710        need_check: bool,
711        imported_memories: bool,
712        offset: i32,
713        heap_access_oob: Label,
714        unaligned_atomic: Label,
715    ) -> Result<(), CompileError>;
716    /// i32 atomic load of an unsigned 16bits
717    #[allow(clippy::too_many_arguments)]
718    fn i32_atomic_load_16u(
719        &mut self,
720        addr: Location<Self::GPR, Self::SIMD>,
721        memarg: &MemArg,
722        ret: Location<Self::GPR, Self::SIMD>,
723        need_check: bool,
724        imported_memories: bool,
725        offset: i32,
726        heap_access_oob: Label,
727        unaligned_atomic: Label,
728    ) -> Result<(), CompileError>;
729    /// i32 save
730    #[allow(clippy::too_many_arguments)]
731    fn i32_save(
732        &mut self,
733        value: Location<Self::GPR, Self::SIMD>,
734        memarg: &MemArg,
735        addr: Location<Self::GPR, Self::SIMD>,
736        need_check: bool,
737        imported_memories: bool,
738        offset: i32,
739        heap_access_oob: Label,
740        unaligned_atomic: Label,
741    ) -> Result<(), CompileError>;
742    /// i32 save of the lower 8bits
743    #[allow(clippy::too_many_arguments)]
744    fn i32_save_8(
745        &mut self,
746        value: Location<Self::GPR, Self::SIMD>,
747        memarg: &MemArg,
748        addr: Location<Self::GPR, Self::SIMD>,
749        need_check: bool,
750        imported_memories: bool,
751        offset: i32,
752        heap_access_oob: Label,
753        unaligned_atomic: Label,
754    ) -> Result<(), CompileError>;
755    /// i32 save of the lower 16bits
756    #[allow(clippy::too_many_arguments)]
757    fn i32_save_16(
758        &mut self,
759        value: Location<Self::GPR, Self::SIMD>,
760        memarg: &MemArg,
761        addr: Location<Self::GPR, Self::SIMD>,
762        need_check: bool,
763        imported_memories: bool,
764        offset: i32,
765        heap_access_oob: Label,
766        unaligned_atomic: Label,
767    ) -> Result<(), CompileError>;
768    /// i32 atomic save
769    #[allow(clippy::too_many_arguments)]
770    fn i32_atomic_save(
771        &mut self,
772        value: Location<Self::GPR, Self::SIMD>,
773        memarg: &MemArg,
774        addr: Location<Self::GPR, Self::SIMD>,
775        need_check: bool,
776        imported_memories: bool,
777        offset: i32,
778        heap_access_oob: Label,
779        unaligned_atomic: Label,
780    ) -> Result<(), CompileError>;
781    /// i32 atomic save of a the lower 8bits
782    #[allow(clippy::too_many_arguments)]
783    fn i32_atomic_save_8(
784        &mut self,
785        value: Location<Self::GPR, Self::SIMD>,
786        memarg: &MemArg,
787        addr: Location<Self::GPR, Self::SIMD>,
788        need_check: bool,
789        imported_memories: bool,
790        offset: i32,
791        heap_access_oob: Label,
792        unaligned_atomic: Label,
793    ) -> Result<(), CompileError>;
794    /// i32 atomic save of a the lower 16bits
795    #[allow(clippy::too_many_arguments)]
796    fn i32_atomic_save_16(
797        &mut self,
798        value: Location<Self::GPR, Self::SIMD>,
799        memarg: &MemArg,
800        addr: Location<Self::GPR, Self::SIMD>,
801        need_check: bool,
802        imported_memories: bool,
803        offset: i32,
804        heap_access_oob: Label,
805        unaligned_atomic: Label,
806    ) -> Result<(), CompileError>;
807    /// i32 atomic Add with i32
808    #[allow(clippy::too_many_arguments)]
809    fn i32_atomic_add(
810        &mut self,
811        loc: Location<Self::GPR, Self::SIMD>,
812        target: Location<Self::GPR, Self::SIMD>,
813        memarg: &MemArg,
814        ret: Location<Self::GPR, Self::SIMD>,
815        need_check: bool,
816        imported_memories: bool,
817        offset: i32,
818        heap_access_oob: Label,
819        unaligned_atomic: Label,
820    ) -> Result<(), CompileError>;
821    /// i32 atomic Add with unsigned 8bits
822    #[allow(clippy::too_many_arguments)]
823    fn i32_atomic_add_8u(
824        &mut self,
825        loc: Location<Self::GPR, Self::SIMD>,
826        target: Location<Self::GPR, Self::SIMD>,
827        memarg: &MemArg,
828        ret: Location<Self::GPR, Self::SIMD>,
829        need_check: bool,
830        imported_memories: bool,
831        offset: i32,
832        heap_access_oob: Label,
833        unaligned_atomic: Label,
834    ) -> Result<(), CompileError>;
835    /// i32 atomic Add with unsigned 16bits
836    #[allow(clippy::too_many_arguments)]
837    fn i32_atomic_add_16u(
838        &mut self,
839        loc: Location<Self::GPR, Self::SIMD>,
840        target: Location<Self::GPR, Self::SIMD>,
841        memarg: &MemArg,
842        ret: Location<Self::GPR, Self::SIMD>,
843        need_check: bool,
844        imported_memories: bool,
845        offset: i32,
846        heap_access_oob: Label,
847        unaligned_atomic: Label,
848    ) -> Result<(), CompileError>;
849    /// i32 atomic Sub with i32
850    #[allow(clippy::too_many_arguments)]
851    fn i32_atomic_sub(
852        &mut self,
853        loc: Location<Self::GPR, Self::SIMD>,
854        target: Location<Self::GPR, Self::SIMD>,
855        memarg: &MemArg,
856        ret: Location<Self::GPR, Self::SIMD>,
857        need_check: bool,
858        imported_memories: bool,
859        offset: i32,
860        heap_access_oob: Label,
861        unaligned_atomic: Label,
862    ) -> Result<(), CompileError>;
863    /// i32 atomic Sub with unsigned 8bits
864    #[allow(clippy::too_many_arguments)]
865    fn i32_atomic_sub_8u(
866        &mut self,
867        loc: Location<Self::GPR, Self::SIMD>,
868        target: Location<Self::GPR, Self::SIMD>,
869        memarg: &MemArg,
870        ret: Location<Self::GPR, Self::SIMD>,
871        need_check: bool,
872        imported_memories: bool,
873        offset: i32,
874        heap_access_oob: Label,
875        unaligned_atomic: Label,
876    ) -> Result<(), CompileError>;
877    /// i32 atomic Sub with unsigned 16bits
878    #[allow(clippy::too_many_arguments)]
879    fn i32_atomic_sub_16u(
880        &mut self,
881        loc: Location<Self::GPR, Self::SIMD>,
882        target: Location<Self::GPR, Self::SIMD>,
883        memarg: &MemArg,
884        ret: Location<Self::GPR, Self::SIMD>,
885        need_check: bool,
886        imported_memories: bool,
887        offset: i32,
888        heap_access_oob: Label,
889        unaligned_atomic: Label,
890    ) -> Result<(), CompileError>;
891    /// i32 atomic And with i32
892    #[allow(clippy::too_many_arguments)]
893    fn i32_atomic_and(
894        &mut self,
895        loc: Location<Self::GPR, Self::SIMD>,
896        target: Location<Self::GPR, Self::SIMD>,
897        memarg: &MemArg,
898        ret: Location<Self::GPR, Self::SIMD>,
899        need_check: bool,
900        imported_memories: bool,
901        offset: i32,
902        heap_access_oob: Label,
903        unaligned_atomic: Label,
904    ) -> Result<(), CompileError>;
905    /// i32 atomic And with unsigned 8bits
906    #[allow(clippy::too_many_arguments)]
907    fn i32_atomic_and_8u(
908        &mut self,
909        loc: Location<Self::GPR, Self::SIMD>,
910        target: Location<Self::GPR, Self::SIMD>,
911        memarg: &MemArg,
912        ret: Location<Self::GPR, Self::SIMD>,
913        need_check: bool,
914        imported_memories: bool,
915        offset: i32,
916        heap_access_oob: Label,
917        unaligned_atomic: Label,
918    ) -> Result<(), CompileError>;
919    /// i32 atomic And with unsigned 16bits
920    #[allow(clippy::too_many_arguments)]
921    fn i32_atomic_and_16u(
922        &mut self,
923        loc: Location<Self::GPR, Self::SIMD>,
924        target: Location<Self::GPR, Self::SIMD>,
925        memarg: &MemArg,
926        ret: Location<Self::GPR, Self::SIMD>,
927        need_check: bool,
928        imported_memories: bool,
929        offset: i32,
930        heap_access_oob: Label,
931        unaligned_atomic: Label,
932    ) -> Result<(), CompileError>;
933    /// i32 atomic Or with i32
934    #[allow(clippy::too_many_arguments)]
935    fn i32_atomic_or(
936        &mut self,
937        loc: Location<Self::GPR, Self::SIMD>,
938        target: Location<Self::GPR, Self::SIMD>,
939        memarg: &MemArg,
940        ret: Location<Self::GPR, Self::SIMD>,
941        need_check: bool,
942        imported_memories: bool,
943        offset: i32,
944        heap_access_oob: Label,
945        unaligned_atomic: Label,
946    ) -> Result<(), CompileError>;
947    /// i32 atomic Or with unsigned 8bits
948    #[allow(clippy::too_many_arguments)]
949    fn i32_atomic_or_8u(
950        &mut self,
951        loc: Location<Self::GPR, Self::SIMD>,
952        target: Location<Self::GPR, Self::SIMD>,
953        memarg: &MemArg,
954        ret: Location<Self::GPR, Self::SIMD>,
955        need_check: bool,
956        imported_memories: bool,
957        offset: i32,
958        heap_access_oob: Label,
959        unaligned_atomic: Label,
960    ) -> Result<(), CompileError>;
961    /// i32 atomic Or with unsigned 16bits
962    #[allow(clippy::too_many_arguments)]
963    fn i32_atomic_or_16u(
964        &mut self,
965        loc: Location<Self::GPR, Self::SIMD>,
966        target: Location<Self::GPR, Self::SIMD>,
967        memarg: &MemArg,
968        ret: Location<Self::GPR, Self::SIMD>,
969        need_check: bool,
970        imported_memories: bool,
971        offset: i32,
972        heap_access_oob: Label,
973        unaligned_atomic: Label,
974    ) -> Result<(), CompileError>;
975    /// i32 atomic Xor with i32
976    #[allow(clippy::too_many_arguments)]
977    fn i32_atomic_xor(
978        &mut self,
979        loc: Location<Self::GPR, Self::SIMD>,
980        target: Location<Self::GPR, Self::SIMD>,
981        memarg: &MemArg,
982        ret: Location<Self::GPR, Self::SIMD>,
983        need_check: bool,
984        imported_memories: bool,
985        offset: i32,
986        heap_access_oob: Label,
987        unaligned_atomic: Label,
988    ) -> Result<(), CompileError>;
989    /// i32 atomic Xor with unsigned 8bits
990    #[allow(clippy::too_many_arguments)]
991    fn i32_atomic_xor_8u(
992        &mut self,
993        loc: Location<Self::GPR, Self::SIMD>,
994        target: Location<Self::GPR, Self::SIMD>,
995        memarg: &MemArg,
996        ret: Location<Self::GPR, Self::SIMD>,
997        need_check: bool,
998        imported_memories: bool,
999        offset: i32,
1000        heap_access_oob: Label,
1001        unaligned_atomic: Label,
1002    ) -> Result<(), CompileError>;
1003    /// i32 atomic Xor with unsigned 16bits
1004    #[allow(clippy::too_many_arguments)]
1005    fn i32_atomic_xor_16u(
1006        &mut self,
1007        loc: Location<Self::GPR, Self::SIMD>,
1008        target: Location<Self::GPR, Self::SIMD>,
1009        memarg: &MemArg,
1010        ret: Location<Self::GPR, Self::SIMD>,
1011        need_check: bool,
1012        imported_memories: bool,
1013        offset: i32,
1014        heap_access_oob: Label,
1015        unaligned_atomic: Label,
1016    ) -> Result<(), CompileError>;
1017    /// i32 atomic Exchange with i32
1018    #[allow(clippy::too_many_arguments)]
1019    fn i32_atomic_xchg(
1020        &mut self,
1021        loc: Location<Self::GPR, Self::SIMD>,
1022        target: Location<Self::GPR, Self::SIMD>,
1023        memarg: &MemArg,
1024        ret: Location<Self::GPR, Self::SIMD>,
1025        need_check: bool,
1026        imported_memories: bool,
1027        offset: i32,
1028        heap_access_oob: Label,
1029        unaligned_atomic: Label,
1030    ) -> Result<(), CompileError>;
1031    /// i32 atomic Exchange with u8
1032    #[allow(clippy::too_many_arguments)]
1033    fn i32_atomic_xchg_8u(
1034        &mut self,
1035        loc: Location<Self::GPR, Self::SIMD>,
1036        target: Location<Self::GPR, Self::SIMD>,
1037        memarg: &MemArg,
1038        ret: Location<Self::GPR, Self::SIMD>,
1039        need_check: bool,
1040        imported_memories: bool,
1041        offset: i32,
1042        heap_access_oob: Label,
1043        unaligned_atomic: Label,
1044    ) -> Result<(), CompileError>;
1045    /// i32 atomic Exchange with u16
1046    #[allow(clippy::too_many_arguments)]
1047    fn i32_atomic_xchg_16u(
1048        &mut self,
1049        loc: Location<Self::GPR, Self::SIMD>,
1050        target: Location<Self::GPR, Self::SIMD>,
1051        memarg: &MemArg,
1052        ret: Location<Self::GPR, Self::SIMD>,
1053        need_check: bool,
1054        imported_memories: bool,
1055        offset: i32,
1056        heap_access_oob: Label,
1057        unaligned_atomic: Label,
1058    ) -> Result<(), CompileError>;
1059    /// i32 atomic Compare and Exchange with i32
1060    #[allow(clippy::too_many_arguments)]
1061    fn i32_atomic_cmpxchg(
1062        &mut self,
1063        new: Location<Self::GPR, Self::SIMD>,
1064        cmp: Location<Self::GPR, Self::SIMD>,
1065        target: Location<Self::GPR, Self::SIMD>,
1066        memarg: &MemArg,
1067        ret: Location<Self::GPR, Self::SIMD>,
1068        need_check: bool,
1069        imported_memories: bool,
1070        offset: i32,
1071        heap_access_oob: Label,
1072        unaligned_atomic: Label,
1073    ) -> Result<(), CompileError>;
1074    /// i32 atomic Compare and Exchange with u8
1075    #[allow(clippy::too_many_arguments)]
1076    fn i32_atomic_cmpxchg_8u(
1077        &mut self,
1078        new: Location<Self::GPR, Self::SIMD>,
1079        cmp: Location<Self::GPR, Self::SIMD>,
1080        target: Location<Self::GPR, Self::SIMD>,
1081        memarg: &MemArg,
1082        ret: Location<Self::GPR, Self::SIMD>,
1083        need_check: bool,
1084        imported_memories: bool,
1085        offset: i32,
1086        heap_access_oob: Label,
1087        unaligned_atomic: Label,
1088    ) -> Result<(), CompileError>;
1089    /// i32 atomic Compare and Exchange with u16
1090    #[allow(clippy::too_many_arguments)]
1091    fn i32_atomic_cmpxchg_16u(
1092        &mut self,
1093        new: Location<Self::GPR, Self::SIMD>,
1094        cmp: Location<Self::GPR, Self::SIMD>,
1095        target: Location<Self::GPR, Self::SIMD>,
1096        memarg: &MemArg,
1097        ret: Location<Self::GPR, Self::SIMD>,
1098        need_check: bool,
1099        imported_memories: bool,
1100        offset: i32,
1101        heap_access_oob: Label,
1102        unaligned_atomic: Label,
1103    ) -> Result<(), CompileError>;
1104
1105    /// emit a move function address to GPR ready for call, using appropriate relocation
1106    fn emit_call_with_reloc(
1107        &mut self,
1108        calling_convention: CallingConvention,
1109        reloc_target: RelocationTarget,
1110    ) -> Result<Vec<Relocation>, CompileError>;
1111    /// Add with location directly from the stack
1112    fn emit_binop_add64(
1113        &mut self,
1114        loc_a: Location<Self::GPR, Self::SIMD>,
1115        loc_b: Location<Self::GPR, Self::SIMD>,
1116        ret: Location<Self::GPR, Self::SIMD>,
1117    ) -> Result<(), CompileError>;
1118    /// Sub with location directly from the stack
1119    fn emit_binop_sub64(
1120        &mut self,
1121        loc_a: Location<Self::GPR, Self::SIMD>,
1122        loc_b: Location<Self::GPR, Self::SIMD>,
1123        ret: Location<Self::GPR, Self::SIMD>,
1124    ) -> Result<(), CompileError>;
1125    /// Multiply with location directly from the stack
1126    fn emit_binop_mul64(
1127        &mut self,
1128        loc_a: Location<Self::GPR, Self::SIMD>,
1129        loc_b: Location<Self::GPR, Self::SIMD>,
1130        ret: Location<Self::GPR, Self::SIMD>,
1131    ) -> Result<(), CompileError>;
1132    /// Unsigned Division with location directly from the stack. return the offset of the DIV opcode, to mark as trappable.
1133    fn emit_binop_udiv64(
1134        &mut self,
1135        loc_a: Location<Self::GPR, Self::SIMD>,
1136        loc_b: Location<Self::GPR, Self::SIMD>,
1137        ret: Location<Self::GPR, Self::SIMD>,
1138        integer_division_by_zero: Label,
1139    ) -> Result<usize, CompileError>;
1140    /// Signed Division with location directly from the stack. return the offset of the DIV opcode, to mark as trappable.
1141    fn emit_binop_sdiv64(
1142        &mut self,
1143        loc_a: Location<Self::GPR, Self::SIMD>,
1144        loc_b: Location<Self::GPR, Self::SIMD>,
1145        ret: Location<Self::GPR, Self::SIMD>,
1146        integer_division_by_zero: Label,
1147        integer_overflow: Label,
1148    ) -> Result<usize, CompileError>;
1149    /// Unsigned Reminder (of a division) with location directly from the stack. return the offset of the DIV opcode, to mark as trappable.
1150    fn emit_binop_urem64(
1151        &mut self,
1152        loc_a: Location<Self::GPR, Self::SIMD>,
1153        loc_b: Location<Self::GPR, Self::SIMD>,
1154        ret: Location<Self::GPR, Self::SIMD>,
1155        integer_division_by_zero: Label,
1156    ) -> Result<usize, CompileError>;
1157    /// Signed Reminder (of a Division) with location directly from the stack. return the offset of the DIV opcode, to mark as trappable.
1158    fn emit_binop_srem64(
1159        &mut self,
1160        loc_a: Location<Self::GPR, Self::SIMD>,
1161        loc_b: Location<Self::GPR, Self::SIMD>,
1162        ret: Location<Self::GPR, Self::SIMD>,
1163        integer_division_by_zero: Label,
1164    ) -> Result<usize, CompileError>;
1165    /// And with location directly from the stack
1166    fn emit_binop_and64(
1167        &mut self,
1168        loc_a: Location<Self::GPR, Self::SIMD>,
1169        loc_b: Location<Self::GPR, Self::SIMD>,
1170        ret: Location<Self::GPR, Self::SIMD>,
1171    ) -> Result<(), CompileError>;
1172    /// Or with location directly from the stack
1173    fn emit_binop_or64(
1174        &mut self,
1175        loc_a: Location<Self::GPR, Self::SIMD>,
1176        loc_b: Location<Self::GPR, Self::SIMD>,
1177        ret: Location<Self::GPR, Self::SIMD>,
1178    ) -> Result<(), CompileError>;
1179    /// Xor with location directly from the stack
1180    fn emit_binop_xor64(
1181        &mut self,
1182        loc_a: Location<Self::GPR, Self::SIMD>,
1183        loc_b: Location<Self::GPR, Self::SIMD>,
1184        ret: Location<Self::GPR, Self::SIMD>,
1185    ) -> Result<(), CompileError>;
1186    /// Signed Greater of Equal Compare 2 i64, result in a GPR
1187    fn i64_cmp_ge_s(
1188        &mut self,
1189        loc_a: Location<Self::GPR, Self::SIMD>,
1190        loc_b: Location<Self::GPR, Self::SIMD>,
1191        ret: Location<Self::GPR, Self::SIMD>,
1192    ) -> Result<(), CompileError>;
1193    /// Signed Greater Than Compare 2 i64, result in a GPR
1194    fn i64_cmp_gt_s(
1195        &mut self,
1196        loc_a: Location<Self::GPR, Self::SIMD>,
1197        loc_b: Location<Self::GPR, Self::SIMD>,
1198        ret: Location<Self::GPR, Self::SIMD>,
1199    ) -> Result<(), CompileError>;
1200    /// Signed Less of Equal Compare 2 i64, result in a GPR
1201    fn i64_cmp_le_s(
1202        &mut self,
1203        loc_a: Location<Self::GPR, Self::SIMD>,
1204        loc_b: Location<Self::GPR, Self::SIMD>,
1205        ret: Location<Self::GPR, Self::SIMD>,
1206    ) -> Result<(), CompileError>;
1207    /// Signed Less Than Compare 2 i64, result in a GPR
1208    fn i64_cmp_lt_s(
1209        &mut self,
1210        loc_a: Location<Self::GPR, Self::SIMD>,
1211        loc_b: Location<Self::GPR, Self::SIMD>,
1212        ret: Location<Self::GPR, Self::SIMD>,
1213    ) -> Result<(), CompileError>;
1214    /// Unsigned Greater of Equal Compare 2 i64, result in a GPR
1215    fn i64_cmp_ge_u(
1216        &mut self,
1217        loc_a: Location<Self::GPR, Self::SIMD>,
1218        loc_b: Location<Self::GPR, Self::SIMD>,
1219        ret: Location<Self::GPR, Self::SIMD>,
1220    ) -> Result<(), CompileError>;
1221    /// Unsigned Greater Than Compare 2 i64, result in a GPR
1222    fn i64_cmp_gt_u(
1223        &mut self,
1224        loc_a: Location<Self::GPR, Self::SIMD>,
1225        loc_b: Location<Self::GPR, Self::SIMD>,
1226        ret: Location<Self::GPR, Self::SIMD>,
1227    ) -> Result<(), CompileError>;
1228    /// Unsigned Less of Equal Compare 2 i64, result in a GPR
1229    fn i64_cmp_le_u(
1230        &mut self,
1231        loc_a: Location<Self::GPR, Self::SIMD>,
1232        loc_b: Location<Self::GPR, Self::SIMD>,
1233        ret: Location<Self::GPR, Self::SIMD>,
1234    ) -> Result<(), CompileError>;
1235    /// Unsigned Less Than Compare 2 i64, result in a GPR
1236    fn i64_cmp_lt_u(
1237        &mut self,
1238        loc_a: Location<Self::GPR, Self::SIMD>,
1239        loc_b: Location<Self::GPR, Self::SIMD>,
1240        ret: Location<Self::GPR, Self::SIMD>,
1241    ) -> Result<(), CompileError>;
1242    /// Not Equal Compare 2 i64, result in a GPR
1243    fn i64_cmp_ne(
1244        &mut self,
1245        loc_a: Location<Self::GPR, Self::SIMD>,
1246        loc_b: Location<Self::GPR, Self::SIMD>,
1247        ret: Location<Self::GPR, Self::SIMD>,
1248    ) -> Result<(), CompileError>;
1249    /// Equal Compare 2 i64, result in a GPR
1250    fn i64_cmp_eq(
1251        &mut self,
1252        loc_a: Location<Self::GPR, Self::SIMD>,
1253        loc_b: Location<Self::GPR, Self::SIMD>,
1254        ret: Location<Self::GPR, Self::SIMD>,
1255    ) -> Result<(), CompileError>;
1256    /// Count Leading 0 bit of an i64
1257    fn i64_clz(
1258        &mut self,
1259        loc: Location<Self::GPR, Self::SIMD>,
1260        ret: Location<Self::GPR, Self::SIMD>,
1261    ) -> Result<(), CompileError>;
1262    /// Count Trailing 0 bit of an i64
1263    fn i64_ctz(
1264        &mut self,
1265        loc: Location<Self::GPR, Self::SIMD>,
1266        ret: Location<Self::GPR, Self::SIMD>,
1267    ) -> Result<(), CompileError>;
1268    /// Count the number of 1 bit of an i64
1269    fn i64_popcnt(
1270        &mut self,
1271        loc: Location<Self::GPR, Self::SIMD>,
1272        ret: Location<Self::GPR, Self::SIMD>,
1273    ) -> Result<(), CompileError>;
1274    /// i64 Logical Shift Left
1275    fn i64_shl(
1276        &mut self,
1277        loc_a: Location<Self::GPR, Self::SIMD>,
1278        loc_b: Location<Self::GPR, Self::SIMD>,
1279        ret: Location<Self::GPR, Self::SIMD>,
1280    ) -> Result<(), CompileError>;
1281    /// i64 Logical Shift Right
1282    fn i64_shr(
1283        &mut self,
1284        loc_a: Location<Self::GPR, Self::SIMD>,
1285        loc_b: Location<Self::GPR, Self::SIMD>,
1286        ret: Location<Self::GPR, Self::SIMD>,
1287    ) -> Result<(), CompileError>;
1288    /// i64 Arithmetic Shift Right
1289    fn i64_sar(
1290        &mut self,
1291        loc_a: Location<Self::GPR, Self::SIMD>,
1292        loc_b: Location<Self::GPR, Self::SIMD>,
1293        ret: Location<Self::GPR, Self::SIMD>,
1294    ) -> Result<(), CompileError>;
1295    /// i64 Roll Left
1296    fn i64_rol(
1297        &mut self,
1298        loc_a: Location<Self::GPR, Self::SIMD>,
1299        loc_b: Location<Self::GPR, Self::SIMD>,
1300        ret: Location<Self::GPR, Self::SIMD>,
1301    ) -> Result<(), CompileError>;
1302    /// i64 Roll Right
1303    fn i64_ror(
1304        &mut self,
1305        loc_a: Location<Self::GPR, Self::SIMD>,
1306        loc_b: Location<Self::GPR, Self::SIMD>,
1307        ret: Location<Self::GPR, Self::SIMD>,
1308    ) -> Result<(), CompileError>;
1309    /// i64 load
1310    #[allow(clippy::too_many_arguments)]
1311    fn i64_load(
1312        &mut self,
1313        addr: Location<Self::GPR, Self::SIMD>,
1314        memarg: &MemArg,
1315        ret: Location<Self::GPR, Self::SIMD>,
1316        need_check: bool,
1317        imported_memories: bool,
1318        offset: i32,
1319        heap_access_oob: Label,
1320        unaligned_atomic: Label,
1321    ) -> Result<(), CompileError>;
1322    /// i64 load of an unsigned 8bits
1323    #[allow(clippy::too_many_arguments)]
1324    fn i64_load_8u(
1325        &mut self,
1326        addr: Location<Self::GPR, Self::SIMD>,
1327        memarg: &MemArg,
1328        ret: Location<Self::GPR, Self::SIMD>,
1329        need_check: bool,
1330        imported_memories: bool,
1331        offset: i32,
1332        heap_access_oob: Label,
1333        unaligned_atomic: Label,
1334    ) -> Result<(), CompileError>;
1335    /// i64 load of an signed 8bits
1336    #[allow(clippy::too_many_arguments)]
1337    fn i64_load_8s(
1338        &mut self,
1339        addr: Location<Self::GPR, Self::SIMD>,
1340        memarg: &MemArg,
1341        ret: Location<Self::GPR, Self::SIMD>,
1342        need_check: bool,
1343        imported_memories: bool,
1344        offset: i32,
1345        heap_access_oob: Label,
1346        unaligned_atomic: Label,
1347    ) -> Result<(), CompileError>;
1348    /// i64 load of an unsigned 32bits
1349    #[allow(clippy::too_many_arguments)]
1350    fn i64_load_32u(
1351        &mut self,
1352        addr: Location<Self::GPR, Self::SIMD>,
1353        memarg: &MemArg,
1354        ret: Location<Self::GPR, Self::SIMD>,
1355        need_check: bool,
1356        imported_memories: bool,
1357        offset: i32,
1358        heap_access_oob: Label,
1359        unaligned_atomic: Label,
1360    ) -> Result<(), CompileError>;
1361    /// i64 load of an signed 32bits
1362    #[allow(clippy::too_many_arguments)]
1363    fn i64_load_32s(
1364        &mut self,
1365        addr: Location<Self::GPR, Self::SIMD>,
1366        memarg: &MemArg,
1367        ret: Location<Self::GPR, Self::SIMD>,
1368        need_check: bool,
1369        imported_memories: bool,
1370        offset: i32,
1371        heap_access_oob: Label,
1372        unaligned_atomic: Label,
1373    ) -> Result<(), CompileError>;
1374    /// i64 load of an signed 16bits
1375    #[allow(clippy::too_many_arguments)]
1376    fn i64_load_16u(
1377        &mut self,
1378        addr: Location<Self::GPR, Self::SIMD>,
1379        memarg: &MemArg,
1380        ret: Location<Self::GPR, Self::SIMD>,
1381        need_check: bool,
1382        imported_memories: bool,
1383        offset: i32,
1384        heap_access_oob: Label,
1385        unaligned_atomic: Label,
1386    ) -> Result<(), CompileError>;
1387    /// i64 load of an signed 16bits
1388    #[allow(clippy::too_many_arguments)]
1389    fn i64_load_16s(
1390        &mut self,
1391        addr: Location<Self::GPR, Self::SIMD>,
1392        memarg: &MemArg,
1393        ret: Location<Self::GPR, Self::SIMD>,
1394        need_check: bool,
1395        imported_memories: bool,
1396        offset: i32,
1397        heap_access_oob: Label,
1398        unaligned_atomic: Label,
1399    ) -> Result<(), CompileError>;
1400    /// i64 atomic load
1401    #[allow(clippy::too_many_arguments)]
1402    fn i64_atomic_load(
1403        &mut self,
1404        addr: Location<Self::GPR, Self::SIMD>,
1405        memarg: &MemArg,
1406        ret: Location<Self::GPR, Self::SIMD>,
1407        need_check: bool,
1408        imported_memories: bool,
1409        offset: i32,
1410        heap_access_oob: Label,
1411        unaligned_atomic: Label,
1412    ) -> Result<(), CompileError>;
1413    /// i64 atomic load from unsigned 8bits
1414    #[allow(clippy::too_many_arguments)]
1415    fn i64_atomic_load_8u(
1416        &mut self,
1417        addr: Location<Self::GPR, Self::SIMD>,
1418        memarg: &MemArg,
1419        ret: Location<Self::GPR, Self::SIMD>,
1420        need_check: bool,
1421        imported_memories: bool,
1422        offset: i32,
1423        heap_access_oob: Label,
1424        unaligned_atomic: Label,
1425    ) -> Result<(), CompileError>;
1426    /// i64 atomic load from unsigned 16bits
1427    #[allow(clippy::too_many_arguments)]
1428    fn i64_atomic_load_16u(
1429        &mut self,
1430        addr: Location<Self::GPR, Self::SIMD>,
1431        memarg: &MemArg,
1432        ret: Location<Self::GPR, Self::SIMD>,
1433        need_check: bool,
1434        imported_memories: bool,
1435        offset: i32,
1436        heap_access_oob: Label,
1437        unaligned_atomic: Label,
1438    ) -> Result<(), CompileError>;
1439    /// i64 atomic load from unsigned 32bits
1440    #[allow(clippy::too_many_arguments)]
1441    fn i64_atomic_load_32u(
1442        &mut self,
1443        addr: Location<Self::GPR, Self::SIMD>,
1444        memarg: &MemArg,
1445        ret: Location<Self::GPR, Self::SIMD>,
1446        need_check: bool,
1447        imported_memories: bool,
1448        offset: i32,
1449        heap_access_oob: Label,
1450        unaligned_atomic: Label,
1451    ) -> Result<(), CompileError>;
1452    /// i64 save
1453    #[allow(clippy::too_many_arguments)]
1454    fn i64_save(
1455        &mut self,
1456        value: Location<Self::GPR, Self::SIMD>,
1457        memarg: &MemArg,
1458        addr: Location<Self::GPR, Self::SIMD>,
1459        need_check: bool,
1460        imported_memories: bool,
1461        offset: i32,
1462        heap_access_oob: Label,
1463        unaligned_atomic: Label,
1464    ) -> Result<(), CompileError>;
1465    /// i64 save of the lower 8bits
1466    #[allow(clippy::too_many_arguments)]
1467    fn i64_save_8(
1468        &mut self,
1469        value: Location<Self::GPR, Self::SIMD>,
1470        memarg: &MemArg,
1471        addr: Location<Self::GPR, Self::SIMD>,
1472        need_check: bool,
1473        imported_memories: bool,
1474        offset: i32,
1475        heap_access_oob: Label,
1476        unaligned_atomic: Label,
1477    ) -> Result<(), CompileError>;
1478    /// i64 save of the lower 16bits
1479    #[allow(clippy::too_many_arguments)]
1480    fn i64_save_16(
1481        &mut self,
1482        value: Location<Self::GPR, Self::SIMD>,
1483        memarg: &MemArg,
1484        addr: Location<Self::GPR, Self::SIMD>,
1485        need_check: bool,
1486        imported_memories: bool,
1487        offset: i32,
1488        heap_access_oob: Label,
1489        unaligned_atomic: Label,
1490    ) -> Result<(), CompileError>;
1491    /// i64 save of the lower 32bits
1492    #[allow(clippy::too_many_arguments)]
1493    fn i64_save_32(
1494        &mut self,
1495        value: Location<Self::GPR, Self::SIMD>,
1496        memarg: &MemArg,
1497        addr: Location<Self::GPR, Self::SIMD>,
1498        need_check: bool,
1499        imported_memories: bool,
1500        offset: i32,
1501        heap_access_oob: Label,
1502        unaligned_atomic: Label,
1503    ) -> Result<(), CompileError>;
1504    /// i64 atomic save
1505    #[allow(clippy::too_many_arguments)]
1506    fn i64_atomic_save(
1507        &mut self,
1508        value: Location<Self::GPR, Self::SIMD>,
1509        memarg: &MemArg,
1510        addr: Location<Self::GPR, Self::SIMD>,
1511        need_check: bool,
1512        imported_memories: bool,
1513        offset: i32,
1514        heap_access_oob: Label,
1515        unaligned_atomic: Label,
1516    ) -> Result<(), CompileError>;
1517    /// i64 atomic save of a the lower 8bits
1518    #[allow(clippy::too_many_arguments)]
1519    fn i64_atomic_save_8(
1520        &mut self,
1521        value: Location<Self::GPR, Self::SIMD>,
1522        memarg: &MemArg,
1523        addr: Location<Self::GPR, Self::SIMD>,
1524        need_check: bool,
1525        imported_memories: bool,
1526        offset: i32,
1527        heap_access_oob: Label,
1528        unaligned_atomic: Label,
1529    ) -> Result<(), CompileError>;
1530    /// i64 atomic save of a the lower 16bits
1531    #[allow(clippy::too_many_arguments)]
1532    fn i64_atomic_save_16(
1533        &mut self,
1534        value: Location<Self::GPR, Self::SIMD>,
1535        memarg: &MemArg,
1536        addr: Location<Self::GPR, Self::SIMD>,
1537        need_check: bool,
1538        imported_memories: bool,
1539        offset: i32,
1540        heap_access_oob: Label,
1541        unaligned_atomic: Label,
1542    ) -> Result<(), CompileError>;
1543    /// i64 atomic save of a the lower 32bits
1544    #[allow(clippy::too_many_arguments)]
1545    fn i64_atomic_save_32(
1546        &mut self,
1547        value: Location<Self::GPR, Self::SIMD>,
1548        memarg: &MemArg,
1549        addr: Location<Self::GPR, Self::SIMD>,
1550        need_check: bool,
1551        imported_memories: bool,
1552        offset: i32,
1553        heap_access_oob: Label,
1554        unaligned_atomic: Label,
1555    ) -> Result<(), CompileError>;
1556    /// i64 atomic Add with i64
1557    #[allow(clippy::too_many_arguments)]
1558    fn i64_atomic_add(
1559        &mut self,
1560        loc: Location<Self::GPR, Self::SIMD>,
1561        target: Location<Self::GPR, Self::SIMD>,
1562        memarg: &MemArg,
1563        ret: Location<Self::GPR, Self::SIMD>,
1564        need_check: bool,
1565        imported_memories: bool,
1566        offset: i32,
1567        heap_access_oob: Label,
1568        unaligned_atomic: Label,
1569    ) -> Result<(), CompileError>;
1570    /// i64 atomic Add with unsigned 8bits
1571    #[allow(clippy::too_many_arguments)]
1572    fn i64_atomic_add_8u(
1573        &mut self,
1574        loc: Location<Self::GPR, Self::SIMD>,
1575        target: Location<Self::GPR, Self::SIMD>,
1576        memarg: &MemArg,
1577        ret: Location<Self::GPR, Self::SIMD>,
1578        need_check: bool,
1579        imported_memories: bool,
1580        offset: i32,
1581        heap_access_oob: Label,
1582        unaligned_atomic: Label,
1583    ) -> Result<(), CompileError>;
1584    /// i64 atomic Add with unsigned 16bits
1585    #[allow(clippy::too_many_arguments)]
1586    fn i64_atomic_add_16u(
1587        &mut self,
1588        loc: Location<Self::GPR, Self::SIMD>,
1589        target: Location<Self::GPR, Self::SIMD>,
1590        memarg: &MemArg,
1591        ret: Location<Self::GPR, Self::SIMD>,
1592        need_check: bool,
1593        imported_memories: bool,
1594        offset: i32,
1595        heap_access_oob: Label,
1596        unaligned_atomic: Label,
1597    ) -> Result<(), CompileError>;
1598    /// i64 atomic Add with unsigned 32bits
1599    #[allow(clippy::too_many_arguments)]
1600    fn i64_atomic_add_32u(
1601        &mut self,
1602        loc: Location<Self::GPR, Self::SIMD>,
1603        target: Location<Self::GPR, Self::SIMD>,
1604        memarg: &MemArg,
1605        ret: Location<Self::GPR, Self::SIMD>,
1606        need_check: bool,
1607        imported_memories: bool,
1608        offset: i32,
1609        heap_access_oob: Label,
1610        unaligned_atomic: Label,
1611    ) -> Result<(), CompileError>;
1612    /// i64 atomic Sub with i64
1613    #[allow(clippy::too_many_arguments)]
1614    fn i64_atomic_sub(
1615        &mut self,
1616        loc: Location<Self::GPR, Self::SIMD>,
1617        target: Location<Self::GPR, Self::SIMD>,
1618        memarg: &MemArg,
1619        ret: Location<Self::GPR, Self::SIMD>,
1620        need_check: bool,
1621        imported_memories: bool,
1622        offset: i32,
1623        heap_access_oob: Label,
1624        unaligned_atomic: Label,
1625    ) -> Result<(), CompileError>;
1626    /// i64 atomic Sub with unsigned 8bits
1627    #[allow(clippy::too_many_arguments)]
1628    fn i64_atomic_sub_8u(
1629        &mut self,
1630        loc: Location<Self::GPR, Self::SIMD>,
1631        target: Location<Self::GPR, Self::SIMD>,
1632        memarg: &MemArg,
1633        ret: Location<Self::GPR, Self::SIMD>,
1634        need_check: bool,
1635        imported_memories: bool,
1636        offset: i32,
1637        heap_access_oob: Label,
1638        unaligned_atomic: Label,
1639    ) -> Result<(), CompileError>;
1640    /// i64 atomic Sub with unsigned 16bits
1641    #[allow(clippy::too_many_arguments)]
1642    fn i64_atomic_sub_16u(
1643        &mut self,
1644        loc: Location<Self::GPR, Self::SIMD>,
1645        target: Location<Self::GPR, Self::SIMD>,
1646        memarg: &MemArg,
1647        ret: Location<Self::GPR, Self::SIMD>,
1648        need_check: bool,
1649        imported_memories: bool,
1650        offset: i32,
1651        heap_access_oob: Label,
1652        unaligned_atomic: Label,
1653    ) -> Result<(), CompileError>;
1654    /// i64 atomic Sub with unsigned 32bits
1655    #[allow(clippy::too_many_arguments)]
1656    fn i64_atomic_sub_32u(
1657        &mut self,
1658        loc: Location<Self::GPR, Self::SIMD>,
1659        target: Location<Self::GPR, Self::SIMD>,
1660        memarg: &MemArg,
1661        ret: Location<Self::GPR, Self::SIMD>,
1662        need_check: bool,
1663        imported_memories: bool,
1664        offset: i32,
1665        heap_access_oob: Label,
1666        unaligned_atomic: Label,
1667    ) -> Result<(), CompileError>;
1668    /// i64 atomic And with i64
1669    #[allow(clippy::too_many_arguments)]
1670    fn i64_atomic_and(
1671        &mut self,
1672        loc: Location<Self::GPR, Self::SIMD>,
1673        target: Location<Self::GPR, Self::SIMD>,
1674        memarg: &MemArg,
1675        ret: Location<Self::GPR, Self::SIMD>,
1676        need_check: bool,
1677        imported_memories: bool,
1678        offset: i32,
1679        heap_access_oob: Label,
1680        unaligned_atomic: Label,
1681    ) -> Result<(), CompileError>;
1682    /// i64 atomic And with unsigned 8bits
1683    #[allow(clippy::too_many_arguments)]
1684    fn i64_atomic_and_8u(
1685        &mut self,
1686        loc: Location<Self::GPR, Self::SIMD>,
1687        target: Location<Self::GPR, Self::SIMD>,
1688        memarg: &MemArg,
1689        ret: Location<Self::GPR, Self::SIMD>,
1690        need_check: bool,
1691        imported_memories: bool,
1692        offset: i32,
1693        heap_access_oob: Label,
1694        unaligned_atomic: Label,
1695    ) -> Result<(), CompileError>;
1696    /// i64 atomic And with unsigned 16bits
1697    #[allow(clippy::too_many_arguments)]
1698    fn i64_atomic_and_16u(
1699        &mut self,
1700        loc: Location<Self::GPR, Self::SIMD>,
1701        target: Location<Self::GPR, Self::SIMD>,
1702        memarg: &MemArg,
1703        ret: Location<Self::GPR, Self::SIMD>,
1704        need_check: bool,
1705        imported_memories: bool,
1706        offset: i32,
1707        heap_access_oob: Label,
1708        unaligned_atomic: Label,
1709    ) -> Result<(), CompileError>;
1710    /// i64 atomic And with unsigned 32bits
1711    #[allow(clippy::too_many_arguments)]
1712    fn i64_atomic_and_32u(
1713        &mut self,
1714        loc: Location<Self::GPR, Self::SIMD>,
1715        target: Location<Self::GPR, Self::SIMD>,
1716        memarg: &MemArg,
1717        ret: Location<Self::GPR, Self::SIMD>,
1718        need_check: bool,
1719        imported_memories: bool,
1720        offset: i32,
1721        heap_access_oob: Label,
1722        unaligned_atomic: Label,
1723    ) -> Result<(), CompileError>;
1724    /// i64 atomic Or with i64
1725    #[allow(clippy::too_many_arguments)]
1726    fn i64_atomic_or(
1727        &mut self,
1728        loc: Location<Self::GPR, Self::SIMD>,
1729        target: Location<Self::GPR, Self::SIMD>,
1730        memarg: &MemArg,
1731        ret: Location<Self::GPR, Self::SIMD>,
1732        need_check: bool,
1733        imported_memories: bool,
1734        offset: i32,
1735        heap_access_oob: Label,
1736        unaligned_atomic: Label,
1737    ) -> Result<(), CompileError>;
1738    /// i64 atomic Or with unsigned 8bits
1739    #[allow(clippy::too_many_arguments)]
1740    fn i64_atomic_or_8u(
1741        &mut self,
1742        loc: Location<Self::GPR, Self::SIMD>,
1743        target: Location<Self::GPR, Self::SIMD>,
1744        memarg: &MemArg,
1745        ret: Location<Self::GPR, Self::SIMD>,
1746        need_check: bool,
1747        imported_memories: bool,
1748        offset: i32,
1749        heap_access_oob: Label,
1750        unaligned_atomic: Label,
1751    ) -> Result<(), CompileError>;
1752    /// i64 atomic Or with unsigned 16bits
1753    #[allow(clippy::too_many_arguments)]
1754    fn i64_atomic_or_16u(
1755        &mut self,
1756        loc: Location<Self::GPR, Self::SIMD>,
1757        target: Location<Self::GPR, Self::SIMD>,
1758        memarg: &MemArg,
1759        ret: Location<Self::GPR, Self::SIMD>,
1760        need_check: bool,
1761        imported_memories: bool,
1762        offset: i32,
1763        heap_access_oob: Label,
1764        unaligned_atomic: Label,
1765    ) -> Result<(), CompileError>;
1766    /// i64 atomic Or with unsigned 32bits
1767    #[allow(clippy::too_many_arguments)]
1768    fn i64_atomic_or_32u(
1769        &mut self,
1770        loc: Location<Self::GPR, Self::SIMD>,
1771        target: Location<Self::GPR, Self::SIMD>,
1772        memarg: &MemArg,
1773        ret: Location<Self::GPR, Self::SIMD>,
1774        need_check: bool,
1775        imported_memories: bool,
1776        offset: i32,
1777        heap_access_oob: Label,
1778        unaligned_atomic: Label,
1779    ) -> Result<(), CompileError>;
1780    /// i64 atomic Xor with i64
1781    #[allow(clippy::too_many_arguments)]
1782    fn i64_atomic_xor(
1783        &mut self,
1784        loc: Location<Self::GPR, Self::SIMD>,
1785        target: Location<Self::GPR, Self::SIMD>,
1786        memarg: &MemArg,
1787        ret: Location<Self::GPR, Self::SIMD>,
1788        need_check: bool,
1789        imported_memories: bool,
1790        offset: i32,
1791        heap_access_oob: Label,
1792        unaligned_atomic: Label,
1793    ) -> Result<(), CompileError>;
1794    /// i64 atomic Xor with unsigned 8bits
1795    #[allow(clippy::too_many_arguments)]
1796    fn i64_atomic_xor_8u(
1797        &mut self,
1798        loc: Location<Self::GPR, Self::SIMD>,
1799        target: Location<Self::GPR, Self::SIMD>,
1800        memarg: &MemArg,
1801        ret: Location<Self::GPR, Self::SIMD>,
1802        need_check: bool,
1803        imported_memories: bool,
1804        offset: i32,
1805        heap_access_oob: Label,
1806        unaligned_atomic: Label,
1807    ) -> Result<(), CompileError>;
1808    /// i64 atomic Xor with unsigned 16bits
1809    #[allow(clippy::too_many_arguments)]
1810    fn i64_atomic_xor_16u(
1811        &mut self,
1812        loc: Location<Self::GPR, Self::SIMD>,
1813        target: Location<Self::GPR, Self::SIMD>,
1814        memarg: &MemArg,
1815        ret: Location<Self::GPR, Self::SIMD>,
1816        need_check: bool,
1817        imported_memories: bool,
1818        offset: i32,
1819        heap_access_oob: Label,
1820        unaligned_atomic: Label,
1821    ) -> Result<(), CompileError>;
1822    /// i64 atomic Xor with unsigned 32bits
1823    #[allow(clippy::too_many_arguments)]
1824    fn i64_atomic_xor_32u(
1825        &mut self,
1826        loc: Location<Self::GPR, Self::SIMD>,
1827        target: Location<Self::GPR, Self::SIMD>,
1828        memarg: &MemArg,
1829        ret: Location<Self::GPR, Self::SIMD>,
1830        need_check: bool,
1831        imported_memories: bool,
1832        offset: i32,
1833        heap_access_oob: Label,
1834        unaligned_atomic: Label,
1835    ) -> Result<(), CompileError>;
1836    /// i64 atomic Exchange with i64
1837    #[allow(clippy::too_many_arguments)]
1838    fn i64_atomic_xchg(
1839        &mut self,
1840        loc: Location<Self::GPR, Self::SIMD>,
1841        target: Location<Self::GPR, Self::SIMD>,
1842        memarg: &MemArg,
1843        ret: Location<Self::GPR, Self::SIMD>,
1844        need_check: bool,
1845        imported_memories: bool,
1846        offset: i32,
1847        heap_access_oob: Label,
1848        unaligned_atomic: Label,
1849    ) -> Result<(), CompileError>;
1850    /// i64 atomic Exchange with u8
1851    #[allow(clippy::too_many_arguments)]
1852    fn i64_atomic_xchg_8u(
1853        &mut self,
1854        loc: Location<Self::GPR, Self::SIMD>,
1855        target: Location<Self::GPR, Self::SIMD>,
1856        memarg: &MemArg,
1857        ret: Location<Self::GPR, Self::SIMD>,
1858        need_check: bool,
1859        imported_memories: bool,
1860        offset: i32,
1861        heap_access_oob: Label,
1862        unaligned_atomic: Label,
1863    ) -> Result<(), CompileError>;
1864    /// i64 atomic Exchange with u16
1865    #[allow(clippy::too_many_arguments)]
1866    fn i64_atomic_xchg_16u(
1867        &mut self,
1868        loc: Location<Self::GPR, Self::SIMD>,
1869        target: Location<Self::GPR, Self::SIMD>,
1870        memarg: &MemArg,
1871        ret: Location<Self::GPR, Self::SIMD>,
1872        need_check: bool,
1873        imported_memories: bool,
1874        offset: i32,
1875        heap_access_oob: Label,
1876        unaligned_atomic: Label,
1877    ) -> Result<(), CompileError>;
1878    /// i64 atomic Exchange with u32
1879    #[allow(clippy::too_many_arguments)]
1880    fn i64_atomic_xchg_32u(
1881        &mut self,
1882        loc: Location<Self::GPR, Self::SIMD>,
1883        target: Location<Self::GPR, Self::SIMD>,
1884        memarg: &MemArg,
1885        ret: Location<Self::GPR, Self::SIMD>,
1886        need_check: bool,
1887        imported_memories: bool,
1888        offset: i32,
1889        heap_access_oob: Label,
1890        unaligned_atomic: Label,
1891    ) -> Result<(), CompileError>;
1892    /// i64 atomic Compare and Exchange with i32
1893    #[allow(clippy::too_many_arguments)]
1894    fn i64_atomic_cmpxchg(
1895        &mut self,
1896        new: Location<Self::GPR, Self::SIMD>,
1897        cmp: Location<Self::GPR, Self::SIMD>,
1898        target: Location<Self::GPR, Self::SIMD>,
1899        memarg: &MemArg,
1900        ret: Location<Self::GPR, Self::SIMD>,
1901        need_check: bool,
1902        imported_memories: bool,
1903        offset: i32,
1904        heap_access_oob: Label,
1905        unaligned_atomic: Label,
1906    ) -> Result<(), CompileError>;
1907    /// i64 atomic Compare and Exchange with u8
1908    #[allow(clippy::too_many_arguments)]
1909    fn i64_atomic_cmpxchg_8u(
1910        &mut self,
1911        new: Location<Self::GPR, Self::SIMD>,
1912        cmp: Location<Self::GPR, Self::SIMD>,
1913        target: Location<Self::GPR, Self::SIMD>,
1914        memarg: &MemArg,
1915        ret: Location<Self::GPR, Self::SIMD>,
1916        need_check: bool,
1917        imported_memories: bool,
1918        offset: i32,
1919        heap_access_oob: Label,
1920        unaligned_atomic: Label,
1921    ) -> Result<(), CompileError>;
1922    /// i64 atomic Compare and Exchange with u16
1923    #[allow(clippy::too_many_arguments)]
1924    fn i64_atomic_cmpxchg_16u(
1925        &mut self,
1926        new: Location<Self::GPR, Self::SIMD>,
1927        cmp: Location<Self::GPR, Self::SIMD>,
1928        target: Location<Self::GPR, Self::SIMD>,
1929        memarg: &MemArg,
1930        ret: Location<Self::GPR, Self::SIMD>,
1931        need_check: bool,
1932        imported_memories: bool,
1933        offset: i32,
1934        heap_access_oob: Label,
1935        unaligned_atomic: Label,
1936    ) -> Result<(), CompileError>;
1937    /// i64 atomic Compare and Exchange with u32
1938    #[allow(clippy::too_many_arguments)]
1939    fn i64_atomic_cmpxchg_32u(
1940        &mut self,
1941        new: Location<Self::GPR, Self::SIMD>,
1942        cmp: Location<Self::GPR, Self::SIMD>,
1943        target: Location<Self::GPR, Self::SIMD>,
1944        memarg: &MemArg,
1945        ret: Location<Self::GPR, Self::SIMD>,
1946        need_check: bool,
1947        imported_memories: bool,
1948        offset: i32,
1949        heap_access_oob: Label,
1950        unaligned_atomic: Label,
1951    ) -> Result<(), CompileError>;
1952
1953    /// load an F32
1954    #[allow(clippy::too_many_arguments)]
1955    fn f32_load(
1956        &mut self,
1957        addr: Location<Self::GPR, Self::SIMD>,
1958        memarg: &MemArg,
1959        ret: Location<Self::GPR, Self::SIMD>,
1960        need_check: bool,
1961        imported_memories: bool,
1962        offset: i32,
1963        heap_access_oob: Label,
1964        unaligned_atomic: Label,
1965    ) -> Result<(), CompileError>;
1966    /// f32 save
1967    #[allow(clippy::too_many_arguments)]
1968    fn f32_save(
1969        &mut self,
1970        value: Location<Self::GPR, Self::SIMD>,
1971        memarg: &MemArg,
1972        addr: Location<Self::GPR, Self::SIMD>,
1973        canonicalize: bool,
1974        need_check: bool,
1975        imported_memories: bool,
1976        offset: i32,
1977        heap_access_oob: Label,
1978        unaligned_atomic: Label,
1979    ) -> Result<(), CompileError>;
1980    /// load an F64
1981    #[allow(clippy::too_many_arguments)]
1982    fn f64_load(
1983        &mut self,
1984        addr: Location<Self::GPR, Self::SIMD>,
1985        memarg: &MemArg,
1986        ret: Location<Self::GPR, Self::SIMD>,
1987        need_check: bool,
1988        imported_memories: bool,
1989        offset: i32,
1990        heap_access_oob: Label,
1991        unaligned_atomic: Label,
1992    ) -> Result<(), CompileError>;
1993    /// f64 save
1994    #[allow(clippy::too_many_arguments)]
1995    fn f64_save(
1996        &mut self,
1997        value: Location<Self::GPR, Self::SIMD>,
1998        memarg: &MemArg,
1999        addr: Location<Self::GPR, Self::SIMD>,
2000        canonicalize: bool,
2001        need_check: bool,
2002        imported_memories: bool,
2003        offset: i32,
2004        heap_access_oob: Label,
2005        unaligned_atomic: Label,
2006    ) -> Result<(), CompileError>;
2007    /// Convert a F64 from I64, signed or unsigned
2008    fn convert_f64_i64(
2009        &mut self,
2010        loc: Location<Self::GPR, Self::SIMD>,
2011        signed: bool,
2012        ret: Location<Self::GPR, Self::SIMD>,
2013    ) -> Result<(), CompileError>;
2014    /// Convert a F64 from I32, signed or unsigned
2015    fn convert_f64_i32(
2016        &mut self,
2017        loc: Location<Self::GPR, Self::SIMD>,
2018        signed: bool,
2019        ret: Location<Self::GPR, Self::SIMD>,
2020    ) -> Result<(), CompileError>;
2021    /// Convert a F32 from I64, signed or unsigned
2022    fn convert_f32_i64(
2023        &mut self,
2024        loc: Location<Self::GPR, Self::SIMD>,
2025        signed: bool,
2026        ret: Location<Self::GPR, Self::SIMD>,
2027    ) -> Result<(), CompileError>;
2028    /// Convert a F32 from I32, signed or unsigned
2029    fn convert_f32_i32(
2030        &mut self,
2031        loc: Location<Self::GPR, Self::SIMD>,
2032        signed: bool,
2033        ret: Location<Self::GPR, Self::SIMD>,
2034    ) -> Result<(), CompileError>;
2035    /// Convert a F64 to I64, signed or unsigned, without or without saturation
2036    fn convert_i64_f64(
2037        &mut self,
2038        loc: Location<Self::GPR, Self::SIMD>,
2039        ret: Location<Self::GPR, Self::SIMD>,
2040        signed: bool,
2041        sat: bool,
2042    ) -> Result<(), CompileError>;
2043    /// Convert a F64 to I32, signed or unsigned, without or without saturation
2044    fn convert_i32_f64(
2045        &mut self,
2046        loc: Location<Self::GPR, Self::SIMD>,
2047        ret: Location<Self::GPR, Self::SIMD>,
2048        signed: bool,
2049        sat: bool,
2050    ) -> Result<(), CompileError>;
2051    /// Convert a F32 to I64, signed or unsigned, without or without saturation
2052    fn convert_i64_f32(
2053        &mut self,
2054        loc: Location<Self::GPR, Self::SIMD>,
2055        ret: Location<Self::GPR, Self::SIMD>,
2056        signed: bool,
2057        sat: bool,
2058    ) -> Result<(), CompileError>;
2059    /// Convert a F32 to I32, signed or unsigned, without or without saturation
2060    fn convert_i32_f32(
2061        &mut self,
2062        loc: Location<Self::GPR, Self::SIMD>,
2063        ret: Location<Self::GPR, Self::SIMD>,
2064        signed: bool,
2065        sat: bool,
2066    ) -> Result<(), CompileError>;
2067    /// Convert a F32 to F64
2068    fn convert_f64_f32(
2069        &mut self,
2070        loc: Location<Self::GPR, Self::SIMD>,
2071        ret: Location<Self::GPR, Self::SIMD>,
2072    ) -> Result<(), CompileError>;
2073    /// Convert a F64 to F32
2074    fn convert_f32_f64(
2075        &mut self,
2076        loc: Location<Self::GPR, Self::SIMD>,
2077        ret: Location<Self::GPR, Self::SIMD>,
2078    ) -> Result<(), CompileError>;
2079    /// Negate an F64
2080    fn f64_neg(
2081        &mut self,
2082        loc: Location<Self::GPR, Self::SIMD>,
2083        ret: Location<Self::GPR, Self::SIMD>,
2084    ) -> Result<(), CompileError>;
2085    /// Get the Absolute Value of an F64
2086    fn f64_abs(
2087        &mut self,
2088        loc: Location<Self::GPR, Self::SIMD>,
2089        ret: Location<Self::GPR, Self::SIMD>,
2090    ) -> Result<(), CompileError>;
2091    /// Copy sign from tmp1 Self::GPR to tmp2 Self::GPR
2092    fn emit_i64_copysign(&mut self, tmp1: Self::GPR, tmp2: Self::GPR) -> Result<(), CompileError>;
2093    /// Get the Square Root of an F64
2094    fn f64_sqrt(
2095        &mut self,
2096        loc: Location<Self::GPR, Self::SIMD>,
2097        ret: Location<Self::GPR, Self::SIMD>,
2098    ) -> Result<(), CompileError>;
2099    /// Trunc of an F64
2100    fn f64_trunc(
2101        &mut self,
2102        loc: Location<Self::GPR, Self::SIMD>,
2103        ret: Location<Self::GPR, Self::SIMD>,
2104    ) -> Result<(), CompileError>;
2105    /// Ceil of an F64
2106    fn f64_ceil(
2107        &mut self,
2108        loc: Location<Self::GPR, Self::SIMD>,
2109        ret: Location<Self::GPR, Self::SIMD>,
2110    ) -> Result<(), CompileError>;
2111    /// Floor of an F64
2112    fn f64_floor(
2113        &mut self,
2114        loc: Location<Self::GPR, Self::SIMD>,
2115        ret: Location<Self::GPR, Self::SIMD>,
2116    ) -> Result<(), CompileError>;
2117    /// Round at nearest int of an F64
2118    fn f64_nearest(
2119        &mut self,
2120        loc: Location<Self::GPR, Self::SIMD>,
2121        ret: Location<Self::GPR, Self::SIMD>,
2122    ) -> Result<(), CompileError>;
2123    /// Greater of Equal Compare 2 F64, result in a GPR
2124    fn f64_cmp_ge(
2125        &mut self,
2126        loc_a: Location<Self::GPR, Self::SIMD>,
2127        loc_b: Location<Self::GPR, Self::SIMD>,
2128        ret: Location<Self::GPR, Self::SIMD>,
2129    ) -> Result<(), CompileError>;
2130    /// Greater Than Compare 2 F64, result in a GPR
2131    fn f64_cmp_gt(
2132        &mut self,
2133        loc_a: Location<Self::GPR, Self::SIMD>,
2134        loc_b: Location<Self::GPR, Self::SIMD>,
2135        ret: Location<Self::GPR, Self::SIMD>,
2136    ) -> Result<(), CompileError>;
2137    /// Less of Equal Compare 2 F64, result in a GPR
2138    fn f64_cmp_le(
2139        &mut self,
2140        loc_a: Location<Self::GPR, Self::SIMD>,
2141        loc_b: Location<Self::GPR, Self::SIMD>,
2142        ret: Location<Self::GPR, Self::SIMD>,
2143    ) -> Result<(), CompileError>;
2144    /// Less Than Compare 2 F64, result in a GPR
2145    fn f64_cmp_lt(
2146        &mut self,
2147        loc_a: Location<Self::GPR, Self::SIMD>,
2148        loc_b: Location<Self::GPR, Self::SIMD>,
2149        ret: Location<Self::GPR, Self::SIMD>,
2150    ) -> Result<(), CompileError>;
2151    /// Not Equal Compare 2 F64, result in a GPR
2152    fn f64_cmp_ne(
2153        &mut self,
2154        loc_a: Location<Self::GPR, Self::SIMD>,
2155        loc_b: Location<Self::GPR, Self::SIMD>,
2156        ret: Location<Self::GPR, Self::SIMD>,
2157    ) -> Result<(), CompileError>;
2158    /// Equal Compare 2 F64, result in a GPR
2159    fn f64_cmp_eq(
2160        &mut self,
2161        loc_a: Location<Self::GPR, Self::SIMD>,
2162        loc_b: Location<Self::GPR, Self::SIMD>,
2163        ret: Location<Self::GPR, Self::SIMD>,
2164    ) -> Result<(), CompileError>;
2165    /// get Min for 2 F64 values
2166    fn f64_min(
2167        &mut self,
2168        loc_a: Location<Self::GPR, Self::SIMD>,
2169        loc_b: Location<Self::GPR, Self::SIMD>,
2170        ret: Location<Self::GPR, Self::SIMD>,
2171    ) -> Result<(), CompileError>;
2172    /// get Max for 2 F64 values
2173    fn f64_max(
2174        &mut self,
2175        loc_a: Location<Self::GPR, Self::SIMD>,
2176        loc_b: Location<Self::GPR, Self::SIMD>,
2177        ret: Location<Self::GPR, Self::SIMD>,
2178    ) -> Result<(), CompileError>;
2179    /// Add 2 F64 values
2180    fn f64_add(
2181        &mut self,
2182        loc_a: Location<Self::GPR, Self::SIMD>,
2183        loc_b: Location<Self::GPR, Self::SIMD>,
2184        ret: Location<Self::GPR, Self::SIMD>,
2185    ) -> Result<(), CompileError>;
2186    /// Sub 2 F64 values
2187    fn f64_sub(
2188        &mut self,
2189        loc_a: Location<Self::GPR, Self::SIMD>,
2190        loc_b: Location<Self::GPR, Self::SIMD>,
2191        ret: Location<Self::GPR, Self::SIMD>,
2192    ) -> Result<(), CompileError>;
2193    /// Multiply 2 F64 values
2194    fn f64_mul(
2195        &mut self,
2196        loc_a: Location<Self::GPR, Self::SIMD>,
2197        loc_b: Location<Self::GPR, Self::SIMD>,
2198        ret: Location<Self::GPR, Self::SIMD>,
2199    ) -> Result<(), CompileError>;
2200    /// Divide 2 F64 values
2201    fn f64_div(
2202        &mut self,
2203        loc_a: Location<Self::GPR, Self::SIMD>,
2204        loc_b: Location<Self::GPR, Self::SIMD>,
2205        ret: Location<Self::GPR, Self::SIMD>,
2206    ) -> Result<(), CompileError>;
2207    /// Negate an F32
2208    fn f32_neg(
2209        &mut self,
2210        loc: Location<Self::GPR, Self::SIMD>,
2211        ret: Location<Self::GPR, Self::SIMD>,
2212    ) -> Result<(), CompileError>;
2213    /// Get the Absolute Value of an F32
2214    fn f32_abs(
2215        &mut self,
2216        loc: Location<Self::GPR, Self::SIMD>,
2217        ret: Location<Self::GPR, Self::SIMD>,
2218    ) -> Result<(), CompileError>;
2219    /// Copy sign from tmp1 Self::GPR to tmp2 Self::GPR
2220    fn emit_i32_copysign(&mut self, tmp1: Self::GPR, tmp2: Self::GPR) -> Result<(), CompileError>;
2221    /// Get the Square Root of an F32
2222    fn f32_sqrt(
2223        &mut self,
2224        loc: Location<Self::GPR, Self::SIMD>,
2225        ret: Location<Self::GPR, Self::SIMD>,
2226    ) -> Result<(), CompileError>;
2227    /// Trunc of an F32
2228    fn f32_trunc(
2229        &mut self,
2230        loc: Location<Self::GPR, Self::SIMD>,
2231        ret: Location<Self::GPR, Self::SIMD>,
2232    ) -> Result<(), CompileError>;
2233    /// Ceil of an F32
2234    fn f32_ceil(
2235        &mut self,
2236        loc: Location<Self::GPR, Self::SIMD>,
2237        ret: Location<Self::GPR, Self::SIMD>,
2238    ) -> Result<(), CompileError>;
2239    /// Floor of an F32
2240    fn f32_floor(
2241        &mut self,
2242        loc: Location<Self::GPR, Self::SIMD>,
2243        ret: Location<Self::GPR, Self::SIMD>,
2244    ) -> Result<(), CompileError>;
2245    /// Round at nearest int of an F32
2246    fn f32_nearest(
2247        &mut self,
2248        loc: Location<Self::GPR, Self::SIMD>,
2249        ret: Location<Self::GPR, Self::SIMD>,
2250    ) -> Result<(), CompileError>;
2251    /// Greater of Equal Compare 2 F32, result in a GPR
2252    fn f32_cmp_ge(
2253        &mut self,
2254        loc_a: Location<Self::GPR, Self::SIMD>,
2255        loc_b: Location<Self::GPR, Self::SIMD>,
2256        ret: Location<Self::GPR, Self::SIMD>,
2257    ) -> Result<(), CompileError>;
2258    /// Greater Than Compare 2 F32, result in a GPR
2259    fn f32_cmp_gt(
2260        &mut self,
2261        loc_a: Location<Self::GPR, Self::SIMD>,
2262        loc_b: Location<Self::GPR, Self::SIMD>,
2263        ret: Location<Self::GPR, Self::SIMD>,
2264    ) -> Result<(), CompileError>;
2265    /// Less of Equal Compare 2 F32, result in a GPR
2266    fn f32_cmp_le(
2267        &mut self,
2268        loc_a: Location<Self::GPR, Self::SIMD>,
2269        loc_b: Location<Self::GPR, Self::SIMD>,
2270        ret: Location<Self::GPR, Self::SIMD>,
2271    ) -> Result<(), CompileError>;
2272    /// Less Than Compare 2 F32, result in a GPR
2273    fn f32_cmp_lt(
2274        &mut self,
2275        loc_a: Location<Self::GPR, Self::SIMD>,
2276        loc_b: Location<Self::GPR, Self::SIMD>,
2277        ret: Location<Self::GPR, Self::SIMD>,
2278    ) -> Result<(), CompileError>;
2279    /// Not Equal Compare 2 F32, result in a GPR
2280    fn f32_cmp_ne(
2281        &mut self,
2282        loc_a: Location<Self::GPR, Self::SIMD>,
2283        loc_b: Location<Self::GPR, Self::SIMD>,
2284        ret: Location<Self::GPR, Self::SIMD>,
2285    ) -> Result<(), CompileError>;
2286    /// Equal Compare 2 F32, result in a GPR
2287    fn f32_cmp_eq(
2288        &mut self,
2289        loc_a: Location<Self::GPR, Self::SIMD>,
2290        loc_b: Location<Self::GPR, Self::SIMD>,
2291        ret: Location<Self::GPR, Self::SIMD>,
2292    ) -> Result<(), CompileError>;
2293    /// get Min for 2 F32 values
2294    fn f32_min(
2295        &mut self,
2296        loc_a: Location<Self::GPR, Self::SIMD>,
2297        loc_b: Location<Self::GPR, Self::SIMD>,
2298        ret: Location<Self::GPR, Self::SIMD>,
2299    ) -> Result<(), CompileError>;
2300    /// get Max for 2 F32 values
2301    fn f32_max(
2302        &mut self,
2303        loc_a: Location<Self::GPR, Self::SIMD>,
2304        loc_b: Location<Self::GPR, Self::SIMD>,
2305        ret: Location<Self::GPR, Self::SIMD>,
2306    ) -> Result<(), CompileError>;
2307    /// Add 2 F32 values
2308    fn f32_add(
2309        &mut self,
2310        loc_a: Location<Self::GPR, Self::SIMD>,
2311        loc_b: Location<Self::GPR, Self::SIMD>,
2312        ret: Location<Self::GPR, Self::SIMD>,
2313    ) -> Result<(), CompileError>;
2314    /// Sub 2 F32 values
2315    fn f32_sub(
2316        &mut self,
2317        loc_a: Location<Self::GPR, Self::SIMD>,
2318        loc_b: Location<Self::GPR, Self::SIMD>,
2319        ret: Location<Self::GPR, Self::SIMD>,
2320    ) -> Result<(), CompileError>;
2321    /// Multiply 2 F32 values
2322    fn f32_mul(
2323        &mut self,
2324        loc_a: Location<Self::GPR, Self::SIMD>,
2325        loc_b: Location<Self::GPR, Self::SIMD>,
2326        ret: Location<Self::GPR, Self::SIMD>,
2327    ) -> Result<(), CompileError>;
2328    /// Divide 2 F32 values
2329    fn f32_div(
2330        &mut self,
2331        loc_a: Location<Self::GPR, Self::SIMD>,
2332        loc_b: Location<Self::GPR, Self::SIMD>,
2333        ret: Location<Self::GPR, Self::SIMD>,
2334    ) -> Result<(), CompileError>;
2335
2336    /// Standard function Trampoline generation
2337    fn gen_std_trampoline(
2338        &self,
2339        sig: &FunctionType,
2340        calling_convention: CallingConvention,
2341    ) -> Result<FunctionBody, CompileError>;
2342    /// Generates dynamic import function call trampoline for a function type.
2343    fn gen_std_dynamic_import_trampoline(
2344        &self,
2345        vmoffsets: &VMOffsets,
2346        sig: &FunctionType,
2347        calling_convention: CallingConvention,
2348    ) -> Result<FunctionBody, CompileError>;
2349    /// Singlepass calls import functions through a trampoline.
2350    fn gen_import_call_trampoline(
2351        &self,
2352        vmoffsets: &VMOffsets,
2353        index: FunctionIndex,
2354        sig: &FunctionType,
2355        calling_convention: CallingConvention,
2356    ) -> Result<CustomSection, CompileError>;
2357    /// generate eh_frame instruction (or None if not possible / supported)
2358    fn gen_dwarf_unwind_info(&mut self, code_len: usize) -> Option<UnwindInstructions>;
2359    /// generate Windows unwind instructions (or None if not possible / supported)
2360    fn gen_windows_unwind_info(&mut self, code_len: usize) -> Option<Vec<u8>>;
2361}
2362
2363/// Standard entry trampoline generation
2364pub fn gen_std_trampoline(
2365    sig: &FunctionType,
2366    target: &Target,
2367    calling_convention: CallingConvention,
2368    object: Option<&CompiledKind>,
2369) -> Result<CompileOutput<FunctionBody>, CompileError> {
2370    let body = match target.triple().architecture {
2371        Architecture::X86_64 => {
2372            let machine = MachineX86_64::new(Some(target.clone()))?;
2373            machine.gen_std_trampoline(sig, calling_convention)
2374        }
2375        Architecture::Aarch64(_) => {
2376            let machine = MachineARM64::new(Some(target.clone()));
2377            machine.gen_std_trampoline(sig, calling_convention)
2378        }
2379        Architecture::Riscv64(_) => {
2380            let machine = MachineRiscv::new(Some(target.clone()), false)?;
2381            machine.gen_std_trampoline(sig, calling_convention)
2382        }
2383        _ => Err(CompileError::UnsupportedTarget(
2384            "singlepass unimplemented arch for gen_std_trampoline".to_owned(),
2385        )),
2386    }?;
2387    match object {
2388        Some(kind) => Ok(CompileOutput::Object(
2389            elf::emit_function_body(target, kind, &body)?,
2390            None,
2391        )),
2392        None => Ok(CompileOutput::InMemory(body)),
2393    }
2394}
2395
2396/// Generates dynamic import function call trampoline for a function type.
2397pub fn gen_std_dynamic_import_trampoline(
2398    vmoffsets: &VMOffsets,
2399    sig: &FunctionType,
2400    target: &Target,
2401    calling_convention: CallingConvention,
2402    object: Option<&CompiledKind>,
2403) -> Result<CompileOutput<FunctionBody>, CompileError> {
2404    let body = match target.triple().architecture {
2405        Architecture::X86_64 => {
2406            let machine = MachineX86_64::new(Some(target.clone()))?;
2407            machine.gen_std_dynamic_import_trampoline(vmoffsets, sig, calling_convention)
2408        }
2409        Architecture::Aarch64(_) => {
2410            let machine = MachineARM64::new(Some(target.clone()));
2411            machine.gen_std_dynamic_import_trampoline(vmoffsets, sig, calling_convention)
2412        }
2413        Architecture::Riscv64(_) => {
2414            let machine = MachineRiscv::new(Some(target.clone()), false)?;
2415            machine.gen_std_dynamic_import_trampoline(vmoffsets, sig, calling_convention)
2416        }
2417        _ => Err(CompileError::UnsupportedTarget(
2418            "singlepass unimplemented arch for gen_std_dynamic_import_trampoline".to_owned(),
2419        )),
2420    }?;
2421    match object {
2422        Some(kind) => Ok(CompileOutput::Object(
2423            elf::emit_function_body(target, kind, &body)?,
2424            None,
2425        )),
2426        None => Ok(CompileOutput::InMemory(body)),
2427    }
2428}
2429/// Singlepass calls import functions through a trampoline.
2430pub fn gen_import_call_trampoline(
2431    vmoffsets: &VMOffsets,
2432    index: FunctionIndex,
2433    sig: &FunctionType,
2434    target: &Target,
2435    calling_convention: CallingConvention,
2436    experimental_artifact: bool,
2437) -> Result<CompileOutput<CustomSection>, CompileError> {
2438    let section = match target.triple().architecture {
2439        Architecture::X86_64 => {
2440            let machine = MachineX86_64::new(Some(target.clone()))?;
2441            machine.gen_import_call_trampoline(vmoffsets, index, sig, calling_convention)
2442        }
2443        Architecture::Aarch64(_) => {
2444            let machine = MachineARM64::new(Some(target.clone()));
2445            machine.gen_import_call_trampoline(vmoffsets, index, sig, calling_convention)
2446        }
2447        Architecture::Riscv64(_) => {
2448            let machine = MachineRiscv::new(Some(target.clone()), false)?;
2449            machine.gen_import_call_trampoline(vmoffsets, index, sig, calling_convention)
2450        }
2451        _ => Err(CompileError::UnsupportedTarget(
2452            "singlepass unimplemented arch for gen_import_call_trampoline".to_owned(),
2453        )),
2454    }?;
2455    if experimental_artifact {
2456        Ok(CompileOutput::Object(
2457            elf::emit_import_trampoline(
2458                target,
2459                &CompiledKind::ImportFunctionTrampoline(index, sig.to_owned()),
2460                &section,
2461            )?,
2462            None,
2463        ))
2464    } else {
2465        Ok(CompileOutput::InMemory(section))
2466    }
2467}
2468
2469// Constants for the bounds of truncation operations. These are the least or
2470// greatest exact floats in either f32 or f64 representation less-than (for
2471// least) or greater-than (for greatest) the i32 or i64 or u32 or u64
2472// min (for least) or max (for greatest), when rounding towards zero.
2473
2474/// Greatest Exact Float (32 bits) less-than i32::MIN when rounding towards zero.
2475pub const GEF32_LT_I32_MIN: f32 = -2147483904.0;
2476/// Least Exact Float (32 bits) greater-than i32::MAX when rounding towards zero.
2477pub const LEF32_GT_I32_MAX: f32 = 2147483648.0;
2478/// Greatest Exact Float (32 bits) less-than i64::MIN when rounding towards zero.
2479pub const GEF32_LT_I64_MIN: f32 = -9223373136366403584.0;
2480/// Least Exact Float (32 bits) greater-than i64::MAX when rounding towards zero.
2481pub const LEF32_GT_I64_MAX: f32 = 9223372036854775808.0;
2482/// Greatest Exact Float (32 bits) less-than u32::MIN when rounding towards zero.
2483pub const GEF32_LT_U32_MIN: f32 = -1.0;
2484/// Least Exact Float (32 bits) greater-than u32::MAX when rounding towards zero.
2485pub const LEF32_GT_U32_MAX: f32 = 4294967296.0;
2486/// Greatest Exact Float (32 bits) less-than u64::MIN when rounding towards zero.
2487pub const GEF32_LT_U64_MIN: f32 = -1.0;
2488/// Least Exact Float (32 bits) greater-than u64::MAX when rounding towards zero.
2489pub const LEF32_GT_U64_MAX: f32 = 18446744073709551616.0;
2490
2491/// Greatest Exact Float (64 bits) less-than i32::MIN when rounding towards zero.
2492pub const GEF64_LT_I32_MIN: f64 = -2147483649.0;
2493/// Least Exact Float (64 bits) greater-than i32::MAX when rounding towards zero.
2494pub const LEF64_GT_I32_MAX: f64 = 2147483648.0;
2495/// Greatest Exact Float (64 bits) less-than i64::MIN when rounding towards zero.
2496pub const GEF64_LT_I64_MIN: f64 = -9223372036854777856.0;
2497/// Least Exact Float (64 bits) greater-than i64::MAX when rounding towards zero.
2498pub const LEF64_GT_I64_MAX: f64 = 9223372036854775808.0;
2499/// Greatest Exact Float (64 bits) less-than u32::MIN when rounding towards zero.
2500pub const GEF64_LT_U32_MIN: f64 = -1.0;
2501/// Least Exact Float (64 bits) greater-than u32::MAX when rounding towards zero.
2502pub const LEF64_GT_U32_MAX: f64 = 4294967296.0;
2503/// Greatest Exact Float (64 bits) less-than u64::MIN when rounding towards zero.
2504pub const GEF64_LT_U64_MIN: f64 = -1.0;
2505/// Least Exact Float (64 bits) greater-than u64::MAX when rounding towards zero.
2506pub const LEF64_GT_U64_MAX: f64 = 18446744073709551616.0;