Browse Source

winch: Implement new trampolines (#6358)

* winch: Implement new trampolines

This change is a follow-up to
https://github.com/bytecodealliance/wasmtime/pull/6262, in which the new
trampolines, described [here](https://github.com/bytecodealliance/rfcs/blob/main/accepted/tail-calls.md#new-trampolines-and-vmcallercheckedanyfunc-changes),
were introduced to Wasmtime.

This change, focuses on the `array-to-wasm`,
`native-to-wasm` and `wasm-to-native` trampolines to restore Winch's
working state prior to the introduction of the new trampolines. It's
worth noting that the new approach for trampolines make it easier to support
the `TypedFunc` API in Winch. Prior to the introduction of the new
trampolines, it was not obvious how to approach it.

This change also introduces a pinned register that will hold the
`VMContext` pointer, which is loaded in the `*-to-wasm`  trampolines;
the `VMContext`  register is a pre-requisite to this change to support
the `wasm-to-native` trampolines.

Lastly, with the introduction of the `VMContext` register and the
`wasm-to-native` trampolines, this change also introduces support for
calling function imports, which is a variation of the already existing
calls to locally defined functions.

The other notable piece of this change aside from the trampolines is
`winch-codegen`'s dependency on `wasmtime-environ`. Winch is so closely
tied to the concepts exposed by the wasmtime crates that it makes sense
to tie them together, even though the separation provides some
advantages like easier testing in some cases, in the long run, there's
probably going to be less need to test Winch in isolation and rather
we'd rely more on integration style tests which require all of Wasmtime
pieces anyway (fuzzing, spec tests, etc).

This change doesn't update the  existing implmenetation of
`winch_codegen::FuncEnv`, but the intention is to update that part after
this change.

prtest:full

* tests: Ignore miri in Winch integration tests

* Remove hardcoded alignment and addend
pull/6387/head
Saúl Cabrera 2 years ago
committed by GitHub
parent
commit
20c5836295
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      Cargo.lock
  2. 63
      crates/winch/src/compiler.rs
  3. 2
      scripts/publish.rs
  4. 140
      tests/all/winch.rs
  5. 1
      winch/codegen/Cargo.toml
  6. 8
      winch/codegen/src/abi/mod.rs
  7. 79
      winch/codegen/src/codegen/call.rs
  8. 84
      winch/codegen/src/codegen/mod.rs
  9. 18
      winch/codegen/src/frame/mod.rs
  10. 8
      winch/codegen/src/isa/aarch64/abi.rs
  11. 10
      winch/codegen/src/isa/aarch64/masm.rs
  12. 12
      winch/codegen/src/isa/aarch64/mod.rs
  13. 8
      winch/codegen/src/isa/aarch64/regs.rs
  14. 22
      winch/codegen/src/isa/mod.rs
  15. 8
      winch/codegen/src/isa/x64/abi.rs
  16. 2
      winch/codegen/src/isa/x64/address.rs
  17. 22
      winch/codegen/src/isa/x64/masm.rs
  18. 32
      winch/codegen/src/isa/x64/mod.rs
  19. 22
      winch/codegen/src/isa/x64/regs.rs
  20. 2
      winch/codegen/src/lib.rs
  21. 16
      winch/codegen/src/masm.rs
  22. 11
      winch/codegen/src/regalloc.rs
  23. 5
      winch/codegen/src/stack.rs
  24. 400
      winch/codegen/src/trampoline.rs
  25. 3
      winch/codegen/src/visitor.rs
  26. 8
      winch/environ/src/lib.rs
  27. 15
      winch/filetests/filetests/aarch64/i32_add/const.wat
  28. 33
      winch/filetests/filetests/aarch64/i32_add/locals.wat
  29. 15
      winch/filetests/filetests/aarch64/i32_add/max.wat
  30. 17
      winch/filetests/filetests/aarch64/i32_add/max_one.wat
  31. 15
      winch/filetests/filetests/aarch64/i32_add/mixed.wat
  32. 23
      winch/filetests/filetests/aarch64/i32_add/params.wat
  33. 17
      winch/filetests/filetests/aarch64/i32_add/signed.wat
  34. 15
      winch/filetests/filetests/aarch64/i32_add/unsigned_with_zero.wat
  35. 15
      winch/filetests/filetests/aarch64/i64_add/const.wat
  36. 35
      winch/filetests/filetests/aarch64/i64_add/locals.wat
  37. 17
      winch/filetests/filetests/aarch64/i64_add/max.wat
  38. 17
      winch/filetests/filetests/aarch64/i64_add/max_one.wat
  39. 15
      winch/filetests/filetests/aarch64/i64_add/mixed.wat
  40. 23
      winch/filetests/filetests/aarch64/i64_add/params.wat
  41. 17
      winch/filetests/filetests/aarch64/i64_add/signed.wat
  42. 15
      winch/filetests/filetests/aarch64/i64_add/unsigned_with_zero.wat
  43. 158
      winch/filetests/filetests/x64/call/params.wat
  44. 59
      winch/filetests/filetests/x64/call/simple.wat
  45. 11
      winch/filetests/filetests/x64/i32_add/const.wat
  46. 28
      winch/filetests/filetests/x64/i32_add/locals.wat
  47. 11
      winch/filetests/filetests/x64/i32_add/max.wat
  48. 11
      winch/filetests/filetests/x64/i32_add/max_one.wat
  49. 11
      winch/filetests/filetests/x64/i32_add/mixed.wat
  50. 21
      winch/filetests/filetests/x64/i32_add/params.wat
  51. 11
      winch/filetests/filetests/x64/i32_add/signed.wat
  52. 11
      winch/filetests/filetests/x64/i32_add/unsigned_with_zero.wat
  53. 21
      winch/filetests/filetests/x64/i32_divs/const.wat
  54. 21
      winch/filetests/filetests/x64/i32_divs/one_zero.wat
  55. 21
      winch/filetests/filetests/x64/i32_divs/overflow.wat
  56. 27
      winch/filetests/filetests/x64/i32_divs/params.wat
  57. 21
      winch/filetests/filetests/x64/i32_divs/zero_zero.wat
  58. 15
      winch/filetests/filetests/x64/i32_divu/const.wat
  59. 15
      winch/filetests/filetests/x64/i32_divu/one_zero.wat
  60. 21
      winch/filetests/filetests/x64/i32_divu/params.wat
  61. 15
      winch/filetests/filetests/x64/i32_divu/signed.wat
  62. 15
      winch/filetests/filetests/x64/i32_divu/zero_zero.wat
  63. 11
      winch/filetests/filetests/x64/i32_mul/const.wat
  64. 28
      winch/filetests/filetests/x64/i32_mul/locals.wat
  65. 11
      winch/filetests/filetests/x64/i32_mul/max.wat
  66. 11
      winch/filetests/filetests/x64/i32_mul/max_one.wat
  67. 11
      winch/filetests/filetests/x64/i32_mul/mixed.wat
  68. 21
      winch/filetests/filetests/x64/i32_mul/params.wat
  69. 11
      winch/filetests/filetests/x64/i32_mul/signed.wat
  70. 11
      winch/filetests/filetests/x64/i32_mul/unsigned_with_zero.wat
  71. 25
      winch/filetests/filetests/x64/i32_rems/const.wat
  72. 25
      winch/filetests/filetests/x64/i32_rems/one_zero.wat
  73. 25
      winch/filetests/filetests/x64/i32_rems/overflow.wat
  74. 31
      winch/filetests/filetests/x64/i32_rems/params.wat
  75. 25
      winch/filetests/filetests/x64/i32_rems/zero_zero.wat
  76. 17
      winch/filetests/filetests/x64/i32_remu/const.wat
  77. 17
      winch/filetests/filetests/x64/i32_remu/one_zero.wat
  78. 23
      winch/filetests/filetests/x64/i32_remu/params.wat
  79. 17
      winch/filetests/filetests/x64/i32_remu/signed.wat
  80. 17
      winch/filetests/filetests/x64/i32_remu/zero_zero.wat
  81. 11
      winch/filetests/filetests/x64/i32_sub/const.wat
  82. 28
      winch/filetests/filetests/x64/i32_sub/locals.wat
  83. 11
      winch/filetests/filetests/x64/i32_sub/max.wat
  84. 11
      winch/filetests/filetests/x64/i32_sub/max_one.wat
  85. 11
      winch/filetests/filetests/x64/i32_sub/mixed.wat
  86. 21
      winch/filetests/filetests/x64/i32_sub/params.wat
  87. 11
      winch/filetests/filetests/x64/i32_sub/signed.wat
  88. 11
      winch/filetests/filetests/x64/i32_sub/unsigned_with_zero.wat
  89. 11
      winch/filetests/filetests/x64/i64_add/const.wat
  90. 29
      winch/filetests/filetests/x64/i64_add/locals.wat
  91. 13
      winch/filetests/filetests/x64/i64_add/max.wat
  92. 11
      winch/filetests/filetests/x64/i64_add/max_one.wat
  93. 11
      winch/filetests/filetests/x64/i64_add/mixed.wat
  94. 21
      winch/filetests/filetests/x64/i64_add/params.wat
  95. 11
      winch/filetests/filetests/x64/i64_add/signed.wat
  96. 11
      winch/filetests/filetests/x64/i64_add/unsigned_with_zero.wat
  97. 21
      winch/filetests/filetests/x64/i64_divs/const.wat
  98. 21
      winch/filetests/filetests/x64/i64_divs/one_zero.wat
  99. 21
      winch/filetests/filetests/x64/i64_divs/overflow.wat
  100. 27
      winch/filetests/filetests/x64/i64_divs/params.wat

1
Cargo.lock

@ -4431,6 +4431,7 @@ dependencies = [
"smallvec", "smallvec",
"target-lexicon", "target-lexicon",
"wasmparser 0.104.0", "wasmparser 0.104.0",
"wasmtime-environ",
] ]
[[package]] [[package]]

63
crates/winch/src/compiler.rs

@ -6,9 +6,9 @@ use wasmparser::FuncValidatorAllocations;
use wasmtime_cranelift_shared::{CompiledFunction, ModuleTextBuilder}; use wasmtime_cranelift_shared::{CompiledFunction, ModuleTextBuilder};
use wasmtime_environ::{ use wasmtime_environ::{
CompileError, DefinedFuncIndex, FilePos, FuncIndex, FunctionBodyData, FunctionLoc, CompileError, DefinedFuncIndex, FilePos, FuncIndex, FunctionBodyData, FunctionLoc,
ModuleTranslation, ModuleTypes, PrimaryMap, Tunables, WasmFunctionInfo, ModuleTranslation, ModuleTypes, PrimaryMap, Tunables, VMOffsets, WasmFunctionInfo,
}; };
use winch_codegen::TargetIsa; use winch_codegen::{TargetIsa, TrampolineKind};
use winch_environ::FuncEnv; use winch_environ::FuncEnv;
pub(crate) struct Compiler { pub(crate) struct Compiler {
@ -67,10 +67,11 @@ impl wasmtime_environ::Compiler for Compiler {
.unwrap(), .unwrap(),
); );
let mut validator = validator.into_validator(self.take_allocations()); let mut validator = validator.into_validator(self.take_allocations());
let env = FuncEnv::new(&translation.module, translation.get_types(), &self.isa); let vmoffsets = VMOffsets::new(self.isa.pointer_bytes(), &translation.module);
let env = FuncEnv::new(&translation.module, translation.get_types());
let buffer = self let buffer = self
.isa .isa
.compile_function(&sig, &body, &env, &mut validator) .compile_function(&sig, &body, &vmoffsets, &env, &mut validator)
.map_err(|e| CompileError::Codegen(format!("{e:?}"))); .map_err(|e| CompileError::Codegen(format!("{e:?}")));
self.save_allocations(validator.into_allocations()); self.save_allocations(validator.into_allocations());
let buffer = buffer?; let buffer = buffer?;
@ -92,8 +93,21 @@ impl wasmtime_environ::Compiler for Compiler {
types: &ModuleTypes, types: &ModuleTypes,
index: DefinedFuncIndex, index: DefinedFuncIndex,
) -> Result<Box<dyn Any + Send>, CompileError> { ) -> Result<Box<dyn Any + Send>, CompileError> {
let _ = (translation, types, index); let func_index = translation.module.func_index(index);
todo!() let sig = translation.module.functions[func_index].signature;
let ty = &types[sig];
let wasm_ty = wasmparser::FuncType::new(
ty.params().iter().copied().map(Into::into),
ty.returns().iter().copied().map(Into::into),
);
let buffer = self
.isa
.compile_trampoline(&wasm_ty, TrampolineKind::ArrayToWasm(func_index))
.map_err(|e| CompileError::Codegen(format!("{:?}", e)))?;
let compiled_function =
CompiledFunction::new(buffer, CompiledFuncEnv {}, self.isa.function_alignment());
Ok(Box::new(compiled_function))
} }
fn compile_native_to_wasm_trampoline( fn compile_native_to_wasm_trampoline(
@ -102,17 +116,44 @@ impl wasmtime_environ::Compiler for Compiler {
types: &ModuleTypes, types: &ModuleTypes,
index: DefinedFuncIndex, index: DefinedFuncIndex,
) -> Result<Box<dyn Any + Send>, CompileError> { ) -> Result<Box<dyn Any + Send>, CompileError> {
let _ = (translation, types, index); let func_index = translation.module.func_index(index);
todo!() let sig = translation.module.functions[func_index].signature;
let ty = &types[sig];
let wasm_ty = wasmparser::FuncType::new(
ty.params().iter().copied().map(Into::into),
ty.returns().iter().copied().map(Into::into),
);
let buffer = self
.isa
.compile_trampoline(&wasm_ty, TrampolineKind::NativeToWasm(func_index))
.map_err(|e| CompileError::Codegen(format!("{:?}", e)))?;
let compiled_function =
CompiledFunction::new(buffer, CompiledFuncEnv {}, self.isa.function_alignment());
Ok(Box::new(compiled_function))
} }
fn compile_wasm_to_native_trampoline( fn compile_wasm_to_native_trampoline(
&self, &self,
translation: &ModuleTranslation<'_>, _translation: &ModuleTranslation<'_>,
wasm_func_ty: &wasmtime_environ::WasmFuncType, wasm_func_ty: &wasmtime_environ::WasmFuncType,
) -> Result<Box<dyn Any + Send>, CompileError> { ) -> Result<Box<dyn Any + Send>, CompileError> {
let _ = (translation, wasm_func_ty); let wasm_ty = wasmparser::FuncType::new(
todo!() wasm_func_ty.params().iter().copied().map(Into::into),
wasm_func_ty.returns().iter().copied().map(Into::into),
);
let buffer = self
.isa
.compile_trampoline(&wasm_ty, TrampolineKind::WasmToNative)
.map_err(|e| CompileError::Codegen(format!("{:?}", e)))?;
let compiled_function =
CompiledFunction::new(buffer, CompiledFuncEnv {}, self.isa.function_alignment());
Ok(Box::new(compiled_function))
} }
fn append_code( fn append_code(

2
scripts/publish.rs

@ -42,7 +42,6 @@ const CRATES_TO_PUBLISH: &[&str] = &[
"wiggle-generate", "wiggle-generate",
"wiggle-macro", "wiggle-macro",
// winch // winch
"winch-codegen",
"winch", "winch",
// wasmtime // wasmtime
"wasmtime-asm-macros", "wasmtime-asm-macros",
@ -57,6 +56,7 @@ const CRATES_TO_PUBLISH: &[&str] = &[
"wasmtime-cranelift", "wasmtime-cranelift",
"wasmtime-jit", "wasmtime-jit",
"wasmtime-cache", "wasmtime-cache",
"winch-codegen",
"winch-environ", "winch-environ",
"wasmtime-winch", "wasmtime-winch",
"wasmtime", "wasmtime",

140
tests/all/winch.rs

@ -1,58 +1,12 @@
use anyhow::Result;
use wasmtime::*; use wasmtime::*;
#[test] const MODULE: &'static str = r#"
#[ignore]
fn compiles_with_winch() -> Result<()> {
let mut c = Config::new();
c.strategy(Strategy::Winch);
let engine = Engine::new(&c)?;
// Winch only supports a very basic function signature for now while it's being developed.
let test_mod = r#"
(module (module
(import "" "" (func $add (param i32 i32) (result i32)))
(func $test (result i32) (func $test (result i32)
(i32.const 42) (i32.const 42)
) )
(export "test" (func $test))
)
"#;
let mut store = Store::new(&engine, ());
let module = Module::new(&engine, test_mod)?;
let instance = Instance::new(&mut store, &module, &[])?;
let f = instance
.get_func(&mut store, "test")
.ok_or(anyhow::anyhow!("test function not found"))?;
let mut returns = vec![Val::null(); 1];
// Winch doesn't support calling typed functions at the moment.
f.call(&mut store, &[], &mut returns)?;
assert_eq!(returns.len(), 1);
assert_eq!(returns[0].unwrap_i32(), 42);
Ok(())
}
#[test]
#[ignore]
fn compiles_with_winch_stack_arguments() -> Result<()> {
let mut c = Config::new();
c.strategy(Strategy::Winch);
let engine = Engine::new(&c)?;
// Winch only supports a very basic function signature for now while it's being developed.
let test_mod = r#"
(module
(func $sum10 (param $arg_1 i32) (param $arg_2 i32) (param $arg_3 i32) (param $arg_4 i32) (param $arg_5 i32) (param $arg_6 i32) (param $arg_7 i32) (param $arg_8 i32) (param $arg_9 i32) (param $arg_10 i32) (result i32) (func $sum10 (param $arg_1 i32) (param $arg_2 i32) (param $arg_3 i32) (param $arg_4 i32) (param $arg_5 i32) (param $arg_6 i32) (param $arg_7 i32) (param $arg_8 i32) (param $arg_9 i32) (param $arg_10 i32) (result i32)
local.get $arg_1 local.get $arg_1
local.get $arg_2 local.get $arg_2
@ -73,30 +27,98 @@ fn compiles_with_winch_stack_arguments() -> Result<()> {
i32.add i32.add
local.get $arg_10 local.get $arg_10
i32.add) i32.add)
(func $call_add (param i32 i32) (result i32)
(local.get 0)
(local.get 1)
(call $add))
(export "42" (func $test))
(export "sum10" (func $sum10)) (export "sum10" (func $sum10))
(export "call_add" (func $call_add))
) )
"#; "#;
fn add_fn(store: impl AsContextMut) -> Func {
Func::wrap(store, |a: i32, b: i32| a + b)
}
#[test]
#[cfg_attr(miri, ignore)]
fn array_to_wasm() {
let mut c = Config::new();
c.strategy(Strategy::Winch);
let engine = Engine::new(&c).unwrap();
let mut store = Store::new(&engine, ()); let mut store = Store::new(&engine, ());
let module = Module::new(&engine, MODULE).unwrap();
let module = Module::new(&engine, test_mod)?; let add_fn = add_fn(store.as_context_mut());
let instance = Instance::new(&mut store, &module, &[add_fn.into()]).unwrap();
let instance = Instance::new(&mut store, &module, &[])?; let constant = instance
.get_func(&mut store, "42")
.ok_or(anyhow::anyhow!("test function not found"))
.unwrap();
let mut returns = vec![Val::null(); 1];
constant.call(&mut store, &[], &mut returns).unwrap();
let f = instance assert_eq!(returns.len(), 1);
.get_func(&mut store, "sum10") assert_eq!(returns[0].unwrap_i32(), 42);
.ok_or(anyhow::anyhow!("sum10 function not found"))?;
let sum = instance
.get_func(&mut store, "sum10")
.ok_or(anyhow::anyhow!("sum10 function not found"))
.unwrap();
let mut returns = vec![Val::null(); 1]; let mut returns = vec![Val::null(); 1];
// create a new Val array with ten 1s
let args = vec![Val::I32(1); 10]; let args = vec![Val::I32(1); 10];
sum.call(&mut store, &args, &mut returns).unwrap();
// Winch doesn't support calling typed functions at the moment.
f.call(&mut store, &args, &mut returns)?;
assert_eq!(returns.len(), 1); assert_eq!(returns.len(), 1);
assert_eq!(returns[0].unwrap_i32(), 10); assert_eq!(returns[0].unwrap_i32(), 10);
}
#[test]
#[cfg_attr(miri, ignore)]
fn native_to_wasm() {
let mut c = Config::new();
c.strategy(Strategy::Winch);
let engine = Engine::new(&c).unwrap();
let mut store = Store::new(&engine, ());
let module = Module::new(&engine, MODULE).unwrap();
let add_fn = add_fn(store.as_context_mut());
let instance = Instance::new(&mut store, &module, &[add_fn.into()]).unwrap();
let f = instance
.get_typed_func::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), i32>(
&mut store, "sum10",
)
.unwrap();
let args = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
let result = f.call(&mut store, args).unwrap();
assert_eq!(result, 10);
}
#[test]
#[cfg_attr(miri, ignore)]
fn wasm_to_native() {
let mut c = Config::new();
c.strategy(Strategy::Winch);
let engine = Engine::new(&c).unwrap();
let mut store = Store::new(&engine, ());
let module = Module::new(&engine, MODULE).unwrap();
let add_fn = add_fn(store.as_context_mut());
let instance = Instance::new(&mut store, &module, &[add_fn.into()]).unwrap();
let f = instance
.get_typed_func::<(i32, i32), i32>(&mut store, "call_add")
.unwrap();
let args = (41, 1);
let result = f.call(&mut store, args).unwrap();
Ok(()) assert_eq!(result, 42);
} }

1
winch/codegen/Cargo.toml

@ -19,6 +19,7 @@ target-lexicon = { workspace = true, features = ["std"] }
cranelift-codegen = { workspace = true } cranelift-codegen = { workspace = true }
regalloc2 = { workspace = true } regalloc2 = { workspace = true }
gimli = { workspace = true } gimli = { workspace = true }
wasmtime-environ = { workspace = true }
[features] [features]
x64 = ["cranelift-codegen/x86"] x64 = ["cranelift-codegen/x86"]

8
winch/codegen/src/abi/mod.rs

@ -33,6 +33,7 @@
//! | | //! | |
//! | | //! | |
//! | Stack slots | //! | Stack slots |
//! | + `VMContext` slot |
//! | + dynamic space | //! | + dynamic space |
//! | | //! | |
//! | | //! | |
@ -78,6 +79,13 @@ pub(crate) trait ABI {
/// Returns the designated scratch register. /// Returns the designated scratch register.
fn scratch_reg() -> Reg; fn scratch_reg() -> Reg;
/// Returns the frame pointer register.
fn fp_reg() -> Reg;
/// Returns the pinned register used to hold
/// the `VMContext`.
fn vmctx_reg() -> Reg;
/// Returns the callee-saved registers for the given /// Returns the callee-saved registers for the given
/// calling convention. /// calling convention.
fn callee_saved_regs(call_conv: &CallingConvention) -> SmallVec<[Reg; 9]>; fn callee_saved_regs(call_conv: &CallingConvention) -> SmallVec<[Reg; 9]>;

79
winch/codegen/src/codegen/call.rs

@ -2,23 +2,21 @@
//! calling convention, see [ABI]. //! calling convention, see [ABI].
use super::CodeGenContext; use super::CodeGenContext;
use crate::{ use crate::{
abi::{align_to, calculate_frame_adjustment, ABIArg, ABIResult, ABISig, ABI}, abi::{ABIArg, ABIResult, ABISig, ABI},
masm::{CalleeKind, MacroAssembler, OperandSize}, masm::{CalleeKind, MacroAssembler, OperandSize},
reg::Reg, reg::Reg,
stack::Val, stack::Val,
}; };
use wasmtime_environ::FuncIndex;
/// All the information needed to emit a function call. /// All the information needed to emit a function call.
pub(crate) struct FnCall<'a> { pub(crate) struct FnCall<'a> {
/// The total stack space in bytes used by the function call. /// The stack space consumed by the function call; that is,
/// This amount includes the sum of: /// the sum of:
/// ///
/// 1. The amount of stack space that needs to be explicitly /// 1. The amount of stack space created by saving any live
/// allocated at the callsite for callee arguments that
/// go in the stack, plus any alignment.
/// 2. The amount of stack space created by saving any live
/// registers at the callsite. /// registers at the callsite.
/// 3. The amount of space used by any memory entries in the value /// 2. The amount of space used by any memory entries in the value
/// stack present at the callsite, that will be used as /// stack present at the callsite, that will be used as
/// arguments for the function call. Any memory values in the /// arguments for the function call. Any memory values in the
/// value stack that are needed as part of the function /// value stack that are needed as part of the function
@ -33,17 +31,17 @@ pub(crate) struct FnCall<'a> {
/// assigned); it's more efficient to track the space needed by /// assigned); it's more efficient to track the space needed by
/// those memory values and reclaim it at once. /// those memory values and reclaim it at once.
/// ///
/// The machine stack state that this amount is capturing, is the following: /// The machine stack throghout the function call is as follows:
/// ┌──────────────────────────────────────────────────┐ /// ┌──────────────────────────────────────────────────┐
/// │ │ /// │ │
/// │ /// │ 1
/// │ Stack space created by any previous spills │ /// │ Stack space created by any previous spills │
/// │ from the value stack; and which memory values │ /// │ from the value stack; and which memory values │
/// │ are used as function arguments. │ /// │ are used as function arguments. │
/// │ │ /// │ │
/// ├──────────────────────────────────────────────────┤ ---> The Wasm value stack at this point in time would look like: /// ├──────────────────────────────────────────────────┤ ---> The Wasm value stack at this point in time would look like:
/// │ │ [ Reg | Reg | Mem(offset) | Mem(offset) ] /// │ │ [ Reg | Reg | Mem(offset) | Mem(offset) ]
/// │ /// │ 2
/// │ Stack space created by saving │ /// │ Stack space created by saving │
/// │ any live registers at the callsite. │ /// │ any live registers at the callsite. │
/// │ │ /// │ │
@ -60,7 +58,7 @@ pub(crate) struct FnCall<'a> {
/// │ │ /// │ │
/// └──────────────────────────────────────────────────┘ ------> Stack pointer when emitting the call /// └──────────────────────────────────────────────────┘ ------> Stack pointer when emitting the call
/// ///
total_stack_space: u32, call_stack_space: u32,
/// The total stack space needed for the callee arguments on the /// The total stack space needed for the callee arguments on the
/// stack, including any adjustments to the function's frame and /// stack, including any adjustments to the function's frame and
/// aligned to to the required ABI alignment. /// aligned to to the required ABI alignment.
@ -87,7 +85,6 @@ impl<'a> FnCall<'a> {
/// having saved any live registers, so that we can account for /// having saved any live registers, so that we can account for
/// any pushes generated by register spilling. /// any pushes generated by register spilling.
pub fn new<A: ABI, M: MacroAssembler>( pub fn new<A: ABI, M: MacroAssembler>(
abi: &A,
callee_sig: &'a ABISig, callee_sig: &'a ABISig,
context: &mut CodeGenContext, context: &mut CodeGenContext,
masm: &mut M, masm: &mut M,
@ -135,34 +132,56 @@ impl<'a> FnCall<'a> {
} }
}; };
let delta = calculate_frame_adjustment(
masm.sp_offset(),
abi.arg_base_offset() as u32,
abi.call_stack_align() as u32,
);
let arg_stack_space = align_to(arg_stack_space + delta, abi.call_stack_align() as u32);
Self { Self {
abi_sig: &callee_sig, abi_sig: &callee_sig,
arg_stack_space, arg_stack_space,
total_stack_space: (spilled_regs * <A as ABI>::word_bytes()) call_stack_space: (spilled_regs * <A as ABI>::word_bytes())
+ (memory_values * <A as ABI>::word_bytes()) + (memory_values * <A as ABI>::word_bytes()),
+ arg_stack_space,
sp_offset_at_callsite, sp_offset_at_callsite,
} }
} }
/// Emit the function call. /// Emit a direct function call, to a locally defined function.
pub fn emit<M: MacroAssembler, A: ABI>( pub fn direct<M: MacroAssembler, A: ABI>(
&self,
masm: &mut M,
context: &mut CodeGenContext,
callee: FuncIndex,
alignment: u32,
addend: u32,
) {
let reserved_stack = masm.call(alignment, addend, self.arg_stack_space, |masm| {
self.assign_args(context, masm, <A as ABI>::scratch_reg());
CalleeKind::Direct(callee.as_u32())
});
self.post_call::<M, A>(masm, context, reserved_stack);
}
/// Emit an indirect function call, using a raw address.
pub fn indirect<M: MacroAssembler, A: ABI>(
&self,
masm: &mut M,
context: &mut CodeGenContext,
addr: M::Address,
alignment: u32,
addend: u32,
) {
let reserved_stack = masm.call(alignment, addend, self.arg_stack_space, |masm| {
let scratch = <A as ABI>::scratch_reg();
self.assign_args(context, masm, scratch);
masm.load(addr, scratch, OperandSize::S64);
CalleeKind::Indirect(scratch)
});
self.post_call::<M, A>(masm, context, reserved_stack);
}
fn post_call<M: MacroAssembler, A: ABI>(
&self, &self,
masm: &mut M, masm: &mut M,
context: &mut CodeGenContext, context: &mut CodeGenContext,
callee: u32, size: u32,
) { ) {
masm.reserve_stack(self.arg_stack_space); masm.free_stack(self.call_stack_space + size);
self.assign_args(context, masm, <A as ABI>::scratch_reg());
masm.call(CalleeKind::Direct(callee));
masm.free_stack(self.total_stack_space);
context.drop_last(self.abi_sig.params.len()); context.drop_last(self.abi_sig.params.len());
// The stack pointer at the end of the function call // The stack pointer at the end of the function call
// cannot be less than what it was when starting the // cannot be less than what it was when starting the

84
winch/codegen/src/codegen/mod.rs

@ -1,11 +1,15 @@
use crate::{ use crate::{
abi::{ABISig, ABI}, abi::{ABISig, ABI},
masm::{MacroAssembler, OperandSize}, masm::{MacroAssembler, OperandSize},
stack::Val,
CallingConvention, CallingConvention,
}; };
use anyhow::Result; use anyhow::Result;
use call::FnCall; use call::FnCall;
use wasmparser::{BinaryReader, FuncValidator, ValType, ValidatorResources, VisitOperator}; use wasmparser::{
BinaryReader, FuncType, FuncValidator, ValType, ValidatorResources, VisitOperator,
};
use wasmtime_environ::{FuncIndex, VMOffsets};
mod context; mod context;
pub(crate) use context::*; pub(crate) use context::*;
@ -33,6 +37,9 @@ where
/// A reference to the current ABI. /// A reference to the current ABI.
pub abi: &'a A, pub abi: &'a A,
/// Offsets used with the VM context pointer.
vmoffsets: &'a VMOffsets<u8>,
} }
impl<'a, A, M> CodeGen<'a, A, M> impl<'a, A, M> CodeGen<'a, A, M>
@ -46,6 +53,7 @@ where
context: CodeGenContext<'a>, context: CodeGenContext<'a>,
env: &'a dyn FuncEnv, env: &'a dyn FuncEnv,
sig: ABISig, sig: ABISig,
vmoffsets: &'a VMOffsets<u8>,
) -> Self { ) -> Self {
Self { Self {
sig, sig,
@ -53,6 +61,7 @@ where
masm, masm,
abi, abi,
env, env,
vmoffsets,
} }
} }
@ -89,6 +98,12 @@ where
&mut self.context.regalloc, &mut self.context.regalloc,
); );
// Save the vmctx pointer to its local slot in case we need to reload it
// at any point.
let vmctx_addr = self.masm.local_address(&self.context.frame.vmctx_slot);
self.masm
.store(<A as ABI>::vmctx_reg().into(), vmctx_addr, OperandSize::S64);
while !body.eof() { while !body.eof() {
let offset = body.original_position(); let offset = body.original_position();
body.visit_operator(&mut ValidateThenVisit(validator.visitor(offset), self))??; body.visit_operator(&mut ValidateThenVisit(validator.visitor(offset), self))??;
@ -121,16 +136,61 @@ where
} }
/// Emit a direct function call. /// Emit a direct function call.
pub fn emit_call(&mut self, index: u32) { pub fn emit_call(&mut self, index: FuncIndex) {
let callee = self.env.callee_from_index(index); let callee = self.env.callee_from_index(index.as_u32());
if callee.import { let (sig, callee_addr): (ABISig, Option<<M as MacroAssembler>::Address>) = if callee.import
// TODO: Only locally defined functions for now. {
unreachable!() let mut params = vec![ValType::I64, ValType::I64];
params.extend_from_slice(&callee.ty.params());
let sig = FuncType::new(params, callee.ty.results().to_owned());
let caller_vmctx = <A as ABI>::vmctx_reg();
let callee_vmctx = self.context.any_gpr(self.masm);
let callee_vmctx_offset = self.vmoffsets.vmctx_vmfunction_import_vmctx(index);
let callee_vmctx_addr = self.masm.address_at_reg(caller_vmctx, callee_vmctx_offset);
// FIXME Remove harcoded operand size, this will be needed
// once 32-bit architectures are supported.
self.masm
.load(callee_vmctx_addr, callee_vmctx, OperandSize::S64);
let callee_body_offset = self.vmoffsets.vmctx_vmfunction_import_wasm_call(index);
let callee_addr = self.masm.address_at_reg(caller_vmctx, callee_body_offset);
// Put the callee / caller vmctx at the start of the
// range of the stack so that they are used as first
// and second arguments.
let stack = &mut self.context.stack;
let location = stack.len() - (sig.params().len() - 2);
stack.insert(location as usize, Val::reg(caller_vmctx));
stack.insert(location as usize, Val::reg(callee_vmctx));
(
self.abi.sig(&sig, &CallingConvention::Default),
Some(callee_addr),
)
} else {
(self.abi.sig(&callee.ty, &CallingConvention::Default), None)
};
let fncall = FnCall::new::<A, M>(&sig, &mut self.context, self.masm);
let alignment = self.abi.call_stack_align();
let addend = self.abi.arg_base_offset();
if let Some(addr) = callee_addr {
fncall.indirect::<M, A>(
self.masm,
&mut self.context,
addr,
alignment.into(),
addend.into(),
);
} else {
fncall.direct::<M, A>(
self.masm,
&mut self.context,
index,
alignment.into(),
addend.into(),
);
} }
let sig = self.abi.sig(&callee.ty, &CallingConvention::Default);
let fncall = FnCall::new(self.abi, &sig, &mut self.context, self.masm);
fncall.emit::<M, A>(self.masm, &mut self.context, index);
} }
/// Emit the usual function end instruction sequence. /// Emit the usual function end instruction sequence.
@ -141,10 +201,6 @@ where
} }
fn spill_register_arguments(&mut self) { fn spill_register_arguments(&mut self) {
// TODO
// Revisit this once the implicit VMContext argument is introduced;
// when that happens the mapping between local slots and abi args
// is not going to be symmetric.
self.sig self.sig
.params .params
.iter() .iter()

18
winch/codegen/src/frame/mod.rs

@ -20,7 +20,7 @@ impl DefinedLocalsRange {
} }
} }
/// An abstraction to read the defined locals from the WASM binary for a function. /// An abstraction to read the defined locals from the Wasm binary for a function.
#[derive(Default)] #[derive(Default)]
pub(crate) struct DefinedLocals { pub(crate) struct DefinedLocals {
/// The defined locals for a function. /// The defined locals for a function.
@ -30,13 +30,13 @@ pub(crate) struct DefinedLocals {
} }
impl DefinedLocals { impl DefinedLocals {
/// Compute the local slots for a WASM function. /// Compute the local slots for a Wasm function.
pub fn new( pub fn new(
reader: &mut BinaryReader<'_>, reader: &mut BinaryReader<'_>,
validator: &mut FuncValidator<ValidatorResources>, validator: &mut FuncValidator<ValidatorResources>,
) -> Result<Self> { ) -> Result<Self> {
let mut next_stack = 0; let mut next_stack = 0;
// The first 32 bits of a WASM binary function describe the number of locals // The first 32 bits of a Wasm binary function describe the number of locals.
let local_count = reader.read_var_u32()?; let local_count = reader.read_var_u32()?;
let mut slots: Locals = Default::default(); let mut slots: Locals = Default::default();
@ -74,6 +74,9 @@ pub(crate) struct Frame {
/// Locals get calculated when allocating a frame and are readonly /// Locals get calculated when allocating a frame and are readonly
/// through the function compilation lifetime. /// through the function compilation lifetime.
pub locals: Locals, pub locals: Locals,
/// The offset to the slot containing the `VMContext`.
pub vmctx_slot: LocalSlot,
} }
impl Frame { impl Frame {
@ -90,14 +93,15 @@ impl Frame {
.map(|l| LocalSlot::new(l.ty, l.offset + defined_locals_start)), .map(|l| LocalSlot::new(l.ty, l.offset + defined_locals_start)),
); );
let locals_size = align_to( let vmctx_slots_size = <A as ABI>::word_bytes();
defined_locals_start + defined_locals.stack_size, let vmctx_offset = defined_locals_start + defined_locals.stack_size + vmctx_slots_size;
abi.stack_align().into(),
); let locals_size = align_to(vmctx_offset, abi.stack_align().into());
Ok(Self { Ok(Self {
locals, locals,
locals_size, locals_size,
vmctx_slot: LocalSlot::i64(vmctx_offset),
defined_locals_range: DefinedLocalsRange( defined_locals_range: DefinedLocalsRange(
defined_locals_start..defined_locals.stack_size, defined_locals_start..defined_locals.stack_size,
), ),

8
winch/codegen/src/isa/aarch64/abi.rs

@ -87,6 +87,14 @@ impl ABI for Aarch64ABI {
todo!() todo!()
} }
fn fp_reg() -> Reg {
regs::fp()
}
fn vmctx_reg() -> Reg {
regs::xreg(9)
}
fn callee_saved_regs(_call_conv: &CallingConvention) -> SmallVec<[Reg; 9]> { fn callee_saved_regs(_call_conv: &CallingConvention) -> SmallVec<[Reg; 9]> {
regs::callee_saved() regs::callee_saved()
} }

10
winch/codegen/src/isa/aarch64/masm.rs

@ -136,7 +136,13 @@ impl Masm for MacroAssembler {
self.asm.str(src, dst, size); self.asm.str(src, dst, size);
} }
fn call(&mut self, _callee: CalleeKind) { fn call(
&mut self,
_alignment: u32,
_addend: u32,
_stack_args_size: u32,
_load_callee: impl FnMut(&mut Self) -> CalleeKind,
) -> u32 {
todo!() todo!()
} }
@ -195,7 +201,7 @@ impl Masm for MacroAssembler {
self.sp_offset self.sp_offset
} }
fn address_from_reg(&self, reg: Reg, offset: u32) -> Self::Address { fn address_at_reg(&self, reg: Reg, offset: u32) -> Self::Address {
Address::offset(reg, offset as i64) Address::offset(reg, offset as i64)
} }
} }

12
winch/codegen/src/isa/aarch64/mod.rs

@ -8,7 +8,7 @@ use crate::{
regalloc::RegAlloc, regalloc::RegAlloc,
regset::RegSet, regset::RegSet,
stack::Stack, stack::Stack,
FuncEnv, FuncEnv, TrampolineKind,
}; };
use anyhow::Result; use anyhow::Result;
use cranelift_codegen::settings::{self, Flags}; use cranelift_codegen::settings::{self, Flags};
@ -17,6 +17,7 @@ use cranelift_codegen::{MachTextSectionBuilder, TextSectionBuilder};
use masm::MacroAssembler as Aarch64Masm; use masm::MacroAssembler as Aarch64Masm;
use target_lexicon::Triple; use target_lexicon::Triple;
use wasmparser::{FuncType, FuncValidator, FunctionBody, ValidatorResources}; use wasmparser::{FuncType, FuncValidator, FunctionBody, ValidatorResources};
use wasmtime_environ::VMOffsets;
mod abi; mod abi;
mod address; mod address;
@ -85,6 +86,7 @@ impl TargetIsa for Aarch64 {
&self, &self,
sig: &FuncType, sig: &FuncType,
body: &FunctionBody, body: &FunctionBody,
vmoffsets: &VMOffsets<u8>,
env: &dyn FuncEnv, env: &dyn FuncEnv,
validator: &mut FuncValidator<ValidatorResources>, validator: &mut FuncValidator<ValidatorResources>,
) -> Result<MachBufferFinalized<Final>> { ) -> Result<MachBufferFinalized<Final>> {
@ -99,7 +101,7 @@ impl TargetIsa for Aarch64 {
// TODO: Add floating point bitmask // TODO: Add floating point bitmask
let regalloc = RegAlloc::new(RegSet::new(ALL_GPR, 0), scratch()); let regalloc = RegAlloc::new(RegSet::new(ALL_GPR, 0), scratch());
let codegen_context = CodeGenContext::new(regalloc, stack, &frame); let codegen_context = CodeGenContext::new(regalloc, stack, &frame);
let mut codegen = CodeGen::new(&mut masm, &abi, codegen_context, env, abi_sig); let mut codegen = CodeGen::new(&mut masm, &abi, codegen_context, env, abi_sig, vmoffsets);
codegen.emit(&mut body, validator)?; codegen.emit(&mut body, validator)?;
Ok(masm.finalize()) Ok(masm.finalize())
@ -116,7 +118,11 @@ impl TargetIsa for Aarch64 {
32 32
} }
fn host_to_wasm_trampoline(&self, _ty: &FuncType) -> Result<MachBufferFinalized<Final>> { fn compile_trampoline(
&self,
_ty: &FuncType,
_kind: TrampolineKind,
) -> Result<MachBufferFinalized<Final>> {
todo!() todo!()
} }
} }

8
winch/codegen/src/isa/aarch64/regs.rs

@ -53,6 +53,11 @@ pub(crate) const fn zero() -> Reg {
xreg(31) xreg(31)
} }
/// The VM context register.
pub(crate) const fn vmctx() -> Reg {
xreg(9)
}
/// Stack pointer register. /// Stack pointer register.
/// ///
/// In aarch64 the zero and stack pointer registers are contextually /// In aarch64 the zero and stack pointer registers are contextually
@ -132,7 +137,8 @@ const NON_ALLOCATABLE_GPR: u32 = (1 << ip0().hw_enc())
| (1 << fp().hw_enc()) | (1 << fp().hw_enc())
| (1 << lr().hw_enc()) | (1 << lr().hw_enc())
| (1 << zero().hw_enc()) | (1 << zero().hw_enc())
| (1 << shadow_sp().hw_enc()); | (1 << shadow_sp().hw_enc())
| (1 << vmctx().hw_enc());
/// Bitmask to represent the available general purpose registers. /// Bitmask to represent the available general purpose registers.
pub(crate) const ALL_GPR: u32 = u32::MAX & !NON_ALLOCATABLE_GPR; pub(crate) const ALL_GPR: u32 = u32::MAX & !NON_ALLOCATABLE_GPR;

22
winch/codegen/src/isa/mod.rs

@ -1,3 +1,4 @@
use crate::{FuncEnv, TrampolineKind};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use core::fmt::Formatter; use core::fmt::Formatter;
use cranelift_codegen::isa::{CallConv, IsaBuilder}; use cranelift_codegen::isa::{CallConv, IsaBuilder};
@ -9,8 +10,7 @@ use std::{
}; };
use target_lexicon::{Architecture, Triple}; use target_lexicon::{Architecture, Triple};
use wasmparser::{FuncType, FuncValidator, FunctionBody, ValidatorResources}; use wasmparser::{FuncType, FuncValidator, FunctionBody, ValidatorResources};
use wasmtime_environ::VMOffsets;
use crate::FuncEnv;
#[cfg(feature = "x64")] #[cfg(feature = "x64")]
pub(crate) mod x64; pub(crate) mod x64;
@ -149,6 +149,7 @@ pub trait TargetIsa: Send + Sync {
&self, &self,
sig: &FuncType, sig: &FuncType,
body: &FunctionBody, body: &FunctionBody,
vmoffsets: &VMOffsets<u8>,
env: &dyn FuncEnv, env: &dyn FuncEnv,
validator: &mut FuncValidator<ValidatorResources>, validator: &mut FuncValidator<ValidatorResources>,
) -> Result<MachBufferFinalized<Final>>; ) -> Result<MachBufferFinalized<Final>>;
@ -186,8 +187,21 @@ pub trait TargetIsa: Send + Sync {
/// See `cranelift_codegen::isa::TargetIsa::function_alignment`. /// See `cranelift_codegen::isa::TargetIsa::function_alignment`.
fn function_alignment(&self) -> u32; fn function_alignment(&self) -> u32;
/// Generate a trampoline that can be used to call a wasm function from wasmtime. /// Compile a trampoline kind.
fn host_to_wasm_trampoline(&self, ty: &FuncType) -> Result<MachBufferFinalized<Final>>; ///
/// This function, internally dispatches to the right trampoline to emit
/// depending on the `kind` paramter.
fn compile_trampoline(
&self,
ty: &FuncType,
kind: TrampolineKind,
) -> Result<MachBufferFinalized<Final>>;
/// Returns the pointer width of the ISA in bytes.
fn pointer_bytes(&self) -> u8 {
let width = self.triple().pointer_width().unwrap();
width.bytes()
}
} }
impl Debug for &dyn TargetIsa { impl Debug for &dyn TargetIsa {

8
winch/codegen/src/isa/x64/abi.rs

@ -121,6 +121,14 @@ impl ABI for X64ABI {
regs::scratch() regs::scratch()
} }
fn fp_reg() -> Reg {
regs::rbp()
}
fn vmctx_reg() -> Reg {
regs::vmctx()
}
fn callee_saved_regs(call_conv: &CallingConvention) -> SmallVec<[Reg; 9]> { fn callee_saved_regs(call_conv: &CallingConvention) -> SmallVec<[Reg; 9]> {
regs::callee_saved(call_conv) regs::callee_saved(call_conv)
} }

2
winch/codegen/src/isa/x64/address.rs

@ -10,7 +10,7 @@ pub(crate) enum Address {
} }
impl Address { impl Address {
/// Create an offset /// Create an offset.
pub fn offset(base: Reg, offset: u32) -> Self { pub fn offset(base: Reg, offset: u32) -> Self {
Self::Offset { base, offset } Self::Offset { base, offset }
} }

22
winch/codegen/src/isa/x64/masm.rs

@ -4,7 +4,11 @@ use super::{
regs::{self, rbp, rsp}, regs::{self, rbp, rsp},
}; };
use crate::masm::{DivKind, MacroAssembler as Masm, OperandSize, RegImm, RemKind}; use crate::masm::{DivKind, MacroAssembler as Masm, OperandSize, RegImm, RemKind};
use crate::{abi::LocalSlot, codegen::CodeGenContext, stack::Val}; use crate::{
abi::{align_to, calculate_frame_adjustment, LocalSlot},
codegen::CodeGenContext,
stack::Val,
};
use crate::{isa::reg::Reg, masm::CalleeKind}; use crate::{isa::reg::Reg, masm::CalleeKind};
use cranelift_codegen::{isa::x64::settings as x64_settings, settings, Final, MachBufferFinalized}; use cranelift_codegen::{isa::x64::settings as x64_settings, settings, Final, MachBufferFinalized};
@ -114,8 +118,20 @@ impl Masm for MacroAssembler {
self.decrement_sp(8); self.decrement_sp(8);
} }
fn call(&mut self, callee: CalleeKind) { fn call(
&mut self,
alignment: u32,
addend: u32,
stack_args_size: u32,
mut load_callee: impl FnMut(&mut Self) -> CalleeKind,
) -> u32 {
let delta = calculate_frame_adjustment(self.sp_offset(), addend, alignment);
let aligned_args_size = align_to(stack_args_size, alignment);
let total_stack = delta + aligned_args_size;
self.reserve_stack(total_stack);
let callee = load_callee(self);
self.asm.call(callee); self.asm.call(callee);
total_stack
} }
fn load(&mut self, src: Address, dst: Reg, size: OperandSize) { fn load(&mut self, src: Address, dst: Reg, size: OperandSize) {
@ -237,7 +253,7 @@ impl Masm for MacroAssembler {
self.asm.finalize() self.asm.finalize()
} }
fn address_from_reg(&self, reg: Reg, offset: u32) -> Self::Address { fn address_at_reg(&self, reg: Reg, offset: u32) -> Self::Address {
Address::offset(reg, offset) Address::offset(reg, offset)
} }
} }

32
winch/codegen/src/isa/x64/mod.rs

@ -8,18 +8,19 @@ use crate::isa::{x64::masm::MacroAssembler as X64Masm, CallingConvention};
use crate::masm::MacroAssembler; use crate::masm::MacroAssembler;
use crate::regalloc::RegAlloc; use crate::regalloc::RegAlloc;
use crate::stack::Stack; use crate::stack::Stack;
use crate::trampoline::Trampoline;
use crate::FuncEnv; use crate::FuncEnv;
use crate::{ use crate::{
isa::{Builder, TargetIsa}, isa::{Builder, TargetIsa},
regset::RegSet, regset::RegSet,
}; };
use crate::{Trampoline, TrampolineKind};
use anyhow::Result; use anyhow::Result;
use cranelift_codegen::settings::{self, Flags}; use cranelift_codegen::settings::{self, Flags};
use cranelift_codegen::{isa::x64::settings as x64_settings, Final, MachBufferFinalized}; use cranelift_codegen::{isa::x64::settings as x64_settings, Final, MachBufferFinalized};
use cranelift_codegen::{MachTextSectionBuilder, TextSectionBuilder}; use cranelift_codegen::{MachTextSectionBuilder, TextSectionBuilder};
use target_lexicon::Triple; use target_lexicon::Triple;
use wasmparser::{FuncType, FuncValidator, FunctionBody, ValidatorResources}; use wasmparser::{FuncType, FuncValidator, FunctionBody, ValidatorResources};
use wasmtime_environ::VMOffsets;
use self::regs::ALL_GPR; use self::regs::ALL_GPR;
@ -90,6 +91,7 @@ impl TargetIsa for X64 {
&self, &self,
sig: &FuncType, sig: &FuncType,
body: &FunctionBody, body: &FunctionBody,
vmoffsets: &VMOffsets<u8>,
env: &dyn FuncEnv, env: &dyn FuncEnv,
validator: &mut FuncValidator<ValidatorResources>, validator: &mut FuncValidator<ValidatorResources>,
) -> Result<MachBufferFinalized<Final>> { ) -> Result<MachBufferFinalized<Final>> {
@ -104,7 +106,7 @@ impl TargetIsa for X64 {
// TODO Add in floating point bitmask // TODO Add in floating point bitmask
let regalloc = RegAlloc::new(RegSet::new(ALL_GPR, 0), regs::scratch()); let regalloc = RegAlloc::new(RegSet::new(ALL_GPR, 0), regs::scratch());
let codegen_context = CodeGenContext::new(regalloc, stack, &frame); let codegen_context = CodeGenContext::new(regalloc, stack, &frame);
let mut codegen = CodeGen::new(&mut masm, &abi, codegen_context, env, abi_sig); let mut codegen = CodeGen::new(&mut masm, &abi, codegen_context, env, abi_sig, vmoffsets);
codegen.emit(&mut body, validator)?; codegen.emit(&mut body, validator)?;
@ -120,15 +122,31 @@ impl TargetIsa for X64 {
16 16
} }
fn host_to_wasm_trampoline(&self, ty: &FuncType) -> Result<MachBufferFinalized<Final>> { fn compile_trampoline(
&self,
ty: &FuncType,
kind: TrampolineKind,
) -> Result<MachBufferFinalized<Final>> {
use TrampolineKind::*;
let abi = abi::X64ABI::default(); let abi = abi::X64ABI::default();
let mut masm = X64Masm::new(self.shared_flags.clone(), self.isa_flags.clone()); let mut masm = X64Masm::new(self.shared_flags.clone(), self.isa_flags.clone());
let call_conv = self.wasmtime_call_conv(); let call_conv = self.wasmtime_call_conv();
let mut trampoline = let mut trampoline = Trampoline::new(
Trampoline::new(&mut masm, &abi, regs::scratch(), regs::argv(), &call_conv); &mut masm,
&abi,
trampoline.emit_host_to_wasm(ty); regs::scratch(),
regs::argv(),
&call_conv,
self.pointer_bytes(),
);
match kind {
ArrayToWasm(idx) => trampoline.emit_array_to_wasm(ty, idx)?,
NativeToWasm(idx) => trampoline.emit_native_to_wasm(ty, idx)?,
WasmToNative => trampoline.emit_wasm_to_native(ty)?,
}
Ok(masm.finalize()) Ok(masm.finalize())
} }

22
winch/codegen/src/isa/x64/regs.rs

@ -51,18 +51,25 @@ pub(crate) fn r9() -> Reg {
pub(crate) fn r10() -> Reg { pub(crate) fn r10() -> Reg {
gpr(ENC_R10) gpr(ENC_R10)
} }
pub(crate) fn r11() -> Reg {
gpr(ENC_R11)
}
pub(crate) fn r12() -> Reg { pub(crate) fn r12() -> Reg {
gpr(ENC_R12) gpr(ENC_R12)
} }
pub(crate) fn r13() -> Reg { pub(crate) fn r13() -> Reg {
gpr(ENC_R13) gpr(ENC_R13)
} }
/// Used as a pinned register to hold
/// the `VMContext`.
/// Non-allocatable in Winch's default
/// ABI, and callee-saved in SystemV and
/// Fastcall.
pub(crate) fn r14() -> Reg { pub(crate) fn r14() -> Reg {
gpr(ENC_R14) gpr(ENC_R14)
} }
pub(crate) fn vmctx() -> Reg {
r14()
}
pub(crate) fn rbx() -> Reg { pub(crate) fn rbx() -> Reg {
gpr(ENC_RBX) gpr(ENC_RBX)
} }
@ -78,6 +85,13 @@ pub(crate) fn rbp() -> Reg {
gpr(ENC_RBP) gpr(ENC_RBP)
} }
/// Used as the scratch register.
/// Non-allocatable in Winch's default
/// ABI.
pub(crate) fn r11() -> Reg {
gpr(ENC_R11)
}
pub(crate) fn scratch() -> Reg { pub(crate) fn scratch() -> Reg {
r11() r11()
} }
@ -151,7 +165,7 @@ pub(crate) fn xmm15() -> Reg {
const GPR: u32 = 16; const GPR: u32 = 16;
const ALLOCATABLE_GPR: u32 = (1 << GPR) - 1; const ALLOCATABLE_GPR: u32 = (1 << GPR) - 1;
const NON_ALLOCATABLE_GPR: u32 = (1 << ENC_RBP) | (1 << ENC_RSP) | (1 << ENC_R11); const NON_ALLOCATABLE_GPR: u32 = (1 << ENC_RBP) | (1 << ENC_RSP) | (1 << ENC_R11) | (1 << ENC_R14);
/// Bitmask to represent the available general purpose registers. /// Bitmask to represent the available general purpose registers.
pub(crate) const ALL_GPR: u32 = ALLOCATABLE_GPR & !NON_ALLOCATABLE_GPR; pub(crate) const ALL_GPR: u32 = ALLOCATABLE_GPR & !NON_ALLOCATABLE_GPR;

2
winch/codegen/src/lib.rs

@ -17,4 +17,6 @@ mod regalloc;
mod regset; mod regset;
mod stack; mod stack;
mod trampoline; mod trampoline;
pub use trampoline::TrampolineKind;
use trampoline::*;
mod visitor; mod visitor;

16
winch/codegen/src/masm.rs

@ -39,6 +39,7 @@ pub(crate) enum RegImm {
Imm(i64), Imm(i64),
} }
#[derive(Clone)]
pub(crate) enum CalleeKind { pub(crate) enum CalleeKind {
/// A function call to a raw address. /// A function call to a raw address.
Indirect(Reg), Indirect(Reg),
@ -83,7 +84,7 @@ impl From<Reg> for RegImm {
pub(crate) trait MacroAssembler { pub(crate) trait MacroAssembler {
/// The addressing mode. /// The addressing mode.
type Address; type Address: Copy;
/// Emit the function prologue. /// Emit the function prologue.
fn prologue(&mut self); fn prologue(&mut self);
@ -109,11 +110,18 @@ pub(crate) trait MacroAssembler {
/// current position of the stack pointer (e.g. [sp + offset]. /// current position of the stack pointer (e.g. [sp + offset].
fn address_at_sp(&self, offset: u32) -> Self::Address; fn address_at_sp(&self, offset: u32) -> Self::Address;
/// Construct an address that is relative to the given register. /// Construct an address that is absolute to the current position
fn address_from_reg(&self, reg: Reg, offset: u32) -> Self::Address; /// of the given register.
fn address_at_reg(&self, reg: Reg, offset: u32) -> Self::Address;
/// Emit a function call to either a local or external function. /// Emit a function call to either a local or external function.
fn call(&mut self, callee: CalleeKind); fn call(
&mut self,
alignment: u32,
addend: u32,
stack_args_size: u32,
f: impl FnMut(&mut Self) -> CalleeKind,
) -> u32;
/// Get stack pointer offset. /// Get stack pointer offset.
fn sp_offset(&self) -> u32; fn sp_offset(&self) -> u32;

11
winch/codegen/src/regalloc.rs

@ -46,6 +46,12 @@ impl RegAlloc {
where where
F: FnMut(&mut RegAlloc), F: FnMut(&mut RegAlloc),
{ {
// If the scratch register is explicitly requested
// just return it, it's usage should never cause spills.
if named == self.scratch {
return named;
}
self.regset.gpr(named).unwrap_or_else(|| { self.regset.gpr(named).unwrap_or_else(|| {
spill(self); spill(self);
self.regset self.regset
@ -56,6 +62,9 @@ impl RegAlloc {
/// Mark a particular general purpose register as available. /// Mark a particular general purpose register as available.
pub fn free_gpr(&mut self, reg: Reg) { pub fn free_gpr(&mut self, reg: Reg) {
self.regset.free_gpr(reg); // Never mark the designated scratch register as allocatable.
if reg != self.scratch {
self.regset.free_gpr(reg);
}
} }
} }

5
winch/codegen/src/stack.rs

@ -117,6 +117,11 @@ impl Stack {
} }
} }
/// Insert a new value at the specified index.
pub fn insert(&mut self, at: usize, val: Val) {
self.inner.insert(at, val);
}
/// Get the length of the stack. /// Get the length of the stack.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.inner.len() self.inner.len()

400
winch/codegen/src/trampoline.rs

@ -1,15 +1,41 @@
//! Trampoline implementation for Winch.
//!
//! This module contains all the necessary pieces to emit the various
//! trampolines required by Wasmtime to call JIT code.
//
// TODO
//
// * Remove the usage of hardcoded operand sizes (`OperandSize::S64`) when
// loading/storing the VM context pointer. The real value of the operand size
// and VM context type should be derived from the ABI's pointer size. This is
// going to be relevant once 32-bit architectures are supported.
//
// * Save the fp and pc for fast stack walking.
use crate::{ use crate::{
abi::{align_to, calculate_frame_adjustment, ABIArg, ABIResult, ABI}, abi::{ABIArg, ABIParams, ABIResult, ABISig, ABI},
isa::CallingConvention, isa::CallingConvention,
masm::{CalleeKind, MacroAssembler, OperandSize, RegImm}, masm::{CalleeKind, MacroAssembler, OperandSize, RegImm},
reg::Reg, reg::Reg,
}; };
use anyhow::{anyhow, Result};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::mem; use std::mem;
use wasmparser::{FuncType, ValType}; use wasmparser::{FuncType, ValType};
use wasmtime_environ::{FuncIndex, PtrSize};
/// A trampoline to provide interopt between different calling /// The supported trampoline kinds.
/// conventions. /// See https://github.com/bytecodealliance/rfcs/blob/main/accepted/tail-calls.md#new-trampolines-and-vmcallercheckedanyfunc-changes
/// for more details.
pub enum TrampolineKind {
/// Calling from native to Wasm, using the array calling convention.
ArrayToWasm(FuncIndex),
/// Calling from native to Wasm.
NativeToWasm(FuncIndex),
/// Calling from Wasm to native.
WasmToNative,
}
/// The main trampoline abstraction.
pub(crate) struct Trampoline<'a, A, M> pub(crate) struct Trampoline<'a, A, M>
where where
A: ABI, A: ABI,
@ -26,12 +52,15 @@ where
/// callee, so it can only be used after the callee-saved /// callee, so it can only be used after the callee-saved
/// registers are on the stack. /// registers are on the stack.
alloc_scratch_reg: Reg, alloc_scratch_reg: Reg,
/// Registers to be saved as part of the trampoline's prologue and epilogue. /// Registers to be saved as part of the trampoline's prologue
/// and to be restored as part of the trampoline's epilogue.
callee_saved_regs: SmallVec<[Reg; 9]>, callee_saved_regs: SmallVec<[Reg; 9]>,
/// The calling convention used by the trampoline, /// The calling convention used by the trampoline,
/// which is the Wasmtime variant of the system ABI's /// which is the Wasmtime variant of the system ABI's
/// calling convention. /// calling convention.
call_conv: &'a CallingConvention, call_conv: &'a CallingConvention,
/// The pointer size of the current ISA.
pointer_size: u8,
} }
impl<'a, A, M> Trampoline<'a, A, M> impl<'a, A, M> Trampoline<'a, A, M>
@ -46,6 +75,7 @@ where
scratch_reg: Reg, scratch_reg: Reg,
alloc_scratch_reg: Reg, alloc_scratch_reg: Reg,
call_conv: &'a CallingConvention, call_conv: &'a CallingConvention,
pointer_size: u8,
) -> Self { ) -> Self {
Self { Self {
masm, masm,
@ -54,147 +84,320 @@ where
alloc_scratch_reg, alloc_scratch_reg,
callee_saved_regs: <A as ABI>::callee_saved_regs(call_conv), callee_saved_regs: <A as ABI>::callee_saved_regs(call_conv),
call_conv, call_conv,
pointer_size,
} }
} }
/// Emit the host to wasm trampoline. /// Emit an array-to-wasm trampoline.
pub fn emit_host_to_wasm(&mut self, ty: &FuncType) { pub fn emit_array_to_wasm(&mut self, ty: &FuncType, callee_index: FuncIndex) -> Result<()> {
// The host to wasm trampoline is currently hard coded (see vmcontext.rs let native_ty = FuncType::new(
// in the wasmtime-runtime crate, `VMArrayCallFunction`). The first two
// parameters are VMContexts (not used at this time). The third
// parameter is the function pointer to call. The fourth parameter is
// an address to storage space for both the return value and the
// arguments to the function.
let trampoline_ty = FuncType::new(
vec![ValType::I64, ValType::I64, ValType::I64, ValType::I64], vec![ValType::I64, ValType::I64, ValType::I64, ValType::I64],
vec![], vec![],
); );
let trampoline_sig = self.abi.sig(&trampoline_ty, self.call_conv); let native_sig = self.native_sig(&native_ty);
let wasm_sig = self.wasm_sig(ty);
// Hard-coding the size in bytes of the trampoline arguments let val_ptr = &native_sig.params[2]
// since it's static, based on the current signature we should .get_reg()
// always have 4 arguments, each of which is 8 bytes. .map(RegImm::reg)
let trampoline_arg_size = 32; .ok_or_else(|| anyhow!("Expected value pointer to be in a register"))?;
let callee_sig = self.abi.sig(ty, &CallingConvention::Default); self.prologue_with_callee_saved();
let val_ptr = if let ABIArg::Reg { reg, ty: _ty } = &trampoline_sig.params[3] { // Get the VM context pointer and move it to the designated pinned
Ok(RegImm::reg(*reg)) // register.
} else { let vmctx_ptr = Self::vmctx(&native_sig.params)?;
Err(anyhow::anyhow!("Expected the val ptr to be in a register")) self.masm
} .mov(vmctx_ptr, <A as ABI>::vmctx_reg().into(), OperandSize::S64);
.unwrap();
self.prologue(); let (offsets, spill_size) = self.spill(&native_sig.params);
let mut trampoline_arg_offsets: [u32; 4] = [0; 4]; let val_ptr_offset = offsets[2];
trampoline_sig // Call the function that was passed into the trampoline.
.params let allocated_stack = self.masm.call(
.iter() self.abi.call_stack_align().into(),
.enumerate() self.abi.arg_base_offset().into(),
.for_each(|(i, param)| { wasm_sig.stack_bytes,
if let ABIArg::Reg { reg, ty: _ty } = param { |masm| {
let offset = self.masm.push(*reg); masm.mov(*val_ptr, self.scratch_reg.into(), OperandSize::S64);
trampoline_arg_offsets[i] = offset; Self::assign_args_from_array(
} masm,
}); &wasm_sig,
self.scratch_reg,
self.alloc_scratch_reg,
);
CalleeKind::Direct(callee_index.as_u32())
},
);
self.masm.free_stack(allocated_stack);
// Move the val ptr back into the scratch register so we can
// load the return values.
self.masm.load(
self.masm.address_from_sp(val_ptr_offset),
self.scratch_reg,
OperandSize::S64,
);
// Move the return values into the value ptr. We are only
// supporting a single return value at this time.
let ABIResult::Reg { reg, ty } = &wasm_sig.result;
if let Some(ty) = ty {
self.masm.store(
RegImm::reg(*reg),
self.masm.address_at_reg(self.scratch_reg, 0),
(*ty).into(),
);
}
self.epilogue_with_callee_saved_restore(spill_size);
Ok(())
}
let val_ptr_offset = trampoline_arg_offsets[3]; /// Emit a native-to-wasm trampoline.
let func_ptr_offset = trampoline_arg_offsets[2]; pub fn emit_native_to_wasm(&mut self, ty: &FuncType, callee_index: FuncIndex) -> Result<()> {
let native_sig = self.native_sig(&ty);
let wasm_sig = self.wasm_sig(&ty);
let vmctx_ptr = Self::vmctx(&native_sig.params)?;
self.prologue_with_callee_saved();
// Move the VM context pointer to the designated pinned register.
self.masm self.masm
.mov(val_ptr, RegImm::reg(self.scratch_reg), OperandSize::S64); .mov(vmctx_ptr, <A as ABI>::vmctx_reg().into(), OperandSize::S64);
// How much we need to adjust the stack pointer by to account let (offsets, spill_size) = self.spill(&native_sig.params);
// for the alignment required by the ISA.
let delta = calculate_frame_adjustment( let reserved_stack = self.masm.call(
self.masm.sp_offset(), self.abi.call_stack_align().into(),
self.abi.arg_base_offset() as u32, self.abi.arg_base_offset().into(),
self.abi.call_stack_align() as u32, wasm_sig.stack_bytes,
|masm| {
Self::assign_args(
masm,
&wasm_sig.params,
&native_sig.params[2..],
&offsets[2..],
self.scratch_reg,
self.abi.arg_base_offset().into(),
);
CalleeKind::Direct(callee_index.as_u32())
},
); );
// The total amount of stack space we need to reserve for the self.masm.free_stack(reserved_stack);
// arguments. self.epilogue_with_callee_saved_restore(spill_size);
let total_arg_stack_space = align_to(
callee_sig.stack_bytes + delta, Ok(())
self.abi.call_stack_align() as u32, }
/// Emit a wasm-to-native trampoline.
pub fn emit_wasm_to_native(&mut self, ty: &FuncType) -> Result<()> {
let mut params = Self::callee_and_caller_vmctx();
params.extend_from_slice(ty.params());
let func_ty = FuncType::new(params, ty.results().to_owned());
let wasm_sig = self.wasm_sig(&func_ty);
let native_sig = self.native_sig(ty);
self.prologue();
let (offsets, spill_size) = self.spill(&wasm_sig.params);
let reserved_stack = self.masm.call(
self.abi.call_stack_align().into(),
self.abi.arg_base_offset().into(),
native_sig.stack_bytes,
|masm| {
// Move the VM context into one of the scratch registers.
let vmctx = Self::vmctx(&wasm_sig.params).unwrap();
masm.mov(
vmctx.into(),
self.alloc_scratch_reg.into(),
OperandSize::S64,
);
Self::assign_args(
masm,
&native_sig.params,
&wasm_sig.params,
&offsets,
self.scratch_reg,
self.abi.arg_base_offset().into(),
);
let body_offset = self.pointer_size.vmnative_call_host_func_context_func_ref()
+ self.pointer_size.vm_func_ref_native_call();
let callee_addr = masm.address_at_reg(self.alloc_scratch_reg, body_offset.into());
masm.load(callee_addr, self.scratch_reg, OperandSize::S64);
CalleeKind::Indirect(self.scratch_reg)
},
); );
self.masm.reserve_stack(total_arg_stack_space); self.masm.free_stack(reserved_stack);
self.epilogue(spill_size);
Ok(())
}
/// Perfom argument assignment, translating between
/// caller and callee calling conventions.
fn assign_args(
masm: &mut M,
callee_params: &[ABIArg],
caller_params: &[ABIArg],
caller_stack_offsets: &[u32],
scratch: Reg,
arg_base_offset: u32,
) {
assert!(callee_params.len() == caller_params.len());
let fp = <A as ABI>::fp_reg();
let mut offset_index = 0;
callee_params
.iter()
.zip(caller_params)
.for_each(
|(callee_param, caller_param)| match (callee_param, caller_param) {
(ABIArg::Reg { ty, reg: dst }, ABIArg::Reg { .. }) => {
let offset = caller_stack_offsets[offset_index];
let addr = masm.address_from_sp(offset);
masm.load(addr, *dst, (*ty).into());
offset_index += 1;
}
(ABIArg::Stack { ty, offset }, ABIArg::Reg { .. }) => {
let spill_offset = caller_stack_offsets[offset_index];
let addr = masm.address_from_sp(spill_offset);
masm.load(addr, scratch, (*ty).into());
let arg_addr = masm.address_at_sp(*offset);
masm.store(scratch.into(), arg_addr, (*ty).into());
offset_index += 1;
}
(ABIArg::Reg { ty, reg: dst }, ABIArg::Stack { ty: _, offset }) => {
let addr = masm.address_at_reg(fp, arg_base_offset + offset);
masm.load(addr, *dst, (*ty).into());
}
(
ABIArg::Stack {
ty,
offset: callee_offset,
},
ABIArg::Stack {
offset: caller_offset,
..
},
) => {
let addr = masm.address_at_reg(fp, arg_base_offset + caller_offset);
masm.load(addr, scratch, (*ty).into());
let arg_addr = masm.address_at_sp(*callee_offset);
masm.store(scratch.into(), arg_addr, (*ty).into());
}
},
)
}
/// Get the type of the caller and callee VM contexts.
fn callee_and_caller_vmctx() -> Vec<ValType> {
vec![ValType::I64, ValType::I64]
}
/// Returns a signature using the system's calling convention.
fn native_sig(&self, ty: &FuncType) -> ABISig {
let mut params = Self::callee_and_caller_vmctx();
params.extend_from_slice(ty.params());
let native_type = FuncType::new(params, ty.results().to_owned());
self.abi.sig(&native_type, self.call_conv)
}
/// Returns a signature using the Winch's default calling convention.
fn wasm_sig(&self, ty: &FuncType) -> ABISig {
self.abi.sig(ty, &CallingConvention::Default)
}
/// Returns the register containing the VM context pointer.
fn vmctx(params: &ABIParams) -> Result<RegImm> {
params[0]
.get_reg()
.map(RegImm::reg)
.ok_or_else(|| anyhow!("Expected vm context pointer to be in a register"))
}
/// Performs a spill of the register params.
fn spill(&mut self, params: &ABIParams) -> (SmallVec<[u32; 6]>, u32) {
let mut offsets = SmallVec::new();
let mut spilled = 0;
params.iter().for_each(|param| {
if let Some(reg) = param.get_reg() {
let offset = self.masm.push(reg);
offsets.push(offset);
spilled += 1;
}
});
// The stack size for the spill, calculated
// from the number of spilled register times
// the size of each push (8 bytes).
let size = spilled * <A as ABI>::word_bytes();
(offsets, size)
}
/// Assigns arguments for the callee, loading them from a register.
fn assign_args_from_array(masm: &mut M, callee_sig: &ABISig, values_reg: Reg, scratch: Reg) {
// The max size a value can be when reading from the params // The max size a value can be when reading from the params
// memory location. // memory location.
let value_size = mem::size_of::<u128>(); let value_size = mem::size_of::<u128>();
callee_sig.params.iter().enumerate().for_each(|(i, param)| { callee_sig.params.iter().enumerate().for_each(|(i, param)| {
let value_offset = (i * value_size) as u32; let value_offset = (i * value_size) as u32;
match param { match param {
ABIArg::Reg { reg, ty } => self.masm.load( ABIArg::Reg { reg, ty } => masm.load(
self.masm.address_from_reg(self.scratch_reg, value_offset), masm.address_at_reg(values_reg, value_offset),
*reg, *reg,
(*ty).into(), (*ty).into(),
), ),
ABIArg::Stack { offset, ty } => { ABIArg::Stack { offset, ty } => {
self.masm.load( masm.load(
self.masm.address_from_reg(self.scratch_reg, value_offset), masm.address_at_reg(values_reg, value_offset),
self.alloc_scratch_reg, scratch,
(*ty).into(), (*ty).into(),
); );
self.masm.store( masm.store(
RegImm::reg(self.alloc_scratch_reg), RegImm::reg(scratch),
self.masm.address_at_sp(*offset), masm.address_at_sp(*offset),
(*ty).into(), (*ty).into(),
); );
} }
} }
}); });
// Move the function pointer from it's stack location into a
// scratch register.
self.masm.load(
self.masm.address_from_sp(func_ptr_offset),
self.scratch_reg,
OperandSize::S64,
);
// Call the function that was passed into the trampoline.
self.masm.call(CalleeKind::Indirect(self.scratch_reg));
self.masm.free_stack(total_arg_stack_space);
// Move the val ptr back into the scratch register so we can
// load the return values.
self.masm.load(
self.masm.address_from_sp(val_ptr_offset),
self.scratch_reg,
OperandSize::S64,
);
// Move the return values into the value ptr. We are only
// supporting a single return value at this time.
let ABIResult::Reg { reg, ty } = &callee_sig.result;
self.masm.store(
RegImm::reg(*reg),
self.masm.address_from_reg(self.scratch_reg, 0),
(*ty).unwrap().into(),
);
self.epilogue(trampoline_arg_size);
} }
/// The trampoline's prologue. /// The trampoline's prologue.
fn prologue(&mut self) { fn prologue(&mut self) {
self.masm.prologue(); self.masm.prologue();
}
/// Similar to [Trampoline::prologue], but saves
/// callee-saved registers.
fn prologue_with_callee_saved(&mut self) {
self.masm.prologue();
// Save any callee-saved registers. // Save any callee-saved registers.
for r in &self.callee_saved_regs { for r in &self.callee_saved_regs {
self.masm.push(*r); self.masm.push(*r);
} }
} }
/// The trampoline's epilogue. /// Similar to [Trampoline::epilogue], but restores
fn epilogue(&mut self, arg_size: u32) { /// callee-saved registers.
fn epilogue_with_callee_saved_restore(&mut self, arg_size: u32) {
// Free the stack space allocated by pushing the trampoline arguments. // Free the stack space allocated by pushing the trampoline arguments.
self.masm.free_stack(arg_size); self.masm.free_stack(arg_size);
// Restore the callee-saved registers. // Restore the callee-saved registers.
@ -203,4 +406,11 @@ where
} }
self.masm.epilogue(0); self.masm.epilogue(0);
} }
/// The trampoline's epilogue.
fn epilogue(&mut self, arg_size: u32) {
// Free the stack space allocated by pushing the trampoline arguments.
self.masm.free_stack(arg_size);
self.masm.epilogue(0);
}
} }

3
winch/codegen/src/visitor.rs

@ -10,6 +10,7 @@ use crate::masm::{DivKind, MacroAssembler, OperandSize, RegImm, RemKind};
use crate::stack::Val; use crate::stack::Val;
use wasmparser::ValType; use wasmparser::ValType;
use wasmparser::VisitOperator; use wasmparser::VisitOperator;
use wasmtime_environ::FuncIndex;
/// A macro to define unsupported WebAssembly operators. /// A macro to define unsupported WebAssembly operators.
/// ///
@ -198,7 +199,7 @@ where
} }
fn visit_call(&mut self, index: u32) { fn visit_call(&mut self, index: u32) {
self.emit_call(index); self.emit_call(FuncIndex::from_u32(index));
} }
wasmparser::for_each_operator!(def_unsupported); wasmparser::for_each_operator!(def_unsupported);

8
winch/environ/src/lib.rs

@ -5,7 +5,7 @@
use wasmparser::types::Types; use wasmparser::types::Types;
use wasmtime_environ::{FuncIndex, Module}; use wasmtime_environ::{FuncIndex, Module};
use winch_codegen::{self, Callee, TargetIsa}; use winch_codegen::{self, Callee};
/// Function environment containing module and runtime specific /// Function environment containing module and runtime specific
/// information. /// information.
@ -14,8 +14,6 @@ pub struct FuncEnv<'a> {
pub module: &'a Module, pub module: &'a Module,
/// Type information about a module, once it has been validated. /// Type information about a module, once it has been validated.
pub types: &'a Types, pub types: &'a Types,
/// The current ISA.
pub isa: &'a Box<dyn TargetIsa>,
} }
impl<'a> winch_codegen::FuncEnv for FuncEnv<'a> { impl<'a> winch_codegen::FuncEnv for FuncEnv<'a> {
@ -35,7 +33,7 @@ impl<'a> winch_codegen::FuncEnv for FuncEnv<'a> {
impl<'a> FuncEnv<'a> { impl<'a> FuncEnv<'a> {
/// Create a new function environment. /// Create a new function environment.
pub fn new(module: &'a Module, types: &'a Types, isa: &'a Box<dyn TargetIsa>) -> Self { pub fn new(module: &'a Module, types: &'a Types) -> Self {
Self { module, types, isa } Self { module, types }
} }
} }

15
winch/filetests/filetests/aarch64/i32_add/const.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: 500180d2 mov x16, #0xa ;; c: ff2300d1 sub sp, sp, #8
;; 10: e003102a mov w0, w16 ;; 10: fc030091 mov x28, sp
;; 14: 00500011 add w0, w0, #0x14 ;; 14: 890300f8 stur x9, [x28]
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 18: 500180d2 mov x16, #0xa
;; 1c: c0035fd6 ret ;; 1c: e003102a mov w0, w16
;; 20: 00500011 add w0, w0, #0x14
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

33
winch/filetests/filetests/aarch64/i32_add/locals.wat

@ -19,21 +19,22 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: ff2300d1 sub sp, sp, #8 ;; c: ff4300d1 sub sp, sp, #0x10
;; 10: fc030091 mov x28, sp ;; 10: fc030091 mov x28, sp
;; 14: 100080d2 mov x16, #0 ;; 14: 100080d2 mov x16, #0
;; 18: 900300f8 stur x16, [x28] ;; 18: 908300f8 stur x16, [x28, #8]
;; 1c: 500180d2 mov x16, #0xa ;; 1c: 890300f8 stur x9, [x28]
;; 20: e003102a mov w0, w16 ;; 20: 500180d2 mov x16, #0xa
;; 24: 804300b8 stur w0, [x28, #4] ;; 24: e003102a mov w0, w16
;; 28: 900280d2 mov x16, #0x14 ;; 28: 80c300b8 stur w0, [x28, #0xc]
;; 2c: e003102a mov w0, w16 ;; 2c: 900280d2 mov x16, #0x14
;; 30: 800300b8 stur w0, [x28] ;; 30: e003102a mov w0, w16
;; 34: 800340b8 ldur w0, [x28] ;; 34: 808300b8 stur w0, [x28, #8]
;; 38: 814340b8 ldur w1, [x28, #4] ;; 38: 808340b8 ldur w0, [x28, #8]
;; 3c: 2160200b add w1, w1, w0, uxtx ;; 3c: 81c340b8 ldur w1, [x28, #0xc]
;; 40: e00301aa mov x0, x1 ;; 40: 2160200b add w1, w1, w0, uxtx
;; 44: ff230091 add sp, sp, #8 ;; 44: e00301aa mov x0, x1
;; 48: fc030091 mov x28, sp ;; 48: ff430091 add sp, sp, #0x10
;; 4c: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 4c: fc030091 mov x28, sp
;; 50: c0035fd6 ret ;; 50: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 54: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i32_add/max.wat

@ -9,8 +9,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: f07b40b2 orr x16, xzr, #0x7fffffff ;; c: ff2300d1 sub sp, sp, #8
;; 10: e003102a mov w0, w16 ;; 10: fc030091 mov x28, sp
;; 14: 00040011 add w0, w0, #1 ;; 14: 890300f8 stur x9, [x28]
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 18: f07b40b2 orr x16, xzr, #0x7fffffff
;; 1c: c0035fd6 ret ;; 1c: e003102a mov w0, w16
;; 20: 00040011 add w0, w0, #1
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

17
winch/filetests/filetests/aarch64/i32_add/max_one.wat

@ -10,9 +10,14 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: f08361b2 orr x16, xzr, #0xffffffff80000000 ;; c: ff2300d1 sub sp, sp, #8
;; 10: e003102a mov w0, w16 ;; 10: fc030091 mov x28, sp
;; 14: 10008092 mov x16, #-1 ;; 14: 890300f8 stur x9, [x28]
;; 18: 0060300b add w0, w0, w16, uxtx ;; 18: f08361b2 orr x16, xzr, #0xffffffff80000000
;; 1c: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 1c: e003102a mov w0, w16
;; 20: c0035fd6 ret ;; 20: 10008092 mov x16, #-1
;; 24: 0060300b add w0, w0, w16, uxtx
;; 28: ff230091 add sp, sp, #8
;; 2c: fc030091 mov x28, sp
;; 30: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 34: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i32_add/mixed.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: 10008092 mov x16, #-1 ;; c: ff2300d1 sub sp, sp, #8
;; 10: e003102a mov w0, w16 ;; 10: fc030091 mov x28, sp
;; 14: 00040011 add w0, w0, #1 ;; 14: 890300f8 stur x9, [x28]
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 18: 10008092 mov x16, #-1
;; 1c: c0035fd6 ret ;; 1c: e003102a mov w0, w16
;; 20: 00040011 add w0, w0, #1
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

23
winch/filetests/filetests/aarch64/i32_add/params.wat

@ -10,15 +10,16 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: ff2300d1 sub sp, sp, #8 ;; c: ff4300d1 sub sp, sp, #0x10
;; 10: fc030091 mov x28, sp ;; 10: fc030091 mov x28, sp
;; 14: 804300b8 stur w0, [x28, #4] ;; 14: 80c300b8 stur w0, [x28, #0xc]
;; 18: 810300b8 stur w1, [x28] ;; 18: 818300b8 stur w1, [x28, #8]
;; 1c: 800340b8 ldur w0, [x28] ;; 1c: 890300f8 stur x9, [x28]
;; 20: 814340b8 ldur w1, [x28, #4] ;; 20: 808340b8 ldur w0, [x28, #8]
;; 24: 2160200b add w1, w1, w0, uxtx ;; 24: 81c340b8 ldur w1, [x28, #0xc]
;; 28: e00301aa mov x0, x1 ;; 28: 2160200b add w1, w1, w0, uxtx
;; 2c: ff230091 add sp, sp, #8 ;; 2c: e00301aa mov x0, x1
;; 30: fc030091 mov x28, sp ;; 30: ff430091 add sp, sp, #0x10
;; 34: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 34: fc030091 mov x28, sp
;; 38: c0035fd6 ret ;; 38: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 3c: c0035fd6 ret

17
winch/filetests/filetests/aarch64/i32_add/signed.wat

@ -10,9 +10,14 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: 10008092 mov x16, #-1 ;; c: ff2300d1 sub sp, sp, #8
;; 10: e003102a mov w0, w16 ;; 10: fc030091 mov x28, sp
;; 14: 10008092 mov x16, #-1 ;; 14: 890300f8 stur x9, [x28]
;; 18: 0060300b add w0, w0, w16, uxtx ;; 18: 10008092 mov x16, #-1
;; 1c: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 1c: e003102a mov w0, w16
;; 20: c0035fd6 ret ;; 20: 10008092 mov x16, #-1
;; 24: 0060300b add w0, w0, w16, uxtx
;; 28: ff230091 add sp, sp, #8
;; 2c: fc030091 mov x28, sp
;; 30: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 34: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i32_add/unsigned_with_zero.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: 300080d2 mov x16, #1 ;; c: ff2300d1 sub sp, sp, #8
;; 10: e003102a mov w0, w16 ;; 10: fc030091 mov x28, sp
;; 14: 00000011 add w0, w0, #0 ;; 14: 890300f8 stur x9, [x28]
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 18: 300080d2 mov x16, #1
;; 1c: c0035fd6 ret ;; 1c: e003102a mov w0, w16
;; 20: 00000011 add w0, w0, #0
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i64_add/const.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: 500180d2 mov x16, #0xa ;; c: ff2300d1 sub sp, sp, #8
;; 10: e00310aa mov x0, x16 ;; 10: fc030091 mov x28, sp
;; 14: 00500091 add x0, x0, #0x14 ;; 14: 890300f8 stur x9, [x28]
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 18: 500180d2 mov x16, #0xa
;; 1c: c0035fd6 ret ;; 1c: e00310aa mov x0, x16
;; 20: 00500091 add x0, x0, #0x14
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

35
winch/filetests/filetests/aarch64/i64_add/locals.wat

@ -19,22 +19,23 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: ff4300d1 sub sp, sp, #0x10 ;; c: ff6300d1 sub sp, sp, #0x18
;; 10: fc030091 mov x28, sp ;; 10: fc030091 mov x28, sp
;; 14: 100080d2 mov x16, #0 ;; 14: 100080d2 mov x16, #0
;; 18: 908300f8 stur x16, [x28, #8] ;; 18: 900301f8 stur x16, [x28, #0x10]
;; 1c: 900300f8 stur x16, [x28] ;; 1c: 908300f8 stur x16, [x28, #8]
;; 20: 500180d2 mov x16, #0xa ;; 20: 890300f8 stur x9, [x28]
;; 24: e00310aa mov x0, x16 ;; 24: 500180d2 mov x16, #0xa
;; 28: 808300f8 stur x0, [x28, #8] ;; 28: e00310aa mov x0, x16
;; 2c: 900280d2 mov x16, #0x14 ;; 2c: 800301f8 stur x0, [x28, #0x10]
;; 30: e00310aa mov x0, x16 ;; 30: 900280d2 mov x16, #0x14
;; 34: 800300f8 stur x0, [x28] ;; 34: e00310aa mov x0, x16
;; 38: 800340f8 ldur x0, [x28] ;; 38: 808300f8 stur x0, [x28, #8]
;; 3c: 818340f8 ldur x1, [x28, #8] ;; 3c: 808340f8 ldur x0, [x28, #8]
;; 40: 2160208b add x1, x1, x0, uxtx ;; 40: 810341f8 ldur x1, [x28, #0x10]
;; 44: e00301aa mov x0, x1 ;; 44: 2160208b add x1, x1, x0, uxtx
;; 48: ff430091 add sp, sp, #0x10 ;; 48: e00301aa mov x0, x1
;; 4c: fc030091 mov x28, sp ;; 4c: ff630091 add sp, sp, #0x18
;; 50: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 50: fc030091 mov x28, sp
;; 54: c0035fd6 ret ;; 54: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 58: c0035fd6 ret

17
winch/filetests/filetests/aarch64/i64_add/max.wat

@ -9,9 +9,14 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: 300080d2 mov x16, #1 ;; c: ff2300d1 sub sp, sp, #8
;; 10: e00310aa mov x0, x16 ;; 10: fc030091 mov x28, sp
;; 14: 1000f092 mov x16, #0x7fffffffffffffff ;; 14: 890300f8 stur x9, [x28]
;; 18: 0060308b add x0, x0, x16, uxtx ;; 18: 300080d2 mov x16, #1
;; 1c: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 1c: e00310aa mov x0, x16
;; 20: c0035fd6 ret ;; 20: 1000f092 mov x16, #0x7fffffffffffffff
;; 24: 0060308b add x0, x0, x16, uxtx
;; 28: ff230091 add sp, sp, #8
;; 2c: fc030091 mov x28, sp
;; 30: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 34: c0035fd6 ret

17
winch/filetests/filetests/aarch64/i64_add/max_one.wat

@ -10,9 +10,14 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: 1000f0d2 mov x16, #-0x8000000000000000 ;; c: ff2300d1 sub sp, sp, #8
;; 10: e00310aa mov x0, x16 ;; 10: fc030091 mov x28, sp
;; 14: 10008092 mov x16, #-1 ;; 14: 890300f8 stur x9, [x28]
;; 18: 0060308b add x0, x0, x16, uxtx ;; 18: 1000f0d2 mov x16, #-0x8000000000000000
;; 1c: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 1c: e00310aa mov x0, x16
;; 20: c0035fd6 ret ;; 20: 10008092 mov x16, #-1
;; 24: 0060308b add x0, x0, x16, uxtx
;; 28: ff230091 add sp, sp, #8
;; 2c: fc030091 mov x28, sp
;; 30: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 34: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i64_add/mixed.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: 10008092 mov x16, #-1 ;; c: ff2300d1 sub sp, sp, #8
;; 10: e00310aa mov x0, x16 ;; 10: fc030091 mov x28, sp
;; 14: 00040091 add x0, x0, #1 ;; 14: 890300f8 stur x9, [x28]
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 18: 10008092 mov x16, #-1
;; 1c: c0035fd6 ret ;; 1c: e00310aa mov x0, x16
;; 20: 00040091 add x0, x0, #1
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

23
winch/filetests/filetests/aarch64/i64_add/params.wat

@ -10,15 +10,16 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: ff4300d1 sub sp, sp, #0x10 ;; c: ff6300d1 sub sp, sp, #0x18
;; 10: fc030091 mov x28, sp ;; 10: fc030091 mov x28, sp
;; 14: 808300f8 stur x0, [x28, #8] ;; 14: 800301f8 stur x0, [x28, #0x10]
;; 18: 810300f8 stur x1, [x28] ;; 18: 818300f8 stur x1, [x28, #8]
;; 1c: 800340f8 ldur x0, [x28] ;; 1c: 890300f8 stur x9, [x28]
;; 20: 818340f8 ldur x1, [x28, #8] ;; 20: 808340f8 ldur x0, [x28, #8]
;; 24: 2160208b add x1, x1, x0, uxtx ;; 24: 810341f8 ldur x1, [x28, #0x10]
;; 28: e00301aa mov x0, x1 ;; 28: 2160208b add x1, x1, x0, uxtx
;; 2c: ff430091 add sp, sp, #0x10 ;; 2c: e00301aa mov x0, x1
;; 30: fc030091 mov x28, sp ;; 30: ff630091 add sp, sp, #0x18
;; 34: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 34: fc030091 mov x28, sp
;; 38: c0035fd6 ret ;; 38: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 3c: c0035fd6 ret

17
winch/filetests/filetests/aarch64/i64_add/signed.wat

@ -10,9 +10,14 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: 10008092 mov x16, #-1 ;; c: ff2300d1 sub sp, sp, #8
;; 10: e00310aa mov x0, x16 ;; 10: fc030091 mov x28, sp
;; 14: 10008092 mov x16, #-1 ;; 14: 890300f8 stur x9, [x28]
;; 18: 0060308b add x0, x0, x16, uxtx ;; 18: 10008092 mov x16, #-1
;; 1c: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 1c: e00310aa mov x0, x16
;; 20: c0035fd6 ret ;; 20: 10008092 mov x16, #-1
;; 24: 0060308b add x0, x0, x16, uxtx
;; 28: ff230091 add sp, sp, #8
;; 2c: fc030091 mov x28, sp
;; 30: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 34: c0035fd6 ret

15
winch/filetests/filetests/aarch64/i64_add/unsigned_with_zero.wat

@ -10,8 +10,13 @@
;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]! ;; 0: fd7bbfa9 stp x29, x30, [sp, #-0x10]!
;; 4: fd030091 mov x29, sp ;; 4: fd030091 mov x29, sp
;; 8: fc030091 mov x28, sp ;; 8: fc030091 mov x28, sp
;; c: 300080d2 mov x16, #1 ;; c: ff2300d1 sub sp, sp, #8
;; 10: e00310aa mov x0, x16 ;; 10: fc030091 mov x28, sp
;; 14: 00000091 add x0, x0, #0 ;; 14: 890300f8 stur x9, [x28]
;; 18: fd7bc1a8 ldp x29, x30, [sp], #0x10 ;; 18: 300080d2 mov x16, #1
;; 1c: c0035fd6 ret ;; 1c: e00310aa mov x0, x16
;; 20: 00000091 add x0, x0, #0
;; 24: ff230091 add sp, sp, #8
;; 28: fc030091 mov x28, sp
;; 2c: fd7bc1a8 ldp x29, x30, [sp], #0x10
;; 30: c0035fd6 ret

158
winch/filetests/filetests/x64/call/params.wat

@ -37,85 +37,87 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c2404 mov dword ptr [rsp + 4], edi ;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 893424 mov dword ptr [rsp], esi ;; c: 89742408 mov dword ptr [rsp + 8], esi
;; f: 8b4c2404 mov ecx, dword ptr [rsp + 4] ;; 10: 4c893424 mov qword ptr [rsp], r14
;; 13: 8b0424 mov eax, dword ptr [rsp] ;; 14: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 16: 31d2 xor edx, edx ;; 18: 8b442408 mov eax, dword ptr [rsp + 8]
;; 18: f7f1 div ecx ;; 1c: 31d2 xor edx, edx
;; 1a: 50 push rax ;; 1e: f7f1 div ecx
;; 1b: 4883ec20 sub rsp, 0x20 ;; 20: 50 push rax
;; 1f: 8b7c2420 mov edi, dword ptr [rsp + 0x20] ;; 21: 4883ec28 sub rsp, 0x28
;; 23: be01000000 mov esi, 1 ;; 25: 8b7c2428 mov edi, dword ptr [rsp + 0x28]
;; 28: ba02000000 mov edx, 2 ;; 29: be01000000 mov esi, 1
;; 2d: b903000000 mov ecx, 3 ;; 2e: ba02000000 mov edx, 2
;; 32: 41b804000000 mov r8d, 4 ;; 33: b903000000 mov ecx, 3
;; 38: 41b905000000 mov r9d, 5 ;; 38: 41b804000000 mov r8d, 4
;; 3e: 41bb06000000 mov r11d, 6 ;; 3e: 41b905000000 mov r9d, 5
;; 44: 44891c24 mov dword ptr [rsp], r11d ;; 44: 41bb06000000 mov r11d, 6
;; 48: 41bb07000000 mov r11d, 7 ;; 4a: 44891c24 mov dword ptr [rsp], r11d
;; 4e: 44895c2408 mov dword ptr [rsp + 8], r11d ;; 4e: 41bb07000000 mov r11d, 7
;; 53: 41bb08000000 mov r11d, 8 ;; 54: 44895c2408 mov dword ptr [rsp + 8], r11d
;; 59: 44895c2410 mov dword ptr [rsp + 0x10], r11d ;; 59: 41bb08000000 mov r11d, 8
;; 5e: e800000000 call 0x63 ;; 5f: 44895c2410 mov dword ptr [rsp + 0x10], r11d
;; 63: 4883c428 add rsp, 0x28 ;; 64: e800000000 call 0x69
;; 67: 50 push rax ;; 69: 4883c430 add rsp, 0x30
;; 68: 448b5c2408 mov r11d, dword ptr [rsp + 8] ;; 6d: 50 push rax
;; 6d: 4153 push r11 ;; 6e: 448b5c2410 mov r11d, dword ptr [rsp + 0x10]
;; 6f: 448b5c2414 mov r11d, dword ptr [rsp + 0x14] ;; 73: 4153 push r11
;; 74: 4153 push r11 ;; 75: 448b5c241c mov r11d, dword ptr [rsp + 0x1c]
;; 76: 59 pop rcx ;; 7a: 4153 push r11
;; 77: 58 pop rax ;; 7c: 59 pop rcx
;; 78: 31d2 xor edx, edx ;; 7d: 58 pop rax
;; 7a: f7f1 div ecx ;; 7e: 31d2 xor edx, edx
;; 7c: 50 push rax ;; 80: f7f1 div ecx
;; 7d: 4883ec20 sub rsp, 0x20 ;; 82: 50 push rax
;; 81: 8b7c2428 mov edi, dword ptr [rsp + 0x28] ;; 83: 4883ec20 sub rsp, 0x20
;; 85: 8b742420 mov esi, dword ptr [rsp + 0x20] ;; 87: 8b7c2428 mov edi, dword ptr [rsp + 0x28]
;; 89: ba02000000 mov edx, 2 ;; 8b: 8b742420 mov esi, dword ptr [rsp + 0x20]
;; 8e: b903000000 mov ecx, 3 ;; 8f: ba02000000 mov edx, 2
;; 93: 41b804000000 mov r8d, 4 ;; 94: b903000000 mov ecx, 3
;; 99: 41b905000000 mov r9d, 5 ;; 99: 41b804000000 mov r8d, 4
;; 9f: 41bb06000000 mov r11d, 6 ;; 9f: 41b905000000 mov r9d, 5
;; a5: 44891c24 mov dword ptr [rsp], r11d ;; a5: 41bb06000000 mov r11d, 6
;; a9: 41bb07000000 mov r11d, 7 ;; ab: 44891c24 mov dword ptr [rsp], r11d
;; af: 44895c2408 mov dword ptr [rsp + 8], r11d ;; af: 41bb07000000 mov r11d, 7
;; b4: 41bb08000000 mov r11d, 8 ;; b5: 44895c2408 mov dword ptr [rsp + 8], r11d
;; ba: 44895c2410 mov dword ptr [rsp + 0x10], r11d ;; ba: 41bb08000000 mov r11d, 8
;; bf: e800000000 call 0xc4 ;; c0: 44895c2410 mov dword ptr [rsp + 0x10], r11d
;; c4: 4883c430 add rsp, 0x30 ;; c5: e800000000 call 0xca
;; c8: 4883c408 add rsp, 8 ;; ca: 4883c430 add rsp, 0x30
;; cc: 5d pop rbp ;; ce: 4883c410 add rsp, 0x10
;; cd: c3 ret ;; d2: 5d pop rbp
;; d3: c3 ret
;; ;;
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec18 sub rsp, 0x18 ;; 4: 4883ec20 sub rsp, 0x20
;; 8: 897c2414 mov dword ptr [rsp + 0x14], edi ;; 8: 897c241c mov dword ptr [rsp + 0x1c], edi
;; c: 89742410 mov dword ptr [rsp + 0x10], esi ;; c: 89742418 mov dword ptr [rsp + 0x18], esi
;; 10: 8954240c mov dword ptr [rsp + 0xc], edx ;; 10: 89542414 mov dword ptr [rsp + 0x14], edx
;; 14: 894c2408 mov dword ptr [rsp + 8], ecx ;; 14: 894c2410 mov dword ptr [rsp + 0x10], ecx
;; 18: 4489442404 mov dword ptr [rsp + 4], r8d ;; 18: 448944240c mov dword ptr [rsp + 0xc], r8d
;; 1d: 44890c24 mov dword ptr [rsp], r9d ;; 1d: 44894c2408 mov dword ptr [rsp + 8], r9d
;; 21: 8b442410 mov eax, dword ptr [rsp + 0x10] ;; 22: 4c893424 mov qword ptr [rsp], r14
;; 25: 8b4c2414 mov ecx, dword ptr [rsp + 0x14] ;; 26: 8b442418 mov eax, dword ptr [rsp + 0x18]
;; 29: 01c1 add ecx, eax ;; 2a: 8b4c241c mov ecx, dword ptr [rsp + 0x1c]
;; 2b: 8b44240c mov eax, dword ptr [rsp + 0xc] ;; 2e: 01c1 add ecx, eax
;; 2f: 01c1 add ecx, eax ;; 30: 8b442414 mov eax, dword ptr [rsp + 0x14]
;; 31: 8b442408 mov eax, dword ptr [rsp + 8] ;; 34: 01c1 add ecx, eax
;; 35: 01c1 add ecx, eax ;; 36: 8b442410 mov eax, dword ptr [rsp + 0x10]
;; 37: 8b442404 mov eax, dword ptr [rsp + 4] ;; 3a: 01c1 add ecx, eax
;; 3b: 01c1 add ecx, eax ;; 3c: 8b44240c mov eax, dword ptr [rsp + 0xc]
;; 3d: 8b0424 mov eax, dword ptr [rsp]
;; 40: 01c1 add ecx, eax ;; 40: 01c1 add ecx, eax
;; 42: 8b4510 mov eax, dword ptr [rbp + 0x10] ;; 42: 8b442408 mov eax, dword ptr [rsp + 8]
;; 45: 01c1 add ecx, eax ;; 46: 01c1 add ecx, eax
;; 47: 8b4518 mov eax, dword ptr [rbp + 0x18] ;; 48: 8b4510 mov eax, dword ptr [rbp + 0x10]
;; 4a: 01c1 add ecx, eax ;; 4b: 01c1 add ecx, eax
;; 4c: 8b4520 mov eax, dword ptr [rbp + 0x20] ;; 4d: 8b4518 mov eax, dword ptr [rbp + 0x18]
;; 4f: 01c1 add ecx, eax ;; 50: 01c1 add ecx, eax
;; 51: 4889c8 mov rax, rcx ;; 52: 8b4520 mov eax, dword ptr [rbp + 0x20]
;; 54: 4883c418 add rsp, 0x18 ;; 55: 01c1 add ecx, eax
;; 58: 5d pop rbp ;; 57: 4889c8 mov rax, rcx
;; 59: c3 ret ;; 5a: 4883c420 add rsp, 0x20
;; 5e: 5d pop rbp
;; 5f: c3 ret

59
winch/filetests/filetests/x64/call/simple.wat

@ -15,35 +15,36 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 48c7042400000000 mov qword ptr [rsp], 0 ;; 8: 48c744240800000000
;; 10: 4883ec10 sub rsp, 0x10 ;; mov qword ptr [rsp + 8], 0
;; 14: bf14000000 mov edi, 0x14 ;; 11: 4c89742404 mov qword ptr [rsp + 4], r14
;; 19: be50000000 mov esi, 0x50 ;; 16: bf14000000 mov edi, 0x14
;; 1e: e800000000 call 0x23 ;; 1b: be50000000 mov esi, 0x50
;; 23: 4883c410 add rsp, 0x10 ;; 20: e800000000 call 0x25
;; 27: b902000000 mov ecx, 2 ;; 25: b902000000 mov ecx, 2
;; 2c: 894c2404 mov dword ptr [rsp + 4], ecx ;; 2a: 894c240c mov dword ptr [rsp + 0xc], ecx
;; 30: 50 push rax ;; 2e: 50 push rax
;; 31: 448b5c240c mov r11d, dword ptr [rsp + 0xc] ;; 2f: 448b5c2414 mov r11d, dword ptr [rsp + 0x14]
;; 36: 4153 push r11 ;; 34: 4153 push r11
;; 38: 59 pop rcx ;; 36: 59 pop rcx
;; 39: 58 pop rax ;; 37: 58 pop rax
;; 3a: 31d2 xor edx, edx ;; 38: 31d2 xor edx, edx
;; 3c: f7f1 div ecx ;; 3a: f7f1 div ecx
;; 3e: 4883c408 add rsp, 8 ;; 3c: 4883c410 add rsp, 0x10
;; 42: 5d pop rbp ;; 40: 5d pop rbp
;; 43: c3 ret ;; 41: c3 ret
;; ;;
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c2404 mov dword ptr [rsp + 4], edi ;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 893424 mov dword ptr [rsp], esi ;; c: 89742408 mov dword ptr [rsp + 8], esi
;; f: 8b0424 mov eax, dword ptr [rsp] ;; 10: 4c893424 mov qword ptr [rsp], r14
;; 12: 8b4c2404 mov ecx, dword ptr [rsp + 4] ;; 14: 8b442408 mov eax, dword ptr [rsp + 8]
;; 16: 0fafc8 imul ecx, eax ;; 18: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 19: 4889c8 mov rax, rcx ;; 1c: 0fafc8 imul ecx, eax
;; 1c: 4883c408 add rsp, 8 ;; 1f: 4889c8 mov rax, rcx
;; 20: 5d pop rbp ;; 22: 4883c410 add rsp, 0x10
;; 21: c3 ret ;; 26: 5d pop rbp
;; 27: c3 ret

11
winch/filetests/filetests/x64/i32_add/const.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b80a000000 mov eax, 0xa ;; 4: 4883ec08 sub rsp, 8
;; 9: 83c014 add eax, 0x14 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b80a000000 mov eax, 0xa
;; d: c3 ret ;; 11: 83c014 add eax, 0x14
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

28
winch/filetests/filetests/x64/i32_add/locals.wat

@ -18,16 +18,18 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 48c7042400000000 mov qword ptr [rsp], 0 ;; 8: 48c744240800000000
;; 10: b80a000000 mov eax, 0xa ;; mov qword ptr [rsp + 8], 0
;; 15: 89442404 mov dword ptr [rsp + 4], eax ;; 11: 4c893424 mov qword ptr [rsp], r14
;; 19: b814000000 mov eax, 0x14 ;; 15: b80a000000 mov eax, 0xa
;; 1e: 890424 mov dword ptr [rsp], eax ;; 1a: 8944240c mov dword ptr [rsp + 0xc], eax
;; 21: 8b0424 mov eax, dword ptr [rsp] ;; 1e: b814000000 mov eax, 0x14
;; 24: 8b4c2404 mov ecx, dword ptr [rsp + 4] ;; 23: 89442408 mov dword ptr [rsp + 8], eax
;; 28: 01c1 add ecx, eax ;; 27: 8b442408 mov eax, dword ptr [rsp + 8]
;; 2a: 4889c8 mov rax, rcx ;; 2b: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 2d: 4883c408 add rsp, 8 ;; 2f: 01c1 add ecx, eax
;; 31: 5d pop rbp ;; 31: 4889c8 mov rax, rcx
;; 32: c3 ret ;; 34: 4883c410 add rsp, 0x10
;; 38: 5d pop rbp
;; 39: c3 ret

11
winch/filetests/filetests/x64/i32_add/max.wat

@ -8,7 +8,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffff7f mov eax, 0x7fffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: 83c001 add eax, 1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b8ffffff7f mov eax, 0x7fffffff
;; d: c3 ret ;; 11: 83c001 add eax, 1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_add/max_one.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b800000080 mov eax, 0x80000000 ;; 4: 4883ec08 sub rsp, 8
;; 9: 83c0ff add eax, -1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b800000080 mov eax, 0x80000000
;; d: c3 ret ;; 11: 83c0ff add eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_add/mixed.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: 83c001 add eax, 1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b8ffffffff mov eax, 0xffffffff
;; d: c3 ret ;; 11: 83c001 add eax, 1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

21
winch/filetests/filetests/x64/i32_add/params.wat

@ -9,13 +9,14 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c2404 mov dword ptr [rsp + 4], edi ;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 893424 mov dword ptr [rsp], esi ;; c: 89742408 mov dword ptr [rsp + 8], esi
;; f: 8b0424 mov eax, dword ptr [rsp] ;; 10: 4c893424 mov qword ptr [rsp], r14
;; 12: 8b4c2404 mov ecx, dword ptr [rsp + 4] ;; 14: 8b442408 mov eax, dword ptr [rsp + 8]
;; 16: 01c1 add ecx, eax ;; 18: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 18: 4889c8 mov rax, rcx ;; 1c: 01c1 add ecx, eax
;; 1b: 4883c408 add rsp, 8 ;; 1e: 4889c8 mov rax, rcx
;; 1f: 5d pop rbp ;; 21: 4883c410 add rsp, 0x10
;; 20: c3 ret ;; 25: 5d pop rbp
;; 26: c3 ret

11
winch/filetests/filetests/x64/i32_add/signed.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: 83c0ff add eax, -1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b8ffffffff mov eax, 0xffffffff
;; d: c3 ret ;; 11: 83c0ff add eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_add/unsigned_with_zero.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b801000000 mov eax, 1 ;; 4: 4883ec08 sub rsp, 8
;; 9: 83c000 add eax, 0 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b801000000 mov eax, 1
;; d: c3 ret ;; 11: 83c000 add eax, 0
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

21
winch/filetests/filetests/x64/i32_divs/const.wat

@ -9,12 +9,15 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b90a000000 mov ecx, 0xa ;; 4: 4883ec08 sub rsp, 8
;; 9: b814000000 mov eax, 0x14 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 83f900 cmp ecx, 0 ;; c: b90a000000 mov ecx, 0xa
;; 11: 0f8405000000 je 0x1c ;; 11: b814000000 mov eax, 0x14
;; 17: 99 cdq ;; 16: 83f900 cmp ecx, 0
;; 18: f7f9 idiv ecx ;; 19: 0f8409000000 je 0x28
;; 1a: 5d pop rbp ;; 1f: 99 cdq
;; 1b: c3 ret ;; 20: f7f9 idiv ecx
;; 1c: 0f0b ud2 ;; 22: 4883c408 add rsp, 8
;; 26: 5d pop rbp
;; 27: c3 ret
;; 28: 0f0b ud2

21
winch/filetests/filetests/x64/i32_divs/one_zero.wat

@ -9,12 +9,15 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0 ;; 4: 4883ec08 sub rsp, 8
;; 9: b801000000 mov eax, 1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 83f900 cmp ecx, 0 ;; c: b900000000 mov ecx, 0
;; 11: 0f8405000000 je 0x1c ;; 11: b801000000 mov eax, 1
;; 17: 99 cdq ;; 16: 83f900 cmp ecx, 0
;; 18: f7f9 idiv ecx ;; 19: 0f8409000000 je 0x28
;; 1a: 5d pop rbp ;; 1f: 99 cdq
;; 1b: c3 ret ;; 20: f7f9 idiv ecx
;; 1c: 0f0b ud2 ;; 22: 4883c408 add rsp, 8
;; 26: 5d pop rbp
;; 27: c3 ret
;; 28: 0f0b ud2

21
winch/filetests/filetests/x64/i32_divs/overflow.wat

@ -9,12 +9,15 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b9ffffffff mov ecx, 0xffffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: b800000080 mov eax, 0x80000000 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 83f900 cmp ecx, 0 ;; c: b9ffffffff mov ecx, 0xffffffff
;; 11: 0f8405000000 je 0x1c ;; 11: b800000080 mov eax, 0x80000000
;; 17: 99 cdq ;; 16: 83f900 cmp ecx, 0
;; 18: f7f9 idiv ecx ;; 19: 0f8409000000 je 0x28
;; 1a: 5d pop rbp ;; 1f: 99 cdq
;; 1b: c3 ret ;; 20: f7f9 idiv ecx
;; 1c: 0f0b ud2 ;; 22: 4883c408 add rsp, 8
;; 26: 5d pop rbp
;; 27: c3 ret
;; 28: 0f0b ud2

27
winch/filetests/filetests/x64/i32_divs/params.wat

@ -9,16 +9,17 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c2404 mov dword ptr [rsp + 4], edi ;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 893424 mov dword ptr [rsp], esi ;; c: 89742408 mov dword ptr [rsp + 8], esi
;; f: 8b0c24 mov ecx, dword ptr [rsp] ;; 10: 4c893424 mov qword ptr [rsp], r14
;; 12: 8b442404 mov eax, dword ptr [rsp + 4] ;; 14: 8b4c2408 mov ecx, dword ptr [rsp + 8]
;; 16: 83f900 cmp ecx, 0 ;; 18: 8b44240c mov eax, dword ptr [rsp + 0xc]
;; 19: 0f8409000000 je 0x28 ;; 1c: 83f900 cmp ecx, 0
;; 1f: 99 cdq ;; 1f: 0f8409000000 je 0x2e
;; 20: f7f9 idiv ecx ;; 25: 99 cdq
;; 22: 4883c408 add rsp, 8 ;; 26: f7f9 idiv ecx
;; 26: 5d pop rbp ;; 28: 4883c410 add rsp, 0x10
;; 27: c3 ret ;; 2c: 5d pop rbp
;; 28: 0f0b ud2 ;; 2d: c3 ret
;; 2e: 0f0b ud2

21
winch/filetests/filetests/x64/i32_divs/zero_zero.wat

@ -9,12 +9,15 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0 ;; 4: 4883ec08 sub rsp, 8
;; 9: b800000000 mov eax, 0 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 83f900 cmp ecx, 0 ;; c: b900000000 mov ecx, 0
;; 11: 0f8405000000 je 0x1c ;; 11: b800000000 mov eax, 0
;; 17: 99 cdq ;; 16: 83f900 cmp ecx, 0
;; 18: f7f9 idiv ecx ;; 19: 0f8409000000 je 0x28
;; 1a: 5d pop rbp ;; 1f: 99 cdq
;; 1b: c3 ret ;; 20: f7f9 idiv ecx
;; 1c: 0f0b ud2 ;; 22: 4883c408 add rsp, 8
;; 26: 5d pop rbp
;; 27: c3 ret
;; 28: 0f0b ud2

15
winch/filetests/filetests/x64/i32_divu/const.wat

@ -9,9 +9,12 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b90a000000 mov ecx, 0xa ;; 4: 4883ec08 sub rsp, 8
;; 9: b814000000 mov eax, 0x14 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 31d2 xor edx, edx ;; c: b90a000000 mov ecx, 0xa
;; 10: f7f1 div ecx ;; 11: b814000000 mov eax, 0x14
;; 12: 5d pop rbp ;; 16: 31d2 xor edx, edx
;; 13: c3 ret ;; 18: f7f1 div ecx
;; 1a: 4883c408 add rsp, 8
;; 1e: 5d pop rbp
;; 1f: c3 ret

15
winch/filetests/filetests/x64/i32_divu/one_zero.wat

@ -9,9 +9,12 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0 ;; 4: 4883ec08 sub rsp, 8
;; 9: b801000000 mov eax, 1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 31d2 xor edx, edx ;; c: b900000000 mov ecx, 0
;; 10: f7f1 div ecx ;; 11: b801000000 mov eax, 1
;; 12: 5d pop rbp ;; 16: 31d2 xor edx, edx
;; 13: c3 ret ;; 18: f7f1 div ecx
;; 1a: 4883c408 add rsp, 8
;; 1e: 5d pop rbp
;; 1f: c3 ret

21
winch/filetests/filetests/x64/i32_divu/params.wat

@ -9,13 +9,14 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c2404 mov dword ptr [rsp + 4], edi ;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 893424 mov dword ptr [rsp], esi ;; c: 89742408 mov dword ptr [rsp + 8], esi
;; f: 8b0c24 mov ecx, dword ptr [rsp] ;; 10: 4c893424 mov qword ptr [rsp], r14
;; 12: 8b442404 mov eax, dword ptr [rsp + 4] ;; 14: 8b4c2408 mov ecx, dword ptr [rsp + 8]
;; 16: 31d2 xor edx, edx ;; 18: 8b44240c mov eax, dword ptr [rsp + 0xc]
;; 18: f7f1 div ecx ;; 1c: 31d2 xor edx, edx
;; 1a: 4883c408 add rsp, 8 ;; 1e: f7f1 div ecx
;; 1e: 5d pop rbp ;; 20: 4883c410 add rsp, 0x10
;; 1f: c3 ret ;; 24: 5d pop rbp
;; 25: c3 ret

15
winch/filetests/filetests/x64/i32_divu/signed.wat

@ -9,9 +9,12 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b9ffffffff mov ecx, 0xffffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: b8ffffffff mov eax, 0xffffffff ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 31d2 xor edx, edx ;; c: b9ffffffff mov ecx, 0xffffffff
;; 10: f7f1 div ecx ;; 11: b8ffffffff mov eax, 0xffffffff
;; 12: 5d pop rbp ;; 16: 31d2 xor edx, edx
;; 13: c3 ret ;; 18: f7f1 div ecx
;; 1a: 4883c408 add rsp, 8
;; 1e: 5d pop rbp
;; 1f: c3 ret

15
winch/filetests/filetests/x64/i32_divu/zero_zero.wat

@ -9,9 +9,12 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0 ;; 4: 4883ec08 sub rsp, 8
;; 9: b800000000 mov eax, 0 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 31d2 xor edx, edx ;; c: b900000000 mov ecx, 0
;; 10: f7f1 div ecx ;; 11: b800000000 mov eax, 0
;; 12: 5d pop rbp ;; 16: 31d2 xor edx, edx
;; 13: c3 ret ;; 18: f7f1 div ecx
;; 1a: 4883c408 add rsp, 8
;; 1e: 5d pop rbp
;; 1f: c3 ret

11
winch/filetests/filetests/x64/i32_mul/const.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b80a000000 mov eax, 0xa ;; 4: 4883ec08 sub rsp, 8
;; 9: 6bc014 imul eax, eax, 0x14 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b80a000000 mov eax, 0xa
;; d: c3 ret ;; 11: 6bc014 imul eax, eax, 0x14
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

28
winch/filetests/filetests/x64/i32_mul/locals.wat

@ -18,16 +18,18 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 48c7042400000000 mov qword ptr [rsp], 0 ;; 8: 48c744240800000000
;; 10: b80a000000 mov eax, 0xa ;; mov qword ptr [rsp + 8], 0
;; 15: 89442404 mov dword ptr [rsp + 4], eax ;; 11: 4c893424 mov qword ptr [rsp], r14
;; 19: b814000000 mov eax, 0x14 ;; 15: b80a000000 mov eax, 0xa
;; 1e: 890424 mov dword ptr [rsp], eax ;; 1a: 8944240c mov dword ptr [rsp + 0xc], eax
;; 21: 8b0424 mov eax, dword ptr [rsp] ;; 1e: b814000000 mov eax, 0x14
;; 24: 8b4c2404 mov ecx, dword ptr [rsp + 4] ;; 23: 89442408 mov dword ptr [rsp + 8], eax
;; 28: 0fafc8 imul ecx, eax ;; 27: 8b442408 mov eax, dword ptr [rsp + 8]
;; 2b: 4889c8 mov rax, rcx ;; 2b: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 2e: 4883c408 add rsp, 8 ;; 2f: 0fafc8 imul ecx, eax
;; 32: 5d pop rbp ;; 32: 4889c8 mov rax, rcx
;; 33: c3 ret ;; 35: 4883c410 add rsp, 0x10
;; 39: 5d pop rbp
;; 3a: c3 ret

11
winch/filetests/filetests/x64/i32_mul/max.wat

@ -8,7 +8,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffff7f mov eax, 0x7fffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: 6bc0ff imul eax, eax, -1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b8ffffff7f mov eax, 0x7fffffff
;; d: c3 ret ;; 11: 6bc0ff imul eax, eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_mul/max_one.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b800000080 mov eax, 0x80000000 ;; 4: 4883ec08 sub rsp, 8
;; 9: 6bc0ff imul eax, eax, -1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b800000080 mov eax, 0x80000000
;; d: c3 ret ;; 11: 6bc0ff imul eax, eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_mul/mixed.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: 6bc001 imul eax, eax, 1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b8ffffffff mov eax, 0xffffffff
;; d: c3 ret ;; 11: 6bc001 imul eax, eax, 1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

21
winch/filetests/filetests/x64/i32_mul/params.wat

@ -9,13 +9,14 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c2404 mov dword ptr [rsp + 4], edi ;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 893424 mov dword ptr [rsp], esi ;; c: 89742408 mov dword ptr [rsp + 8], esi
;; f: 8b0424 mov eax, dword ptr [rsp] ;; 10: 4c893424 mov qword ptr [rsp], r14
;; 12: 8b4c2404 mov ecx, dword ptr [rsp + 4] ;; 14: 8b442408 mov eax, dword ptr [rsp + 8]
;; 16: 0fafc8 imul ecx, eax ;; 18: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 19: 4889c8 mov rax, rcx ;; 1c: 0fafc8 imul ecx, eax
;; 1c: 4883c408 add rsp, 8 ;; 1f: 4889c8 mov rax, rcx
;; 20: 5d pop rbp ;; 22: 4883c410 add rsp, 0x10
;; 21: c3 ret ;; 26: 5d pop rbp
;; 27: c3 ret

11
winch/filetests/filetests/x64/i32_mul/signed.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: 6bc0ff imul eax, eax, -1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b8ffffffff mov eax, 0xffffffff
;; d: c3 ret ;; 11: 6bc0ff imul eax, eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_mul/unsigned_with_zero.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b801000000 mov eax, 1 ;; 4: 4883ec08 sub rsp, 8
;; 9: 6bc000 imul eax, eax, 0 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b801000000 mov eax, 1
;; d: c3 ret ;; 11: 6bc000 imul eax, eax, 0
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

25
winch/filetests/filetests/x64/i32_rems/const.wat

@ -9,14 +9,17 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b905000000 mov ecx, 5 ;; 4: 4883ec08 sub rsp, 8
;; 9: b807000000 mov eax, 7 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 99 cdq ;; c: b905000000 mov ecx, 5
;; f: 83f9ff cmp ecx, -1 ;; 11: b807000000 mov eax, 7
;; 12: 0f850a000000 jne 0x22 ;; 16: 99 cdq
;; 18: ba00000000 mov edx, 0 ;; 17: 83f9ff cmp ecx, -1
;; 1d: e902000000 jmp 0x24 ;; 1a: 0f850a000000 jne 0x2a
;; 22: f7f9 idiv ecx ;; 20: ba00000000 mov edx, 0
;; 24: 4889d0 mov rax, rdx ;; 25: e902000000 jmp 0x2c
;; 27: 5d pop rbp ;; 2a: f7f9 idiv ecx
;; 28: c3 ret ;; 2c: 4889d0 mov rax, rdx
;; 2f: 4883c408 add rsp, 8
;; 33: 5d pop rbp
;; 34: c3 ret

25
winch/filetests/filetests/x64/i32_rems/one_zero.wat

@ -9,14 +9,17 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0 ;; 4: 4883ec08 sub rsp, 8
;; 9: b801000000 mov eax, 1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 99 cdq ;; c: b900000000 mov ecx, 0
;; f: 83f9ff cmp ecx, -1 ;; 11: b801000000 mov eax, 1
;; 12: 0f850a000000 jne 0x22 ;; 16: 99 cdq
;; 18: ba00000000 mov edx, 0 ;; 17: 83f9ff cmp ecx, -1
;; 1d: e902000000 jmp 0x24 ;; 1a: 0f850a000000 jne 0x2a
;; 22: f7f9 idiv ecx ;; 20: ba00000000 mov edx, 0
;; 24: 4889d0 mov rax, rdx ;; 25: e902000000 jmp 0x2c
;; 27: 5d pop rbp ;; 2a: f7f9 idiv ecx
;; 28: c3 ret ;; 2c: 4889d0 mov rax, rdx
;; 2f: 4883c408 add rsp, 8
;; 33: 5d pop rbp
;; 34: c3 ret

25
winch/filetests/filetests/x64/i32_rems/overflow.wat

@ -9,14 +9,17 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b9ffffffff mov ecx, 0xffffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: b800000080 mov eax, 0x80000000 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 99 cdq ;; c: b9ffffffff mov ecx, 0xffffffff
;; f: 83f9ff cmp ecx, -1 ;; 11: b800000080 mov eax, 0x80000000
;; 12: 0f850a000000 jne 0x22 ;; 16: 99 cdq
;; 18: ba00000000 mov edx, 0 ;; 17: 83f9ff cmp ecx, -1
;; 1d: e902000000 jmp 0x24 ;; 1a: 0f850a000000 jne 0x2a
;; 22: f7f9 idiv ecx ;; 20: ba00000000 mov edx, 0
;; 24: 4889d0 mov rax, rdx ;; 25: e902000000 jmp 0x2c
;; 27: 5d pop rbp ;; 2a: f7f9 idiv ecx
;; 28: c3 ret ;; 2c: 4889d0 mov rax, rdx
;; 2f: 4883c408 add rsp, 8
;; 33: 5d pop rbp
;; 34: c3 ret

31
winch/filetests/filetests/x64/i32_rems/params.wat

@ -9,18 +9,19 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c2404 mov dword ptr [rsp + 4], edi ;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 893424 mov dword ptr [rsp], esi ;; c: 89742408 mov dword ptr [rsp + 8], esi
;; f: 8b0c24 mov ecx, dword ptr [rsp] ;; 10: 4c893424 mov qword ptr [rsp], r14
;; 12: 8b442404 mov eax, dword ptr [rsp + 4] ;; 14: 8b4c2408 mov ecx, dword ptr [rsp + 8]
;; 16: 99 cdq ;; 18: 8b44240c mov eax, dword ptr [rsp + 0xc]
;; 17: 83f9ff cmp ecx, -1 ;; 1c: 99 cdq
;; 1a: 0f850a000000 jne 0x2a ;; 1d: 83f9ff cmp ecx, -1
;; 20: ba00000000 mov edx, 0 ;; 20: 0f850a000000 jne 0x30
;; 25: e902000000 jmp 0x2c ;; 26: ba00000000 mov edx, 0
;; 2a: f7f9 idiv ecx ;; 2b: e902000000 jmp 0x32
;; 2c: 4889d0 mov rax, rdx ;; 30: f7f9 idiv ecx
;; 2f: 4883c408 add rsp, 8 ;; 32: 4889d0 mov rax, rdx
;; 33: 5d pop rbp ;; 35: 4883c410 add rsp, 0x10
;; 34: c3 ret ;; 39: 5d pop rbp
;; 3a: c3 ret

25
winch/filetests/filetests/x64/i32_rems/zero_zero.wat

@ -9,14 +9,17 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0 ;; 4: 4883ec08 sub rsp, 8
;; 9: b800000000 mov eax, 0 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 99 cdq ;; c: b900000000 mov ecx, 0
;; f: 83f9ff cmp ecx, -1 ;; 11: b800000000 mov eax, 0
;; 12: 0f850a000000 jne 0x22 ;; 16: 99 cdq
;; 18: ba00000000 mov edx, 0 ;; 17: 83f9ff cmp ecx, -1
;; 1d: e902000000 jmp 0x24 ;; 1a: 0f850a000000 jne 0x2a
;; 22: f7f9 idiv ecx ;; 20: ba00000000 mov edx, 0
;; 24: 4889d0 mov rax, rdx ;; 25: e902000000 jmp 0x2c
;; 27: 5d pop rbp ;; 2a: f7f9 idiv ecx
;; 28: c3 ret ;; 2c: 4889d0 mov rax, rdx
;; 2f: 4883c408 add rsp, 8
;; 33: 5d pop rbp
;; 34: c3 ret

17
winch/filetests/filetests/x64/i32_remu/const.wat

@ -9,10 +9,13 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b905000000 mov ecx, 5 ;; 4: 4883ec08 sub rsp, 8
;; 9: b807000000 mov eax, 7 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 31d2 xor edx, edx ;; c: b905000000 mov ecx, 5
;; 10: f7f1 div ecx ;; 11: b807000000 mov eax, 7
;; 12: 4889d0 mov rax, rdx ;; 16: 31d2 xor edx, edx
;; 15: 5d pop rbp ;; 18: f7f1 div ecx
;; 16: c3 ret ;; 1a: 4889d0 mov rax, rdx
;; 1d: 4883c408 add rsp, 8
;; 21: 5d pop rbp
;; 22: c3 ret

17
winch/filetests/filetests/x64/i32_remu/one_zero.wat

@ -9,10 +9,13 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0 ;; 4: 4883ec08 sub rsp, 8
;; 9: b801000000 mov eax, 1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 31d2 xor edx, edx ;; c: b900000000 mov ecx, 0
;; 10: f7f1 div ecx ;; 11: b801000000 mov eax, 1
;; 12: 4889d0 mov rax, rdx ;; 16: 31d2 xor edx, edx
;; 15: 5d pop rbp ;; 18: f7f1 div ecx
;; 16: c3 ret ;; 1a: 4889d0 mov rax, rdx
;; 1d: 4883c408 add rsp, 8
;; 21: 5d pop rbp
;; 22: c3 ret

23
winch/filetests/filetests/x64/i32_remu/params.wat

@ -9,14 +9,15 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c2404 mov dword ptr [rsp + 4], edi ;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 893424 mov dword ptr [rsp], esi ;; c: 89742408 mov dword ptr [rsp + 8], esi
;; f: 8b0c24 mov ecx, dword ptr [rsp] ;; 10: 4c893424 mov qword ptr [rsp], r14
;; 12: 8b442404 mov eax, dword ptr [rsp + 4] ;; 14: 8b4c2408 mov ecx, dword ptr [rsp + 8]
;; 16: 31d2 xor edx, edx ;; 18: 8b44240c mov eax, dword ptr [rsp + 0xc]
;; 18: f7f1 div ecx ;; 1c: 31d2 xor edx, edx
;; 1a: 4889d0 mov rax, rdx ;; 1e: f7f1 div ecx
;; 1d: 4883c408 add rsp, 8 ;; 20: 4889d0 mov rax, rdx
;; 21: 5d pop rbp ;; 23: 4883c410 add rsp, 0x10
;; 22: c3 ret ;; 27: 5d pop rbp
;; 28: c3 ret

17
winch/filetests/filetests/x64/i32_remu/signed.wat

@ -9,10 +9,13 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b9ffffffff mov ecx, 0xffffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: b8ffffffff mov eax, 0xffffffff ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 31d2 xor edx, edx ;; c: b9ffffffff mov ecx, 0xffffffff
;; 10: f7f1 div ecx ;; 11: b8ffffffff mov eax, 0xffffffff
;; 12: 4889d0 mov rax, rdx ;; 16: 31d2 xor edx, edx
;; 15: 5d pop rbp ;; 18: f7f1 div ecx
;; 16: c3 ret ;; 1a: 4889d0 mov rax, rdx
;; 1d: 4883c408 add rsp, 8
;; 21: 5d pop rbp
;; 22: c3 ret

17
winch/filetests/filetests/x64/i32_remu/zero_zero.wat

@ -9,10 +9,13 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b900000000 mov ecx, 0 ;; 4: 4883ec08 sub rsp, 8
;; 9: b800000000 mov eax, 0 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; e: 31d2 xor edx, edx ;; c: b900000000 mov ecx, 0
;; 10: f7f1 div ecx ;; 11: b800000000 mov eax, 0
;; 12: 4889d0 mov rax, rdx ;; 16: 31d2 xor edx, edx
;; 15: 5d pop rbp ;; 18: f7f1 div ecx
;; 16: c3 ret ;; 1a: 4889d0 mov rax, rdx
;; 1d: 4883c408 add rsp, 8
;; 21: 5d pop rbp
;; 22: c3 ret

11
winch/filetests/filetests/x64/i32_sub/const.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b80a000000 mov eax, 0xa ;; 4: 4883ec08 sub rsp, 8
;; 9: 83e814 sub eax, 0x14 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b80a000000 mov eax, 0xa
;; d: c3 ret ;; 11: 83e814 sub eax, 0x14
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

28
winch/filetests/filetests/x64/i32_sub/locals.wat

@ -18,16 +18,18 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 48c7042400000000 mov qword ptr [rsp], 0 ;; 8: 48c744240800000000
;; 10: b80a000000 mov eax, 0xa ;; mov qword ptr [rsp + 8], 0
;; 15: 89442404 mov dword ptr [rsp + 4], eax ;; 11: 4c893424 mov qword ptr [rsp], r14
;; 19: b814000000 mov eax, 0x14 ;; 15: b80a000000 mov eax, 0xa
;; 1e: 890424 mov dword ptr [rsp], eax ;; 1a: 8944240c mov dword ptr [rsp + 0xc], eax
;; 21: 8b0424 mov eax, dword ptr [rsp] ;; 1e: b814000000 mov eax, 0x14
;; 24: 8b4c2404 mov ecx, dword ptr [rsp + 4] ;; 23: 89442408 mov dword ptr [rsp + 8], eax
;; 28: 29c1 sub ecx, eax ;; 27: 8b442408 mov eax, dword ptr [rsp + 8]
;; 2a: 4889c8 mov rax, rcx ;; 2b: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 2d: 4883c408 add rsp, 8 ;; 2f: 29c1 sub ecx, eax
;; 31: 5d pop rbp ;; 31: 4889c8 mov rax, rcx
;; 32: c3 ret ;; 34: 4883c410 add rsp, 0x10
;; 38: 5d pop rbp
;; 39: c3 ret

11
winch/filetests/filetests/x64/i32_sub/max.wat

@ -8,7 +8,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffff7f mov eax, 0x7fffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: 83e8ff sub eax, -1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b8ffffff7f mov eax, 0x7fffffff
;; d: c3 ret ;; 11: 83e8ff sub eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_sub/max_one.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b800000080 mov eax, 0x80000000 ;; 4: 4883ec08 sub rsp, 8
;; 9: 83e801 sub eax, 1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b800000080 mov eax, 0x80000000
;; d: c3 ret ;; 11: 83e801 sub eax, 1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_sub/mixed.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: 83e801 sub eax, 1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b8ffffffff mov eax, 0xffffffff
;; d: c3 ret ;; 11: 83e801 sub eax, 1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

21
winch/filetests/filetests/x64/i32_sub/params.wat

@ -9,13 +9,14 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec08 sub rsp, 8 ;; 4: 4883ec10 sub rsp, 0x10
;; 8: 897c2404 mov dword ptr [rsp + 4], edi ;; 8: 897c240c mov dword ptr [rsp + 0xc], edi
;; c: 893424 mov dword ptr [rsp], esi ;; c: 89742408 mov dword ptr [rsp + 8], esi
;; f: 8b0424 mov eax, dword ptr [rsp] ;; 10: 4c893424 mov qword ptr [rsp], r14
;; 12: 8b4c2404 mov ecx, dword ptr [rsp + 4] ;; 14: 8b442408 mov eax, dword ptr [rsp + 8]
;; 16: 29c1 sub ecx, eax ;; 18: 8b4c240c mov ecx, dword ptr [rsp + 0xc]
;; 18: 4889c8 mov rax, rcx ;; 1c: 29c1 sub ecx, eax
;; 1b: 4883c408 add rsp, 8 ;; 1e: 4889c8 mov rax, rcx
;; 1f: 5d pop rbp ;; 21: 4883c410 add rsp, 0x10
;; 20: c3 ret ;; 25: 5d pop rbp
;; 26: c3 ret

11
winch/filetests/filetests/x64/i32_sub/signed.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b8ffffffff mov eax, 0xffffffff ;; 4: 4883ec08 sub rsp, 8
;; 9: 83e8ff sub eax, -1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b8ffffffff mov eax, 0xffffffff
;; d: c3 ret ;; 11: 83e8ff sub eax, -1
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i32_sub/unsigned_with_zero.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: b801000000 mov eax, 1 ;; 4: 4883ec08 sub rsp, 8
;; 9: 83c000 add eax, 0 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 5d pop rbp ;; c: b801000000 mov eax, 1
;; d: c3 ret ;; 11: 83c000 add eax, 0
;; 14: 4883c408 add rsp, 8
;; 18: 5d pop rbp
;; 19: c3 ret

11
winch/filetests/filetests/x64/i64_add/const.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c00a000000 mov rax, 0xa ;; 4: 4883ec08 sub rsp, 8
;; b: 4883c014 add rax, 0x14 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; f: 5d pop rbp ;; c: 48c7c00a000000 mov rax, 0xa
;; 10: c3 ret ;; 13: 4883c014 add rax, 0x14
;; 17: 4883c408 add rsp, 8
;; 1b: 5d pop rbp
;; 1c: c3 ret

29
winch/filetests/filetests/x64/i64_add/locals.wat

@ -18,18 +18,19 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec10 sub rsp, 0x10 ;; 4: 4883ec18 sub rsp, 0x18
;; 8: 4531db xor r11d, r11d ;; 8: 4531db xor r11d, r11d
;; b: 4c895c2408 mov qword ptr [rsp + 8], r11 ;; b: 4c895c2410 mov qword ptr [rsp + 0x10], r11
;; 10: 4c891c24 mov qword ptr [rsp], r11 ;; 10: 4c895c2408 mov qword ptr [rsp + 8], r11
;; 14: 48c7c00a000000 mov rax, 0xa ;; 15: 4c893424 mov qword ptr [rsp], r14
;; 1b: 4889442408 mov qword ptr [rsp + 8], rax ;; 19: 48c7c00a000000 mov rax, 0xa
;; 20: 48c7c014000000 mov rax, 0x14 ;; 20: 4889442410 mov qword ptr [rsp + 0x10], rax
;; 27: 48890424 mov qword ptr [rsp], rax ;; 25: 48c7c014000000 mov rax, 0x14
;; 2b: 488b0424 mov rax, qword ptr [rsp] ;; 2c: 4889442408 mov qword ptr [rsp + 8], rax
;; 2f: 488b4c2408 mov rcx, qword ptr [rsp + 8] ;; 31: 488b442408 mov rax, qword ptr [rsp + 8]
;; 34: 4801c1 add rcx, rax ;; 36: 488b4c2410 mov rcx, qword ptr [rsp + 0x10]
;; 37: 4889c8 mov rax, rcx ;; 3b: 4801c1 add rcx, rax
;; 3a: 4883c410 add rsp, 0x10 ;; 3e: 4889c8 mov rax, rcx
;; 3e: 5d pop rbp ;; 41: 4883c418 add rsp, 0x18
;; 3f: c3 ret ;; 45: 5d pop rbp
;; 46: c3 ret

13
winch/filetests/filetests/x64/i64_add/max.wat

@ -8,9 +8,12 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c001000000 mov rax, 1 ;; 4: 4883ec08 sub rsp, 8
;; b: 49bbffffffffffffff7f ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48c7c001000000 mov rax, 1
;; 13: 49bbffffffffffffff7f
;; movabs r11, 0x7fffffffffffffff ;; movabs r11, 0x7fffffffffffffff
;; 15: 4c01d8 add rax, r11 ;; 1d: 4c01d8 add rax, r11
;; 18: 5d pop rbp ;; 20: 4883c408 add rsp, 8
;; 19: c3 ret ;; 24: 5d pop rbp
;; 25: c3 ret

11
winch/filetests/filetests/x64/i64_add/max_one.wat

@ -9,8 +9,11 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 48b80000000000000080 ;; 4: 4883ec08 sub rsp, 8
;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48b80000000000000080
;; movabs rax, 0x8000000000000000 ;; movabs rax, 0x8000000000000000
;; e: 4883c0ff add rax, -1 ;; 16: 4883c0ff add rax, -1
;; 12: 5d pop rbp ;; 1a: 4883c408 add rsp, 8
;; 13: c3 ret ;; 1e: 5d pop rbp
;; 1f: c3 ret

11
winch/filetests/filetests/x64/i64_add/mixed.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c0ffffffff mov rax, 0xffffffffffffffff ;; 4: 4883ec08 sub rsp, 8
;; b: 4883c001 add rax, 1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; f: 5d pop rbp ;; c: 48c7c0ffffffff mov rax, 0xffffffffffffffff
;; 10: c3 ret ;; 13: 4883c001 add rax, 1
;; 17: 4883c408 add rsp, 8
;; 1b: 5d pop rbp
;; 1c: c3 ret

21
winch/filetests/filetests/x64/i64_add/params.wat

@ -9,13 +9,14 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec10 sub rsp, 0x10 ;; 4: 4883ec18 sub rsp, 0x18
;; 8: 48897c2408 mov qword ptr [rsp + 8], rdi ;; 8: 48897c2410 mov qword ptr [rsp + 0x10], rdi
;; d: 48893424 mov qword ptr [rsp], rsi ;; d: 4889742408 mov qword ptr [rsp + 8], rsi
;; 11: 488b0424 mov rax, qword ptr [rsp] ;; 12: 4c893424 mov qword ptr [rsp], r14
;; 15: 488b4c2408 mov rcx, qword ptr [rsp + 8] ;; 16: 488b442408 mov rax, qword ptr [rsp + 8]
;; 1a: 4801c1 add rcx, rax ;; 1b: 488b4c2410 mov rcx, qword ptr [rsp + 0x10]
;; 1d: 4889c8 mov rax, rcx ;; 20: 4801c1 add rcx, rax
;; 20: 4883c410 add rsp, 0x10 ;; 23: 4889c8 mov rax, rcx
;; 24: 5d pop rbp ;; 26: 4883c418 add rsp, 0x18
;; 25: c3 ret ;; 2a: 5d pop rbp
;; 2b: c3 ret

11
winch/filetests/filetests/x64/i64_add/signed.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c0ffffffff mov rax, 0xffffffffffffffff ;; 4: 4883ec08 sub rsp, 8
;; b: 4883c0ff add rax, -1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; f: 5d pop rbp ;; c: 48c7c0ffffffff mov rax, 0xffffffffffffffff
;; 10: c3 ret ;; 13: 4883c0ff add rax, -1
;; 17: 4883c408 add rsp, 8
;; 1b: 5d pop rbp
;; 1c: c3 ret

11
winch/filetests/filetests/x64/i64_add/unsigned_with_zero.wat

@ -9,7 +9,10 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c001000000 mov rax, 1 ;; 4: 4883ec08 sub rsp, 8
;; b: 4883c000 add rax, 0 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; f: 5d pop rbp ;; c: 48c7c001000000 mov rax, 1
;; 10: c3 ret ;; 13: 4883c000 add rax, 0
;; 17: 4883c408 add rsp, 8
;; 1b: 5d pop rbp
;; 1c: c3 ret

21
winch/filetests/filetests/x64/i64_divs/const.wat

@ -9,12 +9,15 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c10a000000 mov rcx, 0xa ;; 4: 4883ec08 sub rsp, 8
;; b: 48c7c014000000 mov rax, 0x14 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; 12: 4883f900 cmp rcx, 0 ;; c: 48c7c10a000000 mov rcx, 0xa
;; 16: 0f8407000000 je 0x23 ;; 13: 48c7c014000000 mov rax, 0x14
;; 1c: 4899 cqo ;; 1a: 4883f900 cmp rcx, 0
;; 1e: 48f7f9 idiv rcx ;; 1e: 0f840b000000 je 0x2f
;; 21: 5d pop rbp ;; 24: 4899 cqo
;; 22: c3 ret ;; 26: 48f7f9 idiv rcx
;; 23: 0f0b ud2 ;; 29: 4883c408 add rsp, 8
;; 2d: 5d pop rbp
;; 2e: c3 ret
;; 2f: 0f0b ud2

21
winch/filetests/filetests/x64/i64_divs/one_zero.wat

@ -9,12 +9,15 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c100000000 mov rcx, 0 ;; 4: 4883ec08 sub rsp, 8
;; b: 48c7c001000000 mov rax, 1 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; 12: 4883f900 cmp rcx, 0 ;; c: 48c7c100000000 mov rcx, 0
;; 16: 0f8407000000 je 0x23 ;; 13: 48c7c001000000 mov rax, 1
;; 1c: 4899 cqo ;; 1a: 4883f900 cmp rcx, 0
;; 1e: 48f7f9 idiv rcx ;; 1e: 0f840b000000 je 0x2f
;; 21: 5d pop rbp ;; 24: 4899 cqo
;; 22: c3 ret ;; 26: 48f7f9 idiv rcx
;; 23: 0f0b ud2 ;; 29: 4883c408 add rsp, 8
;; 2d: 5d pop rbp
;; 2e: c3 ret
;; 2f: 0f0b ud2

21
winch/filetests/filetests/x64/i64_divs/overflow.wat

@ -9,13 +9,16 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 48c7c1ffffffff mov rcx, 0xffffffffffffffff ;; 4: 4883ec08 sub rsp, 8
;; b: 48b80000000000000080 ;; 8: 4c893424 mov qword ptr [rsp], r14
;; c: 48c7c1ffffffff mov rcx, 0xffffffffffffffff
;; 13: 48b80000000000000080
;; movabs rax, 0x8000000000000000 ;; movabs rax, 0x8000000000000000
;; 15: 4883f900 cmp rcx, 0 ;; 1d: 4883f900 cmp rcx, 0
;; 19: 0f8407000000 je 0x26 ;; 21: 0f840b000000 je 0x32
;; 1f: 4899 cqo ;; 27: 4899 cqo
;; 21: 48f7f9 idiv rcx ;; 29: 48f7f9 idiv rcx
;; 24: 5d pop rbp ;; 2c: 4883c408 add rsp, 8
;; 25: c3 ret ;; 30: 5d pop rbp
;; 26: 0f0b ud2 ;; 31: c3 ret
;; 32: 0f0b ud2

27
winch/filetests/filetests/x64/i64_divs/params.wat

@ -9,16 +9,17 @@
) )
;; 0: 55 push rbp ;; 0: 55 push rbp
;; 1: 4889e5 mov rbp, rsp ;; 1: 4889e5 mov rbp, rsp
;; 4: 4883ec10 sub rsp, 0x10 ;; 4: 4883ec18 sub rsp, 0x18
;; 8: 48897c2408 mov qword ptr [rsp + 8], rdi ;; 8: 48897c2410 mov qword ptr [rsp + 0x10], rdi
;; d: 48893424 mov qword ptr [rsp], rsi ;; d: 4889742408 mov qword ptr [rsp + 8], rsi
;; 11: 488b0c24 mov rcx, qword ptr [rsp] ;; 12: 4c893424 mov qword ptr [rsp], r14
;; 15: 488b442408 mov rax, qword ptr [rsp + 8] ;; 16: 488b4c2408 mov rcx, qword ptr [rsp + 8]
;; 1a: 4883f900 cmp rcx, 0 ;; 1b: 488b442410 mov rax, qword ptr [rsp + 0x10]
;; 1e: 0f840b000000 je 0x2f ;; 20: 4883f900 cmp rcx, 0
;; 24: 4899 cqo ;; 24: 0f840b000000 je 0x35
;; 26: 48f7f9 idiv rcx ;; 2a: 4899 cqo
;; 29: 4883c410 add rsp, 0x10 ;; 2c: 48f7f9 idiv rcx
;; 2d: 5d pop rbp ;; 2f: 4883c418 add rsp, 0x18
;; 2e: c3 ret ;; 33: 5d pop rbp
;; 2f: 0f0b ud2 ;; 34: c3 ret
;; 35: 0f0b ud2

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save