diff --git a/ci/build-test-matrix.js b/ci/build-test-matrix.js index 3cf7e2687d8c..954be57728ee 100644 --- a/ci/build-test-matrix.js +++ b/ci/build-test-matrix.js @@ -36,7 +36,7 @@ function supports32Bit(pkg) { if (pkg.indexOf("pulley") !== -1) return true; - return pkg == 'wasmtime-fiber'; + return pkg == 'wasmtime-fiber' || pkg == 'wasmtime'; } // This is the full, unsharded, and unfiltered matrix of what we test on @@ -231,7 +231,9 @@ async function shard(configs) { for (const config of configs) { // Special case 32-bit configs. Only some crates, according to // `supports32Bit`, run on this target. At this time the set of supported - // crates is small enough that they're not sharded. + // crates is small enough that they're not sharded. A second shard, however, + // is included which runs `--test wast` to run the full `*.wast` test suite + // in CI on 32-bit platforms, at this time effectively testing Pulley. if (config["32-bit"] === true) { sharded.push(Object.assign( {}, @@ -242,6 +244,11 @@ async function shard(configs) { .join(" "), } )); + sharded.push(Object.assign( + {}, + config, + { bucket: '--test wast' }, + )); continue; } diff --git a/cranelift/codegen/src/isa/pulley_shared/abi.rs b/cranelift/codegen/src/isa/pulley_shared/abi.rs index b01c4672b57a..831dbe282865 100644 --- a/cranelift/codegen/src/isa/pulley_shared/abi.rs +++ b/cranelift/codegen/src/isa/pulley_shared/abi.rs @@ -1,7 +1,7 @@ //! Implementation of a standard Pulley ABI. use super::{inst::*, PulleyFlags, PulleyTargetKind}; -use crate::isa::pulley_shared::PulleyBackend; +use crate::isa::pulley_shared::{PointerWidth, PulleyBackend}; use crate::{ ir::{self, types::*, MemFlags, Signature}, isa::{self, unwind::UnwindInst}, @@ -533,7 +533,15 @@ where _isa_flags: &PulleyFlags, ) -> u32 { match rc { - RegClass::Int => 1, + // Spilling an integer register requires spilling 8 bytes, and spill + // slots are defined in terms of "word bytes" or the size of a + // pointer. That means on 32-bit pulley we need to take up two spill + // slots for integers where on 64-bit pulley we need to only take up + // one spill slot for integers. + RegClass::Int => match P::pointer_width() { + PointerWidth::PointerWidth32 => 2, + PointerWidth::PointerWidth64 => 1, + }, RegClass::Float => todo!(), RegClass::Vector => unreachable!(), } diff --git a/cranelift/jit/src/compiled_blob.rs b/cranelift/jit/src/compiled_blob.rs index 4eab207ff011..95c3d2495b79 100644 --- a/cranelift/jit/src/compiled_blob.rs +++ b/cranelift/jit/src/compiled_blob.rs @@ -102,7 +102,7 @@ impl CompiledBlob { let at_page = (at as usize) & !0xfff; let pcrel = (what_page as isize).checked_sub(at_page as isize).unwrap(); assert!( - (-1 << 32) <= pcrel && pcrel < (1 << 32), + (-1 << 32) <= (pcrel as i64) && (pcrel as i64) < (1 << 32), "can't reach GOT page with ±4GB `adrp` instruction" ); let val = pcrel >> 12; diff --git a/crates/wasi-nn/Cargo.toml b/crates/wasi-nn/Cargo.toml index f4b6c388eeaa..b05be0bcea88 100644 --- a/crates/wasi-nn/Cargo.toml +++ b/crates/wasi-nn/Cargo.toml @@ -30,9 +30,6 @@ wasmtime = { workspace = true, features = [ # These dependencies are necessary for the wasi-nn implementation: tracing = { workspace = true } thiserror = { workspace = true } -openvino = { version = "0.8.0", features = [ - "runtime-linking", -], optional = true } ort = { version = "2.0.0-rc.2", default-features = false, features = [ "copy-dylibs", @@ -40,6 +37,11 @@ ort = { version = "2.0.0-rc.2", default-features = false, features = [ ], optional = true } tch = { version = "0.17.0", default-features = false, optional = true} +[target.'cfg(target_pointer_width = "64")'.dependencies] +openvino = { version = "0.8.0", features = [ + "runtime-linking", +], optional = true } + [target.'cfg(windows)'.dependencies.windows] version = "0.52" features = [ diff --git a/crates/wasi-nn/src/backend/mod.rs b/crates/wasi-nn/src/backend/mod.rs index 20224be8f540..e657dfef5da7 100644 --- a/crates/wasi-nn/src/backend/mod.rs +++ b/crates/wasi-nn/src/backend/mod.rs @@ -4,7 +4,7 @@ #[cfg(feature = "onnx")] pub mod onnx; -#[cfg(feature = "openvino")] +#[cfg(all(feature = "openvino", target_pointer_width = "64"))] pub mod openvino; #[cfg(feature = "pytorch")] pub mod pytorch; @@ -13,7 +13,7 @@ pub mod winml; #[cfg(feature = "onnx")] use self::onnx::OnnxBackend; -#[cfg(feature = "openvino")] +#[cfg(all(feature = "openvino", target_pointer_width = "64"))] use self::openvino::OpenvinoBackend; #[cfg(feature = "pytorch")] use self::pytorch::PytorchBackend; @@ -31,7 +31,8 @@ use wiggle::GuestError; /// Return a list of all available backend frameworks. pub fn list() -> Vec { let mut backends = vec![]; - #[cfg(feature = "openvino")] + let _ = &mut backends; // silence warnings if none are enabled + #[cfg(all(feature = "openvino", target_pointer_width = "64"))] { backends.push(Backend::from(OpenvinoBackend::default())); } @@ -120,6 +121,7 @@ pub enum BackendError { } /// Read a file into a byte vector. +#[allow(dead_code, reason = "not used on all platforms")] fn read(path: &Path) -> anyhow::Result> { let mut file = File::open(path)?; let mut buffer = vec![]; diff --git a/crates/wasmtime/src/engine/serialization.rs b/crates/wasmtime/src/engine/serialization.rs index 94b3ad37607c..84a1b36bb628 100644 --- a/crates/wasmtime/src/engine/serialization.rs +++ b/crates/wasmtime/src/engine/serialization.rs @@ -641,6 +641,8 @@ mod test { } #[test] + #[cfg(target_arch = "x86_64")] // test on a platform that is known to use + // Cranelift fn test_os_mismatch() -> Result<()> { let engine = Engine::default(); let mut metadata = Metadata::new(&engine); @@ -712,6 +714,7 @@ Caused by: #[test] #[cfg_attr(miri, ignore)] + #[cfg(target_pointer_width = "64")] // different defaults on 32-bit platforms fn test_tunables_int_mismatch() -> Result<()> { let engine = Engine::default(); let mut metadata = Metadata::new(&engine); @@ -762,6 +765,8 @@ Caused by: } #[test] + #[cfg(target_arch = "x86_64")] // test on a platform that is known to + // implement threads fn test_feature_mismatch() -> Result<()> { let mut config = Config::new(); config.wasm_threads(true); diff --git a/crates/wasmtime/src/runtime/externals/table.rs b/crates/wasmtime/src/runtime/externals/table.rs index 24f611a4c005..7aff2a678cdf 100644 --- a/crates/wasmtime/src/runtime/externals/table.rs +++ b/crates/wasmtime/src/runtime/externals/table.rs @@ -441,6 +441,7 @@ impl Table { mod tests { use super::*; use crate::{Instance, Module, Store}; + use wasmtime_environ::TripleExt; #[test] fn hash_key_is_stable_across_duplicate_store_data_entries() -> Result<()> { @@ -452,7 +453,20 @@ mod tests { (table (export "t") 1 1 externref) ) "#, - )?; + ); + // Expect this test to fail on pulley at this time. When pulley supports + // externref this should switch back to using `?` on the constructor + // above for all platforms. + let module = match module { + Ok(module) => { + assert!(!store.engine().target().is_pulley()); + module + } + Err(e) => { + assert!(store.engine().target().is_pulley(), "bad error {e:?}"); + return Ok(()); + } + }; let instance = Instance::new(&mut store, &module, &[])?; // Each time we `get_table`, we call `Table::from_wasmtime` which adds diff --git a/crates/wasmtime/src/runtime/module/registry.rs b/crates/wasmtime/src/runtime/module/registry.rs index 84d0822c31d7..c14ff1d9bcc2 100644 --- a/crates/wasmtime/src/runtime/module/registry.rs +++ b/crates/wasmtime/src/runtime/module/registry.rs @@ -299,6 +299,8 @@ pub fn unregister_code(code: &Arc) { #[cfg_attr(miri, ignore)] fn test_frame_info() -> Result<(), anyhow::Error> { use crate::*; + use wasmtime_environ::TripleExt; + let mut store = Store::<()>::default(); let module = Module::new( store.engine(), @@ -313,7 +315,20 @@ fn test_frame_info() -> Result<(), anyhow::Error> { (func (export "rem_u") (param $x i32) (param $y i32) (result i32) (i32.rem_u (local.get $x) (local.get $y))) ) "#, - )?; + ); + // Expect this test to fail on pulley at this time. When pulley supports + // the instructions above this should switch back to using `?` on the + // constructor above for all platforms. + let module = match module { + Ok(module) => { + assert!(!store.engine().target().is_pulley()); + module + } + Err(e) => { + assert!(store.engine().target().is_pulley(), "bad error {e:?}"); + return Ok(()); + } + }; // Create an instance to ensure the frame information is registered. Instance::new(&mut store, &module, &[])?; diff --git a/crates/wasmtime/src/runtime/values.rs b/crates/wasmtime/src/runtime/values.rs index ecfdc44a704d..4c4284abe946 100644 --- a/crates/wasmtime/src/runtime/values.rs +++ b/crates/wasmtime/src/runtime/values.rs @@ -1021,26 +1021,38 @@ mod tests { fn size_of_val() { // Try to keep tabs on the size of `Val` and make sure we don't grow its // size. - assert_eq!( - std::mem::size_of::(), - if cfg!(any( - target_arch = "x86_64", - target_arch = "aarch64", - target_arch = "riscv64", - target_arch = "s390x" - )) { - 24 - } else { - panic!("unsupported architecture") - } - ); + let expected = if cfg!(target_arch = "x86_64") + || cfg!(target_arch = "aarch64") + || cfg!(target_arch = "s390x") + || cfg!(target_arch = "riscv64") + || cfg!(target_arch = "arm") + { + 24 + } else if cfg!(target_arch = "x86") { + 20 + } else { + panic!("unsupported architecture") + }; + assert_eq!(std::mem::size_of::(), expected); } #[test] fn size_of_ref() { // Try to keep tabs on the size of `Ref` and make sure we don't grow its // size. - assert_eq!(std::mem::size_of::(), 24); + let expected = if cfg!(target_arch = "x86_64") + || cfg!(target_arch = "aarch64") + || cfg!(target_arch = "s390x") + || cfg!(target_arch = "riscv64") + || cfg!(target_arch = "arm") + { + 24 + } else if cfg!(target_arch = "x86") { + 20 + } else { + panic!("unsupported architecture") + }; + assert_eq!(std::mem::size_of::(), expected); } #[test] diff --git a/crates/wasmtime/src/runtime/vm/arch/x86_64.rs b/crates/wasmtime/src/runtime/vm/arch/arm.rs similarity index 78% rename from crates/wasmtime/src/runtime/vm/arch/x86_64.rs rename to crates/wasmtime/src/runtime/vm/arch/arm.rs index f8091400bfe9..2d6a90edc3ad 100644 --- a/crates/wasmtime/src/runtime/vm/arch/x86_64.rs +++ b/crates/wasmtime/src/runtime/vm/arch/arm.rs @@ -1,4 +1,4 @@ -//! x86_64-specific definitions of architecture-specific functions in Wasmtime. +//! arm-specific definitions of architecture-specific functions in Wasmtime. #[inline] #[allow(missing_docs)] @@ -6,7 +6,7 @@ pub fn get_stack_pointer() -> usize { let stack_pointer: usize; unsafe { core::arch::asm!( - "mov {}, rsp", + "mov {}, sp", out(reg) stack_pointer, options(nostack,nomem), ); @@ -24,5 +24,5 @@ pub unsafe fn get_next_older_pc_from_fp(fp: usize) -> usize { pub const NEXT_OLDER_FP_FROM_FP_OFFSET: usize = 0; pub fn assert_fp_is_aligned(fp: usize) { - assert_eq!(fp % 16, 0, "stack should always be aligned to 16"); + assert_eq!(fp % 8, 0, "stack should always be aligned to 8"); } diff --git a/crates/wasmtime/src/runtime/vm/arch/mod.rs b/crates/wasmtime/src/runtime/vm/arch/mod.rs index adb346ceffe3..a8d481f45121 100644 --- a/crates/wasmtime/src/runtime/vm/arch/mod.rs +++ b/crates/wasmtime/src/runtime/vm/arch/mod.rs @@ -8,9 +8,9 @@ //! crate. cfg_if::cfg_if! { - if #[cfg(target_arch = "x86_64")] { - mod x86_64; - use x86_64 as imp; + if #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] { + mod x86; + use x86 as imp; } else if #[cfg(target_arch = "aarch64")] { mod aarch64; use aarch64 as imp; @@ -20,6 +20,9 @@ cfg_if::cfg_if! { } else if #[cfg(target_arch = "riscv64")] { mod riscv64; use riscv64 as imp; + } else if #[cfg(target_arch = "arm")] { + mod arm; + use arm as imp; } else { mod unsupported; use unsupported as imp; diff --git a/crates/wasmtime/src/runtime/vm/arch/unsupported.rs b/crates/wasmtime/src/runtime/vm/arch/unsupported.rs index 7f7759fa4a77..19aca0a3761f 100644 --- a/crates/wasmtime/src/runtime/vm/arch/unsupported.rs +++ b/crates/wasmtime/src/runtime/vm/arch/unsupported.rs @@ -1,15 +1,7 @@ compile_error!("Wasmtime's runtime is being compiled for an architecture that it does not support"); cfg_if::cfg_if! { - if #[cfg(target_arch = "x86")] { - compile_error!("\ -the tracking issue for i686 support is https://github.com/bytecodealliance/wasmtime/issues/1980 \ -"); - } else if #[cfg(target_arch = "arm")] { - compile_error!("\ -the tracking issue for arm support is https://github.com/bytecodealliance/wasmtime/issues/1173 \ -"); - } else if #[cfg(target_arch = "riscv32")] { + if #[cfg(target_arch = "riscv32")] { compile_error!("\ the tracking issue for riscv32 support is https://github.com/bytecodealliance/wasmtime/issues/8768 \ "); diff --git a/crates/wasmtime/src/runtime/vm/arch/x86.rs b/crates/wasmtime/src/runtime/vm/arch/x86.rs new file mode 100644 index 000000000000..fff57a539e40 --- /dev/null +++ b/crates/wasmtime/src/runtime/vm/arch/x86.rs @@ -0,0 +1,39 @@ +//! x86-specific (also x86-64) definitions of architecture-specific functions in +//! Wasmtime. + +#[inline] +#[allow(missing_docs)] +pub fn get_stack_pointer() -> usize { + let stack_pointer: usize; + unsafe { + #[cfg(target_pointer_width = "64")] + core::arch::asm!( + "mov {}, rsp", + out(reg) stack_pointer, + options(nostack,nomem), + ); + #[cfg(target_pointer_width = "32")] + core::arch::asm!( + "mov {}, esp", + out(reg) stack_pointer, + options(nostack,nomem), + ); + } + stack_pointer +} + +pub unsafe fn get_next_older_pc_from_fp(fp: usize) -> usize { + // The calling convention always pushes the return pointer (aka the PC of + // the next older frame) just before this frame. + *(fp as *mut usize).offset(1) +} + +// And the current frame pointer points to the next older frame pointer. +pub const NEXT_OLDER_FP_FROM_FP_OFFSET: usize = 0; + +/// Frame pointers are aligned if they're aligned to twice the size of a +/// pointer. +pub fn assert_fp_is_aligned(fp: usize) { + let align = 2 * size_of::(); + assert_eq!(fp % align, 0, "stack should always be aligned to {align}"); +} diff --git a/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs b/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs index 9ac172a52bf9..29c02e79e59f 100644 --- a/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs +++ b/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs @@ -985,6 +985,7 @@ impl DerefMut for DebugOnly { #[cfg(test)] mod tests { use super::*; + use wasmtime_environ::HostPtr; #[test] fn vm_drc_header_size_align() { @@ -1019,7 +1020,7 @@ mod tests { let actual_offset = (ref_count_ptr as usize) - (extern_data_ptr as usize); let offsets = wasmtime_environ::VMOffsets::from(wasmtime_environ::VMOffsetsFields { - ptr: 8, + ptr: HostPtr, num_imported_functions: 0, num_imported_tables: 0, num_imported_memories: 0, @@ -1047,7 +1048,7 @@ mod tests { let actual_offset = (next_ptr as usize) - (table_ptr as usize); let offsets = wasmtime_environ::VMOffsets::from(wasmtime_environ::VMOffsetsFields { - ptr: 8, + ptr: HostPtr, num_imported_functions: 0, num_imported_tables: 0, num_imported_memories: 0, @@ -1074,7 +1075,7 @@ mod tests { let actual_offset = (end_ptr as usize) - (table_ptr as usize); let offsets = wasmtime_environ::VMOffsets::from(wasmtime_environ::VMOffsetsFields { - ptr: 8, + ptr: HostPtr, num_imported_functions: 0, num_imported_tables: 0, num_imported_memories: 0, diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs index 75e41b562399..f16ed6f7f516 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs @@ -699,6 +699,7 @@ unsafe impl InstanceAllocatorImpl for PoolingInstanceAllocator { } #[cfg(test)] +#[cfg(target_pointer_width = "64")] mod test { use super::*; diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/memory_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/memory_pool.rs index 581d92526583..fb8025d9f85f 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/memory_pool.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/memory_pool.rs @@ -887,8 +887,23 @@ mod tests { guard_bytes, guard_before_slots, }; - let layout = calculate(&constraints); - assert_slab_layout_invariants(constraints, layout.unwrap()); + match calculate(&constraints) { + Ok(layout) => { + assert_slab_layout_invariants(constraints, layout) + } + Err(e) => { + // Only allow failure on 32-bit + // platforms where the calculation + // exceeded the size of the addres + // space + assert!( + cfg!(target_pointer_width = "32") + && e.to_string() + .contains("exceeds addressable memory"), + "bad error: {e:?}" + ); + } + } } } } diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs index 7510d56b17bb..1c26e59b15ac 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs @@ -220,7 +220,6 @@ mod tests { use super::*; use crate::runtime::vm::InstanceLimits; - #[cfg(target_pointer_width = "64")] #[test] fn test_table_pool() -> Result<()> { let pool = TablePool::new(&PoolingInstanceAllocatorConfig { diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/unix_stack_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/unix_stack_pool.rs index c4ef3fd91bd1..ef15b03b28ae 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/unix_stack_pool.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/unix_stack_pool.rs @@ -239,12 +239,11 @@ impl StackPool { } } -#[cfg(test)] +#[cfg(all(test, unix, feature = "async", not(miri)))] mod tests { use super::*; use crate::runtime::vm::InstanceLimits; - #[cfg(all(unix, target_pointer_width = "64", feature = "async", not(miri)))] #[test] fn test_stack_pool() -> Result<()> { let config = PoolingInstanceAllocatorConfig { diff --git a/crates/wasmtime/src/runtime/vm/memory.rs b/crates/wasmtime/src/runtime/vm/memory.rs index 8d3b488ecf37..221eefd2b08f 100644 --- a/crates/wasmtime/src/runtime/vm/memory.rs +++ b/crates/wasmtime/src/runtime/vm/memory.rs @@ -257,11 +257,19 @@ impl Memory { let absolute_max = 0usize.wrapping_sub(page_size); // Sanity-check what should already be true from wasm module validation. + // Note that for 32-bit targets the absolute maximum is `1<<32` during + // compilation, not one-page-less-than-u32::MAX, so need to handle that + // specially here. + let absolute_max64 = if cfg!(target_pointer_width = "32") { + 1 << 32 + } else { + u64::try_from(absolute_max).unwrap() + }; if let Ok(size) = ty.minimum_byte_size() { - assert!(size <= u64::try_from(absolute_max).unwrap()); + assert!(size <= absolute_max64); } if let Ok(max) = ty.maximum_byte_size() { - assert!(max <= u64::try_from(absolute_max).unwrap()); + assert!(max <= absolute_max64); } // If the minimum memory size overflows the size of our own address diff --git a/crates/wasmtime/src/runtime/vm/sys/unix/signals.rs b/crates/wasmtime/src/runtime/vm/sys/unix/signals.rs index e02570a04592..a4a50003aaa5 100644 --- a/crates/wasmtime/src/runtime/vm/sys/unix/signals.rs +++ b/crates/wasmtime/src/runtime/vm/sys/unix/signals.rs @@ -271,6 +271,12 @@ unsafe fn get_trap_registers(cx: *mut libc::c_void, _signum: libc::c_int) -> Tra pc: cx.uc_mcontext.gregs[libc::REG_RIP as usize] as usize, fp: cx.uc_mcontext.gregs[libc::REG_RBP as usize] as usize, } + } else if #[cfg(all(target_os = "linux", target_arch = "x86"))] { + let cx = &*(cx as *const libc::ucontext_t); + TrapRegisters { + pc: cx.uc_mcontext.gregs[libc::REG_EIP as usize] as usize, + fp: cx.uc_mcontext.gregs[libc::REG_EBP as usize] as usize, + } } else if #[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "aarch64"))] { let cx = &*(cx as *const libc::ucontext_t); TrapRegisters { @@ -333,6 +339,12 @@ unsafe fn get_trap_registers(cx: *mut libc::c_void, _signum: libc::c_int) -> Tra pc: cx.sc_rip as usize, fp: cx.sc_rbp as usize, } + } else if #[cfg(all(target_os = "linux", target_arch = "arm"))] { + let cx = &*(cx as *const libc::ucontext_t); + TrapRegisters { + pc: cx.uc_mcontext.arm_pc as usize, + fp: cx.uc_mcontext.arm_fp as usize, + } } else { compile_error!("unsupported platform"); panic!(); diff --git a/crates/wasmtime/src/runtime/vm/sys/unix/unwind.rs b/crates/wasmtime/src/runtime/vm/sys/unix/unwind.rs index cf7a1d65203e..8745e19ab6c9 100644 --- a/crates/wasmtime/src/runtime/vm/sys/unix/unwind.rs +++ b/crates/wasmtime/src/runtime/vm/sys/unix/unwind.rs @@ -9,12 +9,29 @@ pub struct UnwindRegistration { registrations: Vec>, } -extern "C" { - // libunwind import - fn __register_frame(fde: *const u8); - fn __deregister_frame(fde: *const u8); - #[wasmtime_versioned_export_macros::versioned_link] - fn wasmtime_using_libunwind() -> bool; +cfg_if::cfg_if! { + // FIXME: at least on the `gcc-arm-linux-gnueabihf` toolchain on Ubuntu + // these symbols are not provided by default like they are on other targets. + // I'm not ARM expert so I don't know why. For now though consider this an + // optional integration feature with the platform and stub out the functions + // to do nothing which won't break any tests it just means that + // runtime-generated backtraces won't have the same level of fidelity they + // do on other targets. + if #[cfg(target_arch = "arm")] { + unsafe extern "C" fn __register_frame(_: *const u8) {} + unsafe extern "C" fn __deregister_frame(_: *const u8) {} + unsafe extern "C" fn wasmtime_using_libunwind() -> bool { + false + } + } else { + extern "C" { + // libunwind import + fn __register_frame(fde: *const u8); + fn __deregister_frame(fde: *const u8); + #[wasmtime_versioned_export_macros::versioned_link] + fn wasmtime_using_libunwind() -> bool; + } + } } /// There are two primary unwinders on Unix platforms: libunwind and libgcc. diff --git a/crates/wast-util/src/lib.rs b/crates/wast-util/src/lib.rs index cc82f83e4a24..ce62eaa9eeee 100644 --- a/crates/wast-util/src/lib.rs +++ b/crates/wast-util/src/lib.rs @@ -229,6 +229,7 @@ impl TestConfig { } /// Configuration that spec tests can run under. +#[derive(Debug)] pub struct WastConfig { /// Compiler chosen to run this test. pub compiler: Compiler, @@ -434,6 +435,20 @@ impl WastTest { return false; } + // FIXME: once the backend has enough instruction support move these + // into the above tests since they should pass on 64-bit platforms + // as well. + let supported32bit = [ + "misc_testsuite/winch/table_grow.wast", + "misc_testsuite/table_grow_with_funcref.wast", + // ... + ]; + if cfg!(target_pointer_width = "32") { + if supported32bit.iter().any(|part| self.path.ends_with(part)) { + return false; + } + } + return true; } diff --git a/tests/all/instance.rs b/tests/all/instance.rs index 57aab2ce563b..d969afb526c9 100644 --- a/tests/all/instance.rs +++ b/tests/all/instance.rs @@ -34,6 +34,7 @@ fn initializes_linear_memory() -> Result<()> { #[test] #[cfg_attr(miri, ignore)] +#[cfg(target_pointer_width = "64")] fn linear_memory_limits() -> Result<()> { // this test will allocate 4GB of virtual memory space, and may not work in // situations like CI QEMU emulation where it triggers SIGKILL. diff --git a/tests/rlimited-memory.rs b/tests/rlimited-memory.rs index c0fac24c0a37..06bfa5eea4b1 100644 --- a/tests/rlimited-memory.rs +++ b/tests/rlimited-memory.rs @@ -71,7 +71,7 @@ fn custom_limiter_detect_os_oom_failure() -> Result<()> { // limit process to 256MiB memory let rlimit = libc::rlimit { rlim_cur: 0, - rlim_max: process_max_memory as u64, + rlim_max: process_max_memory as libc::rlim_t, }; let res = libc::setrlimit(libc::RLIMIT_DATA, &rlimit); assert_eq!(res, 0, "setrlimit failed: {res}"); diff --git a/tests/wast.rs b/tests/wast.rs index 68abc4923726..fc062c39fc45 100644 --- a/tests/wast.rs +++ b/tests/wast.rs @@ -139,7 +139,11 @@ fn run_wast(test: &WastTest, config: WastConfig) -> anyhow::Result<()> { // Locally testing this out this drops QEMU's memory usage running this // tests suite from 10GiB to 600MiB. Previously we saw that crossing the // 10GiB threshold caused our processes to get OOM killed on CI. - if std::env::var("WASMTIME_TEST_NO_HOG_MEMORY").is_ok() { + // + // Note that this branch is also taken for 32-bit platforms which generally + // can't test much of the pooling allocator as the virtual address space is + // so limited. + if cfg!(target_pointer_width = "32") || std::env::var("WASMTIME_TEST_NO_HOG_MEMORY").is_ok() { // The pooling allocator hogs ~6TB of virtual address space for each // store, so if we don't to hog memory then ignore pooling tests. if config.pooling {