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