diff --git a/Cargo.lock b/Cargo.lock index 574c97a2f2..e5cd71f323 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2705,9 +2705,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.11.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422045212ea98508ae3d28025bc5aaa2bd4a9cdaecd442a08da2ee620ee9ea95" +checksum = "64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834" [[package]] name = "tempfile" diff --git a/Cargo.toml b/Cargo.toml index ab98691b70..5cc273d1f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ wasi-cap-std-sync = { path = "crates/wasi-common/cap-std-sync", version = "0.25. structopt = { version = "0.3.5", features = ["color", "suggestions"] } object = { version = "0.23.0", default-features = false, features = ["write"] } anyhow = "1.0.19" -target-lexicon = { version = "0.11.0", default-features = false } +target-lexicon = { version = "0.12.0", default-features = false } pretty_env_logger = "0.4.0" file-per-thread-logger = "0.1.1" wat = "1.0.36" diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index a5fe3acd3a..80a083250e 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -34,7 +34,7 @@ log = "0.4.8" termcolor = "1.1.2" capstone = { version = "0.7.0", optional = true } wat = { version = "1.0.36", optional = true } -target-lexicon = { version = "0.11", features = ["std"] } +target-lexicon = { version = "0.12", features = ["std"] } peepmatic-souper = { path = "./peepmatic/crates/souper", version = "0.72.0", optional = true } pretty_env_logger = "0.4.0" rayon = { version = "1", optional = true } diff --git a/cranelift/codegen/Cargo.toml b/cranelift/codegen/Cargo.toml index 068c7847a4..835a92ae64 100644 --- a/cranelift/codegen/Cargo.toml +++ b/cranelift/codegen/Cargo.toml @@ -17,7 +17,7 @@ cranelift-codegen-shared = { path = "./shared", version = "0.72.0" } cranelift-entity = { path = "../entity", version = "0.72.0" } cranelift-bforest = { path = "../bforest", version = "0.72.0" } hashbrown = { version = "0.9.1", optional = true } -target-lexicon = "0.11" +target-lexicon = "0.12" log = { version = "0.4.6", default-features = false } serde = { version = "1.0.94", features = ["derive"], optional = true } bincode = { version = "1.2.1", optional = true } diff --git a/cranelift/codegen/meta/src/shared/settings.rs b/cranelift/codegen/meta/src/shared/settings.rs index 2d3cfc6f38..2acc34118d 100644 --- a/cranelift/codegen/meta/src/shared/settings.rs +++ b/cranelift/codegen/meta/src/shared/settings.rs @@ -192,6 +192,7 @@ pub(crate) fn define() -> SettingGroup { "cold", "system_v", "windows_fastcall", + "apple_aarch64", "baldrdash_system_v", "baldrdash_windows", "baldrdash_2020", diff --git a/cranelift/codegen/src/isa/aarch64/abi.rs b/cranelift/codegen/src/isa/aarch64/abi.rs index 2c3776fbf7..8f3b2e6f1e 100644 --- a/cranelift/codegen/src/isa/aarch64/abi.rs +++ b/cranelift/codegen/src/isa/aarch64/abi.rs @@ -171,6 +171,21 @@ impl ABIMachineSpec for AArch64MachineDeps { let has_baldrdash_tls = call_conv == isa::CallConv::Baldrdash2020; // See AArch64 ABI (https://c9x.me/compile/bib/abi-arm64.pdf), sections 5.4. + // + // MacOS aarch64 is slightly different, see also + // https://developer.apple.com/documentation/xcode/writing_arm64_code_for_apple_platforms. + // We are diverging from the MacOS aarch64 implementation in the + // following ways: + // - sign- and zero- extensions of data types less than 32 bits are not + // implemented yet. + // - i128 arguments passing isn't implemented yet in the standard (non + // MacOS) aarch64 ABI. + // - we align the arguments stack space to a 16-bytes boundary, while + // the MacOS allows aligning only on 8 bytes. In practice it means we're + // slightly overallocating when calling, which is fine, and doesn't + // break our other invariants that the stack is always allocated in + // 16-bytes chunks. + let mut next_xreg = 0; let mut next_vreg = 0; let mut next_stack: u64 = 0; @@ -264,13 +279,24 @@ impl ABIMachineSpec for AArch64MachineDeps { *next_reg += 1; remaining_reg_vals -= 1; } else { - // Compute size. Every arg takes a minimum slot of 8 bytes. (16-byte - // stack alignment happens separately after all args.) + // Compute the stack slot's size. let size = (ty_bits(param.value_type) / 8) as u64; - let size = std::cmp::max(size, 8); - // Align. + + let size = if call_conv != isa::CallConv::AppleAarch64 { + // Every arg takes a minimum slot of 8 bytes. (16-byte stack + // alignment happens separately after all args.) + std::cmp::max(size, 8) + } else { + // MacOS aarch64 allows stack slots with sizes less than 8 + // bytes. They still need to be properly aligned on their + // natural data alignment, though. + size + }; + + // Align the stack slot. debug_assert!(size.is_power_of_two()); next_stack = align_to(next_stack, size); + ret.push(ABIArg::stack( next_stack as i64, param.value_type, diff --git a/cranelift/codegen/src/isa/call_conv.rs b/cranelift/codegen/src/isa/call_conv.rs index 61a94e5a43..e764f33c6e 100644 --- a/cranelift/codegen/src/isa/call_conv.rs +++ b/cranelift/codegen/src/isa/call_conv.rs @@ -10,22 +10,24 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub enum CallConv { - /// Best performance, not ABI-stable + /// Best performance, not ABI-stable. Fast, - /// Smallest caller code size, not ABI-stable + /// Smallest caller code size, not ABI-stable. Cold, - /// System V-style convention used on many platforms + /// System V-style convention used on many platforms. SystemV, - /// Windows "fastcall" convention, also used for x64 and ARM + /// Windows "fastcall" convention, also used for x64 and ARM. WindowsFastcall, - /// SpiderMonkey WebAssembly convention on systems using natively SystemV + /// Mac aarch64 calling convention, which is a tweak aarch64 ABI. + AppleAarch64, + /// SpiderMonkey WebAssembly convention on systems using natively SystemV. BaldrdashSystemV, - /// SpiderMonkey WebAssembly convention on Windows + /// SpiderMonkey WebAssembly convention on Windows. BaldrdashWindows, /// SpiderMonkey WebAssembly convention for "ABI-2020", with extra TLS /// register slots in the frame. Baldrdash2020, - /// Specialized convention for the probestack function + /// Specialized convention for the probestack function. Probestack, } @@ -36,6 +38,7 @@ impl CallConv { // Default to System V for unknown targets because most everything // uses System V. Ok(CallingConvention::SystemV) | Err(()) => Self::SystemV, + Ok(CallingConvention::AppleAarch64) => Self::AppleAarch64, Ok(CallingConvention::WindowsFastcall) => Self::WindowsFastcall, Ok(unimp) => unimplemented!("calling convention: {:?}", unimp), } @@ -49,6 +52,7 @@ impl CallConv { LibcallCallConv::Cold => Self::Cold, LibcallCallConv::SystemV => Self::SystemV, LibcallCallConv::WindowsFastcall => Self::WindowsFastcall, + LibcallCallConv::AppleAarch64 => Self::AppleAarch64, LibcallCallConv::BaldrdashSystemV => Self::BaldrdashSystemV, LibcallCallConv::BaldrdashWindows => Self::BaldrdashWindows, LibcallCallConv::Baldrdash2020 => Self::Baldrdash2020, @@ -80,6 +84,7 @@ impl fmt::Display for CallConv { Self::Cold => "cold", Self::SystemV => "system_v", Self::WindowsFastcall => "windows_fastcall", + Self::AppleAarch64 => "apple_aarch64", Self::BaldrdashSystemV => "baldrdash_system_v", Self::BaldrdashWindows => "baldrdash_windows", Self::Baldrdash2020 => "baldrdash_2020", @@ -96,6 +101,7 @@ impl str::FromStr for CallConv { "cold" => Ok(Self::Cold), "system_v" => Ok(Self::SystemV), "windows_fastcall" => Ok(Self::WindowsFastcall), + "apple_aarch64" => Ok(Self::AppleAarch64), "baldrdash_system_v" => Ok(Self::BaldrdashSystemV), "baldrdash_windows" => Ok(Self::BaldrdashWindows), "baldrdash_2020" => Ok(Self::Baldrdash2020), diff --git a/cranelift/codegen/src/isa/x64/abi.rs b/cranelift/codegen/src/isa/x64/abi.rs index 4ae639568d..f55478a1c8 100644 --- a/cranelift/codegen/src/isa/x64/abi.rs +++ b/cranelift/codegen/src/isa/x64/abi.rs @@ -907,6 +907,7 @@ fn get_intreg_for_retval( _ => None, }, CallConv::BaldrdashWindows | CallConv::Probestack => todo!(), + CallConv::AppleAarch64 => unreachable!(), } } @@ -933,6 +934,7 @@ fn get_fltreg_for_retval( _ => None, }, CallConv::BaldrdashWindows | CallConv::Probestack => todo!(), + CallConv::AppleAarch64 => unreachable!(), } } @@ -1001,6 +1003,7 @@ fn get_callee_saves(call_conv: &CallConv, regs: &Set>) -> Vec< .filter(|r| is_callee_save_fastcall(r.to_reg())) .collect(), CallConv::Probestack => todo!("probestack?"), + CallConv::AppleAarch64 => unreachable!(), }; // Sort registers for deterministic code output. We can do an unstable sort because the // registers will be unique (there are no dups). diff --git a/cranelift/codegen/src/isa/x86/abi.rs b/cranelift/codegen/src/isa/x86/abi.rs index 0117b8918b..c6df87ae22 100644 --- a/cranelift/codegen/src/isa/x86/abi.rs +++ b/cranelift/codegen/src/isa/x86/abi.rs @@ -512,6 +512,7 @@ pub fn prologue_epilogue(func: &mut ir::Function, isa: &dyn TargetIsa) -> Codege } CallConv::Probestack => unimplemented!("probestack calling convention"), CallConv::Baldrdash2020 => unimplemented!("Baldrdash ABI 2020"), + CallConv::AppleAarch64 => unreachable!(), } } diff --git a/cranelift/codegen/src/machinst/abi_impl.rs b/cranelift/codegen/src/machinst/abi_impl.rs index f240c9a238..c17406b334 100644 --- a/cranelift/codegen/src/machinst/abi_impl.rs +++ b/cranelift/codegen/src/machinst/abi_impl.rs @@ -646,7 +646,8 @@ impl ABICalleeImpl { || call_conv == isa::CallConv::Fast || call_conv == isa::CallConv::Cold || call_conv.extends_baldrdash() - || call_conv.extends_windows_fastcall(), + || call_conv.extends_windows_fastcall() + || call_conv == isa::CallConv::AppleAarch64, "Unsupported calling convention: {:?}", call_conv ); diff --git a/cranelift/filetests/Cargo.toml b/cranelift/filetests/Cargo.toml index 40d643a708..ccfae3ec1a 100644 --- a/cranelift/filetests/Cargo.toml +++ b/cranelift/filetests/Cargo.toml @@ -23,7 +23,7 @@ gimli = { version = "0.23.0", default-features = false, features = ["read"] } log = "0.4.6" memmap2 = "0.2.1" num_cpus = "1.8.0" -target-lexicon = "0.11" +target-lexicon = "0.12" thiserror = "1.0.15" anyhow = "1.0.32" diff --git a/cranelift/frontend/Cargo.toml b/cranelift/frontend/Cargo.toml index 0b70573955..68635eeff5 100644 --- a/cranelift/frontend/Cargo.toml +++ b/cranelift/frontend/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" [dependencies] cranelift-codegen = { path = "../codegen", version = "0.72.0", default-features = false } -target-lexicon = "0.11" +target-lexicon = "0.12" log = { version = "0.4.6", default-features = false } hashbrown = { version = "0.9.1", optional = true } smallvec = { version = "1.6.1" } diff --git a/cranelift/jit/Cargo.toml b/cranelift/jit/Cargo.toml index c55655aed5..e64da54bcf 100644 --- a/cranelift/jit/Cargo.toml +++ b/cranelift/jit/Cargo.toml @@ -18,7 +18,7 @@ anyhow = "1.0" region = "2.2.0" libc = { version = "0.2.42" } errno = "0.2.4" -target-lexicon = "0.11" +target-lexicon = "0.12" memmap2 = { version = "0.2.1", optional = true } log = { version = "0.4.6", default-features = false } diff --git a/cranelift/native/Cargo.toml b/cranelift/native/Cargo.toml index c1dcf7153f..42c458a03c 100644 --- a/cranelift/native/Cargo.toml +++ b/cranelift/native/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" [dependencies] cranelift-codegen = { path = "../codegen", version = "0.72.0", default-features = false } -target-lexicon = "0.11" +target-lexicon = "0.12" [features] default = ["std"] diff --git a/cranelift/object/Cargo.toml b/cranelift/object/Cargo.toml index d26840ad75..b6799e24c1 100644 --- a/cranelift/object/Cargo.toml +++ b/cranelift/object/Cargo.toml @@ -13,7 +13,7 @@ edition = "2018" cranelift-module = { path = "../module", version = "0.72.0" } cranelift-codegen = { path = "../codegen", version = "0.72.0", default-features = false, features = ["std"] } object = { version = "0.23.0", default-features = false, features = ["write"] } -target-lexicon = "0.11" +target-lexicon = "0.12" anyhow = "1.0" log = { version = "0.4.6", default-features = false } diff --git a/cranelift/reader/Cargo.toml b/cranelift/reader/Cargo.toml index 8316b592d2..c8d0ae99f9 100644 --- a/cranelift/reader/Cargo.toml +++ b/cranelift/reader/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" [dependencies] cranelift-codegen = { path = "../codegen", version = "0.72.0" } smallvec = "1.6.1" -target-lexicon = "0.11" +target-lexicon = "0.12" thiserror = "1.0.15" [badges] diff --git a/cranelift/wasm/Cargo.toml b/cranelift/wasm/Cargo.toml index 25ed63339f..87a1f8c15a 100644 --- a/cranelift/wasm/Cargo.toml +++ b/cranelift/wasm/Cargo.toml @@ -25,7 +25,7 @@ thiserror = "1.0.4" [dev-dependencies] wat = "1.0.36" -target-lexicon = "0.11" +target-lexicon = "0.12" # Enable the riscv feature for cranelift-codegen, as some tests require it cranelift-codegen = { path = "../codegen", version = "0.72.0", default-features = false, features = ["riscv"] } diff --git a/crates/debug/Cargo.toml b/crates/debug/Cargo.toml index 0e69efd8fb..68ec712970 100644 --- a/crates/debug/Cargo.toml +++ b/crates/debug/Cargo.toml @@ -16,7 +16,7 @@ gimli = "0.23.0" wasmparser = "0.76" object = { version = "0.23.0", default-features = false, features = ["read_core", "elf", "write"] } wasmtime-environ = { path = "../environ", version = "0.25.0" } -target-lexicon = { version = "0.11.0", default-features = false } +target-lexicon = { version = "0.12.0", default-features = false } anyhow = "1.0" thiserror = "1.0.4" more-asserts = "0.2.1" diff --git a/crates/jit/Cargo.toml b/crates/jit/Cargo.toml index 4ddb6508cd..e96466883f 100644 --- a/crates/jit/Cargo.toml +++ b/crates/jit/Cargo.toml @@ -27,7 +27,7 @@ wasmtime-obj = { path = "../obj", version = "0.25.0" } rayon = { version = "1.0", optional = true } region = "2.2.0" thiserror = "1.0.4" -target-lexicon = { version = "0.11.0", default-features = false } +target-lexicon = { version = "0.12.0", default-features = false } wasmparser = "0.76" more-asserts = "0.2.1" anyhow = "1.0" diff --git a/crates/obj/Cargo.toml b/crates/obj/Cargo.toml index 6748b1d8ec..f9dba6e11b 100644 --- a/crates/obj/Cargo.toml +++ b/crates/obj/Cargo.toml @@ -15,7 +15,7 @@ anyhow = "1.0" wasmtime-environ = { path = "../environ", version = "0.25.0" } object = { version = "0.23.0", default-features = false, features = ["write"] } more-asserts = "0.2.1" -target-lexicon = { version = "0.11.0", default-features = false } +target-lexicon = { version = "0.12.0", default-features = false } wasmtime-debug = { path = "../debug", version = "0.25.0" } [badges] diff --git a/crates/profiling/Cargo.toml b/crates/profiling/Cargo.toml index 712a6e4470..fc22b6f012 100644 --- a/crates/profiling/Cargo.toml +++ b/crates/profiling/Cargo.toml @@ -18,7 +18,7 @@ lazy_static = "1.4" libc = { version = "0.2.60", default-features = false } scroll = { version = "0.10.1", features = ["derive"], optional = true } serde = { version = "1.0.99", features = ["derive"] } -target-lexicon = "0.11.0" +target-lexicon = "0.12.0" wasmtime-environ = { path = "../environ", version = "0.25.0" } wasmtime-runtime = { path = "../runtime", version = "0.25.0" } ittapi-rs = { version = "0.1.5", optional = true } diff --git a/crates/test-programs/Cargo.toml b/crates/test-programs/Cargo.toml index 660abc0a47..74e16cbd9c 100644 --- a/crates/test-programs/Cargo.toml +++ b/crates/test-programs/Cargo.toml @@ -15,7 +15,7 @@ wasi-common = { path = "../wasi-common", version = "0.25.0" } wasi-cap-std-sync = { path = "../wasi-common/cap-std-sync", version = "0.25.0" } wasmtime = { path = "../wasmtime", version = "0.25.0" } wasmtime-wasi = { path = "../wasi", version = "0.25.0" } -target-lexicon = "0.11.0" +target-lexicon = "0.12.0" pretty_env_logger = "0.4.0" tempfile = "3.1.0" os_pipe = "0.9" diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml index c99f37001e..39feb1777a 100644 --- a/crates/wasmtime/Cargo.toml +++ b/crates/wasmtime/Cargo.toml @@ -19,7 +19,7 @@ wasmtime-jit = { path = "../jit", version = "0.25.0" } wasmtime-cache = { path = "../cache", version = "0.25.0", optional = true } wasmtime-profiling = { path = "../profiling", version = "0.25.0" } wasmtime-fiber = { path = "../fiber", version = "0.25.0", optional = true } -target-lexicon = { version = "0.11.0", default-features = false } +target-lexicon = { version = "0.12.0", default-features = false } wasmparser = "0.76" anyhow = "1.0.19" region = "2.2.0" diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 2b40128d25..4376f7f20d 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -13,7 +13,7 @@ cranelift-codegen = { path = "../cranelift/codegen" } cranelift-reader = { path = "../cranelift/reader" } cranelift-wasm = { path = "../cranelift/wasm" } libfuzzer-sys = "0.4.0" -target-lexicon = "0.11" +target-lexicon = "0.12" peepmatic-fuzzing = { path = "../cranelift/peepmatic/crates/fuzzing", optional = true } wasmtime = { path = "../crates/wasmtime" } wasmtime-fuzzing = { path = "../crates/fuzzing" } diff --git a/tests/all/func.rs b/tests/all/func.rs index 73166cc891..b334056893 100644 --- a/tests/all/func.rs +++ b/tests/all/func.rs @@ -121,9 +121,6 @@ fn signatures_match() { } #[test] -// Note: Cranelift only supports refrerence types (used in the wasm in this -// test) on x64. -#[cfg(target_arch = "x86_64")] fn import_works() -> Result<()> { static HITS: AtomicUsize = AtomicUsize::new(0); diff --git a/tests/all/host_funcs.rs b/tests/all/host_funcs.rs index de94701144..26d4329941 100644 --- a/tests/all/host_funcs.rs +++ b/tests/all/host_funcs.rs @@ -219,9 +219,6 @@ fn signatures_match() -> Result<()> { } #[test] -// Note: Cranelift only supports refrerence types (used in the wasm in this -// test) on x64. -#[cfg(target_arch = "x86_64")] fn import_works() -> Result<()> { static HITS: AtomicUsize = AtomicUsize::new(0); @@ -328,6 +325,141 @@ fn import_works() -> Result<()> { Ok(()) } +#[test] +fn call_import_many_args() -> Result<()> { + let wasm = wat::parse_str( + r#" + (import "" "host" (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32))) + (func (export "run") + i32.const 1 + i32.const 2 + i32.const 3 + i32.const 4 + i32.const 5 + i32.const 6 + i32.const 7 + i32.const 8 + i32.const 9 + i32.const 10 + call 0 + ) + "#, + )?; + + let mut config = Config::new(); + + config.wrap_host_func( + "", + "host", + |x1: i32, + x2: i32, + x3: i32, + x4: i32, + x5: i32, + x6: i32, + x7: i32, + x8: i32, + x9: i32, + x10: i32| { + assert_eq!(x1, 1); + assert_eq!(x2, 2); + assert_eq!(x3, 3); + assert_eq!(x4, 4); + assert_eq!(x5, 5); + assert_eq!(x6, 6); + assert_eq!(x7, 7); + assert_eq!(x8, 8); + assert_eq!(x9, 9); + assert_eq!(x10, 10); + }, + ); + + let engine = Engine::new(&config)?; + let module = Module::new(&engine, &wasm)?; + + let store = Store::new(&engine); + let instance = Instance::new( + &store, + &module, + &[store + .get_host_func("", "host") + .expect("should be defined") + .into()], + )?; + + let run = instance.get_func("run").unwrap(); + run.call(&[])?; + + Ok(()) +} + +#[test] +fn call_wasm_many_args() -> Result<()> { + let wasm = wat::parse_str( + r#" + (func (export "run") (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) + i32.const 1 + get_local 0 + i32.ne + if + unreachable + end + + i32.const 10 + get_local 9 + i32.ne + if + unreachable + end + ) + + (func (export "test") + i32.const 1 + i32.const 2 + i32.const 3 + i32.const 4 + i32.const 5 + i32.const 6 + i32.const 7 + i32.const 8 + i32.const 9 + i32.const 10 + call 0 + ) + "#, + )?; + + let config = Config::new(); + let engine = Engine::new(&config)?; + let module = Module::new(&engine, &wasm)?; + + let store = Store::new(&engine); + let instance = Instance::new(&store, &module, &[])?; + + let run = instance.get_func("run").unwrap(); + run.call(&[ + 1.into(), + 2.into(), + 3.into(), + 4.into(), + 5.into(), + 6.into(), + 7.into(), + 8.into(), + 9.into(), + 10.into(), + ])?; + + let typed_run = + instance.get_typed_func::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), ()>("run")?; + typed_run.call((1, 2, 3, 4, 5, 6, 7, 8, 9, 10))?; + + let test = instance.get_func("test").unwrap(); + test.call(&[])?; + + Ok(()) +} + #[test] fn trap_smoke() -> Result<()> { let mut config = Config::default();