From 90e31cd13e90f668109fbc42a3b444a7048b95fd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Dec 2024 08:39:06 -0700 Subject: [PATCH 01/21] Update QEMU used in CI (#9713) * Update QEMU used in CI I'm getting segfaults on s390x in #9702 and I can't reproduce them locally in QEMU. Try updating QEMU to see if it's a transient bug. Historical updates haven't always gone well, so let's see what CI says. prtest:full * Update risc-v qemu arguments --- .github/workflows/main.yml | 2 +- ci/build-test-matrix.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b2b8da35e90d..0705df14dc4a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -659,7 +659,7 @@ jobs: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} env: - QEMU_BUILD_VERSION: 8.1.5 + QEMU_BUILD_VERSION: 9.1.2 strategy: fail-fast: ${{ github.event_name != 'pull_request' }} matrix: ${{ fromJson(needs.determine.outputs.test-matrix) }} diff --git a/ci/build-test-matrix.js b/ci/build-test-matrix.js index b1c0b73c7fd7..09e5965b5886 100644 --- a/ci/build-test-matrix.js +++ b/ci/build-test-matrix.js @@ -125,7 +125,7 @@ const FULL_MATRIX = [ "target": "riscv64gc-unknown-linux-gnu", "gcc_package": "gcc-riscv64-linux-gnu", "gcc": "riscv64-linux-gnu-gcc", - "qemu": "qemu-riscv64 -cpu rv64,v=true,vlen=256,vext_spec=v1.0,Zfa=true,Zfh=true,zba=true,zbb=true,zbc=true,zbs=true,zbkb=true,zcb=true,x-zicond=true -L /usr/riscv64-linux-gnu", + "qemu": "qemu-riscv64 -cpu rv64,v=true,vlen=256,vext_spec=v1.0,zfa=true,zfh=true,zba=true,zbb=true,zbc=true,zbs=true,zbkb=true,zcb=true,zicond=true -L /usr/riscv64-linux-gnu", "qemu_target": "riscv64-linux-user", "name": "Test Linux riscv64", "filter": "linux-riscv64", From c737a484c3c4c0804635d3538d9cf76bbbebe4f1 Mon Sep 17 00:00:00 2001 From: Rain Date: Tue, 3 Dec 2024 07:47:12 -0800 Subject: [PATCH 02/21] Put MemoryPool and MmapMemory mmaps behind Arc (#9682) In upcoming work we're going to centralize memory management inside `Mmap`. In order to do that, we need memory that logically borrows from the `Mmap` to have access to it. That turns out to be possible in some situations but very difficult in others (see #9681 for an attempt that was a real hassle to get working). To prepare for this work, start moving these uses to be behind `Arc`. These aren't cloned at the moment, but they will be in the future. --- crates/wasmtime/src/runtime/vm/cow.rs | 149 +++++++++++++----- .../instance/allocator/pooling/memory_pool.rs | 6 +- crates/wasmtime/src/runtime/vm/memory/mmap.rs | 38 +++-- crates/wasmtime/src/runtime/vm/mmap.rs | 32 ++-- .../src/runtime/vm/sys/custom/mmap.rs | 4 +- .../wasmtime/src/runtime/vm/sys/miri/mmap.rs | 11 +- .../wasmtime/src/runtime/vm/sys/unix/mmap.rs | 4 +- .../src/runtime/vm/sys/windows/mmap.rs | 4 +- 8 files changed, 168 insertions(+), 80 deletions(-) diff --git a/crates/wasmtime/src/runtime/vm/cow.rs b/crates/wasmtime/src/runtime/vm/cow.rs index cad29faf7d77..d2ff38aa8134 100644 --- a/crates/wasmtime/src/runtime/vm/cow.rs +++ b/crates/wasmtime/src/runtime/vm/cow.rs @@ -817,9 +817,33 @@ mod test { } } - fn mmap_4mib_inaccessible() -> Mmap { + fn mmap_4mib_inaccessible() -> Arc> { let four_mib = HostAlignedByteCount::new(4 << 20).expect("4 MiB is page aligned"); - Mmap::accessible_reserved(HostAlignedByteCount::ZERO, four_mib).unwrap() + Arc::new(Mmap::accessible_reserved(HostAlignedByteCount::ZERO, four_mib).unwrap()) + } + + /// Presents a part of an mmap as a mutable slice within a callback. + /// + /// The callback ensures that the reference no longer lives after the + /// function is done. + /// + /// # Safety + /// + /// The caller must ensure that during this function call, the only way this + /// region of memory is not accessed by (read from or written to) is via the + /// reference. Making the callback `'static` goes some way towards ensuring + /// that, but it's still possible to squirrel away a reference into global + /// state. So don't do that. + unsafe fn with_slice_mut( + mmap: &Arc>, + range: Range, + f: impl FnOnce(&mut [u8]) + 'static, + ) { + let ptr = mmap.as_ptr().cast_mut(); + let slice = unsafe { + core::slice::from_raw_parts_mut(ptr.add(range.start), range.end - range.start) + }; + f(slice); } #[test] @@ -830,7 +854,7 @@ mod test { ..Tunables::default_miri() }; // 4 MiB mmap'd area, not accessible - let mut mmap = mmap_4mib_inaccessible(); + let mmap = mmap_4mib_inaccessible(); // Create a MemoryImageSlot on top of it let mut memfd = MemoryImageSlot::create( mmap.as_mut_ptr() as *mut _, @@ -842,13 +866,18 @@ mod test { // instantiate with 64 KiB initial size memfd.instantiate(64 << 10, None, &ty, &tunables).unwrap(); assert!(memfd.is_dirty()); + // We should be able to access this 64 KiB (try both ends) and // it should consist of zeroes. - let slice = unsafe { mmap.slice_mut(0..65536) }; - assert_eq!(0, slice[0]); - assert_eq!(0, slice[65535]); - slice[1024] = 42; - assert_eq!(42, slice[1024]); + unsafe { + with_slice_mut(&mmap, 0..65536, |slice| { + assert_eq!(0, slice[0]); + assert_eq!(0, slice[65535]); + slice[1024] = 42; + assert_eq!(42, slice[1024]); + }); + } + // grow the heap memfd.set_heap_limit(128 << 10).unwrap(); let slice = unsafe { mmap.slice(0..1 << 20) }; @@ -876,7 +905,7 @@ mod test { ..Tunables::default_miri() }; // 4 MiB mmap'd area, not accessible - let mut mmap = mmap_4mib_inaccessible(); + let mmap = mmap_4mib_inaccessible(); // Create a MemoryImageSlot on top of it let mut memfd = MemoryImageSlot::create( mmap.as_mut_ptr() as *mut _, @@ -891,9 +920,14 @@ mod test { .instantiate(64 << 10, Some(&image), &ty, &tunables) .unwrap(); assert!(memfd.has_image()); - let slice = unsafe { mmap.slice_mut(0..65536) }; - assert_eq!(&[1, 2, 3, 4], &slice[page_size..][..4]); - slice[page_size] = 5; + + unsafe { + with_slice_mut(&mmap, 0..65536, move |slice| { + assert_eq!(&[1, 2, 3, 4], &slice[page_size..][..4]); + slice[page_size] = 5; + }); + } + // Clear and re-instantiate same image memfd .clear_and_remain_ready(HostAlignedByteCount::ZERO, |ptr, len| unsafe { @@ -903,9 +937,9 @@ mod test { memfd .instantiate(64 << 10, Some(&image), &ty, &tunables) .unwrap(); - let slice = unsafe { mmap.slice_mut(0..65536) }; - // Should not see mutation from above + let slice = unsafe { mmap.slice(0..65536) }; assert_eq!(&[1, 2, 3, 4], &slice[page_size..][..4]); + // Clear and re-instantiate no image memfd .clear_and_remain_ready(HostAlignedByteCount::ZERO, |ptr, len| unsafe { @@ -914,8 +948,9 @@ mod test { .unwrap(); memfd.instantiate(64 << 10, None, &ty, &tunables).unwrap(); assert!(!memfd.has_image()); - let slice = unsafe { mmap.slice_mut(0..65536) }; + let slice = unsafe { mmap.slice(0..65536) }; assert_eq!(&[0, 0, 0, 0], &slice[page_size..][..4]); + // Clear and re-instantiate image again memfd .clear_and_remain_ready(HostAlignedByteCount::ZERO, |ptr, len| unsafe { @@ -925,8 +960,9 @@ mod test { memfd .instantiate(64 << 10, Some(&image), &ty, &tunables) .unwrap(); - let slice = unsafe { mmap.slice_mut(0..65536) }; + let slice = unsafe { mmap.slice(0..65536) }; assert_eq!(&[1, 2, 3, 4], &slice[page_size..][..4]); + // Create another image with different data. let image2 = Arc::new(create_memfd_with_data(page_size, &[10, 11, 12, 13]).unwrap()); memfd @@ -937,8 +973,9 @@ mod test { memfd .instantiate(128 << 10, Some(&image2), &ty, &tunables) .unwrap(); - let slice = unsafe { mmap.slice_mut(0..65536) }; + let slice = unsafe { mmap.slice(0..65536) }; assert_eq!(&[10, 11, 12, 13], &slice[page_size..][..4]); + // Instantiate the original image again; we should notice it's // a different image and not reuse the mappings. memfd @@ -949,7 +986,7 @@ mod test { memfd .instantiate(64 << 10, Some(&image), &ty, &tunables) .unwrap(); - let slice = unsafe { mmap.slice_mut(0..65536) }; + let slice = unsafe { mmap.slice(0..65536) }; assert_eq!(&[1, 2, 3, 4], &slice[page_size..][..4]); } @@ -962,7 +999,7 @@ mod test { memory_reservation: 100 << 16, ..Tunables::default_miri() }; - let mut mmap = mmap_4mib_inaccessible(); + let mmap = mmap_4mib_inaccessible(); let mut memfd = MemoryImageSlot::create( mmap.as_mut_ptr() as *mut _, HostAlignedByteCount::ZERO, @@ -979,14 +1016,19 @@ mod test { .instantiate(64 << 10, Some(&image), &ty, &tunables) .unwrap(); assert!(memfd.has_image()); - let slice = unsafe { mmap.slice_mut(0..64 << 10) }; - if image_off > 0 { - assert_eq!(slice[image_off - 1], 0); - } - assert_eq!(slice[image_off + 5], 0); - assert_eq!(&[1, 2, 3, 4], &slice[image_off..][..4]); - slice[image_off] = 5; - assert_eq!(&[5, 2, 3, 4], &slice[image_off..][..4]); + + unsafe { + with_slice_mut(&mmap, 0..64 << 10, move |slice| { + if image_off > 0 { + assert_eq!(slice[image_off - 1], 0); + } + assert_eq!(slice[image_off + 5], 0); + assert_eq!(&[1, 2, 3, 4], &slice[image_off..][..4]); + slice[image_off] = 5; + assert_eq!(&[5, 2, 3, 4], &slice[image_off..][..4]); + }) + }; + memfd .clear_and_remain_ready(amt_to_memset, |ptr, len| unsafe { decommit_pages(ptr, len).unwrap() @@ -999,10 +1041,14 @@ mod test { for amt_to_memset in [0, page_size, page_size * 10, 1 << 20, 10 << 20] { let amt_to_memset = HostAlignedByteCount::new(amt_to_memset).unwrap(); memfd.instantiate(64 << 10, None, &ty, &tunables).unwrap(); - let mem = unsafe { mmap.slice_mut(0..64 << 10) }; - for chunk in mem.chunks_mut(1024) { - assert_eq!(chunk[0], 0); - chunk[0] = 5; + + unsafe { + with_slice_mut(&mmap, 0..64 << 10, |slice| { + for chunk in slice.chunks_mut(1024) { + assert_eq!(chunk[0], 0); + chunk[0] = 5; + } + }); } memfd .clear_and_remain_ready(amt_to_memset, |ptr, len| unsafe { @@ -1023,7 +1069,7 @@ mod test { ..Tunables::default_miri() }; - let mut mmap = mmap_4mib_inaccessible(); + let mmap = mmap_4mib_inaccessible(); let mut memfd = MemoryImageSlot::create( mmap.as_mut_ptr() as *mut _, HostAlignedByteCount::ZERO, @@ -1039,15 +1085,21 @@ mod test { .instantiate(initial, Some(&image), &ty, &tunables) .unwrap(); assert!(memfd.has_image()); - let slice = unsafe { mmap.slice_mut(0..(64 << 10) + page_size) }; - assert_eq!(&[1, 2, 3, 4], &slice[page_size..][..4]); - slice[page_size] = 5; - assert_eq!(&[5, 2, 3, 4], &slice[page_size..][..4]); + + unsafe { + with_slice_mut(&mmap, 0..(64 << 10) + page_size, move |slice| { + assert_eq!(&[1, 2, 3, 4], &slice[page_size..][..4]); + slice[page_size] = 5; + assert_eq!(&[5, 2, 3, 4], &slice[page_size..][..4]); + }); + } + memfd .clear_and_remain_ready(HostAlignedByteCount::ZERO, |ptr, len| unsafe { decommit_pages(ptr, len).unwrap() }) .unwrap(); + let slice = unsafe { mmap.slice(0..(64 << 10) + page_size) }; assert_eq!(&[1, 2, 3, 4], &slice[page_size..][..4]); // Re-instantiate make sure it preserves memory. Grow a bit and set data @@ -1056,10 +1108,17 @@ mod test { .instantiate(initial, Some(&image), &ty, &tunables) .unwrap(); assert_eq!(&[1, 2, 3, 4], &slice[page_size..][..4]); + memfd.set_heap_limit(initial * 2).unwrap(); - assert_eq!(&[0, 0], &slice[initial..initial + 2]); - slice[initial] = 100; - assert_eq!(&[100, 0], &slice[initial..initial + 2]); + + unsafe { + with_slice_mut(&mmap, 0..(64 << 10) + page_size, move |slice| { + assert_eq!(&[0, 0], &slice[initial..initial + 2]); + slice[initial] = 100; + assert_eq!(&[100, 0], &slice[initial..initial + 2]); + }); + } + memfd .clear_and_remain_ready(HostAlignedByteCount::ZERO, |ptr, len| unsafe { decommit_pages(ptr, len).unwrap() @@ -1076,9 +1135,15 @@ mod test { .unwrap(); assert_eq!(&[0, 0], &slice[initial..initial + 2]); memfd.set_heap_limit(initial * 2).unwrap(); - assert_eq!(&[0, 0], &slice[initial..initial + 2]); - slice[initial] = 100; - assert_eq!(&[100, 0], &slice[initial..initial + 2]); + + unsafe { + with_slice_mut(&mmap, 0..(64 << 10) + page_size, move |slice| { + assert_eq!(&[0, 0], &slice[initial..initial + 2]); + slice[initial] = 100; + assert_eq!(&[100, 0], &slice[initial..initial + 2]); + }); + } + memfd .clear_and_remain_ready(HostAlignedByteCount::ZERO, |ptr, len| unsafe { decommit_pages(ptr, len).unwrap() 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 d4a660307ac9..581d92526583 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 @@ -65,7 +65,7 @@ use crate::{ }; use std::ffi::c_void; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::Mutex; +use std::sync::{Arc, Mutex}; use wasmtime_environ::{DefinedMemoryIndex, Module, Tunables}; /// A set of allocator slots. @@ -104,7 +104,7 @@ struct Stripe { /// ``` #[derive(Debug)] pub struct MemoryPool { - mapping: Mmap, + mapping: Arc>, /// This memory pool is stripe-aware. If using memory protection keys, this /// will contain one stripe per available key; otherwise, a single stripe /// with an empty key. @@ -244,7 +244,7 @@ impl MemoryPool { let pool = Self { stripes, - mapping, + mapping: Arc::new(mapping), image_slots, layout, memories_per_instance: usize::try_from(config.limits.max_memories_per_module).unwrap(), diff --git a/crates/wasmtime/src/runtime/vm/memory/mmap.rs b/crates/wasmtime/src/runtime/vm/memory/mmap.rs index 66840f8dcf5c..de95793032ad 100644 --- a/crates/wasmtime/src/runtime/vm/memory/mmap.rs +++ b/crates/wasmtime/src/runtime/vm/memory/mmap.rs @@ -4,13 +4,14 @@ use crate::prelude::*; use crate::runtime::vm::memory::RuntimeLinearMemory; use crate::runtime::vm::{mmap::AlignedLength, HostAlignedByteCount, Mmap}; +use alloc::sync::Arc; use wasmtime_environ::Tunables; /// A linear memory instance. #[derive(Debug)] pub struct MmapMemory { // The underlying allocation. - mmap: Mmap, + mmap: Arc>, // The current length of this Wasm memory, in bytes. // @@ -105,15 +106,18 @@ impl MmapMemory { .err2anyhow() .with_context(|| format!("cannot allocate {minimum} with guard regions"))?; - let mut mmap = Mmap::accessible_reserved(HostAlignedByteCount::ZERO, request_bytes)?; + let mmap = Mmap::accessible_reserved(HostAlignedByteCount::ZERO, request_bytes)?; if minimum > 0 { let accessible = HostAlignedByteCount::new_rounded_up(minimum).err2anyhow()?; - mmap.make_accessible(pre_guard_bytes, accessible)?; + // SAFETY: mmap is not in use right now so it's safe to make it accessible. + unsafe { + mmap.make_accessible(pre_guard_bytes, accessible)?; + } } Ok(Self { - mmap, + mmap: Arc::new(mmap), len: minimum, maximum, pre_guard_size: pre_guard_bytes, @@ -169,7 +173,11 @@ impl RuntimeLinearMemory for MmapMemory { let mut new_mmap = Mmap::accessible_reserved(HostAlignedByteCount::ZERO, request_bytes)?; - new_mmap.make_accessible(self.pre_guard_size, new_accessible)?; + // SAFETY: new_mmap is not in use right now so it's safe to make it + // accessible. + unsafe { + new_mmap.make_accessible(self.pre_guard_size, new_accessible)?; + } // This method has an exclusive reference to `self.mmap` and just // created `new_mmap` so it should be safe to acquire references @@ -182,7 +190,7 @@ impl RuntimeLinearMemory for MmapMemory { dst.copy_from_slice(src); } - self.mmap = new_mmap; + self.mmap = Arc::new(new_mmap); } else { // If the new size of this heap fits within the existing allocation // then all we need to do is to make the new pages accessible. This @@ -198,13 +206,17 @@ impl RuntimeLinearMemory for MmapMemory { // since we are forced to round our accessible range up to the // host's page size. if let Ok(difference) = new_accessible.checked_sub(self.accessible()) { - self.mmap.make_accessible( - self.pre_guard_size - .checked_add(self.accessible()) - .err2anyhow() - .context("overflow calculating new accessible region")?, - difference, - )?; + // SAFETY: the difference was previously inaccessible so we + // never handed out any references to within it. + unsafe { + self.mmap.make_accessible( + self.pre_guard_size + .checked_add(self.accessible()) + .err2anyhow() + .context("overflow calculating new accessible region")?, + difference, + )?; + } } } diff --git a/crates/wasmtime/src/runtime/vm/mmap.rs b/crates/wasmtime/src/runtime/vm/mmap.rs index f9c0d692d43f..a6b76c67db35 100644 --- a/crates/wasmtime/src/runtime/vm/mmap.rs +++ b/crates/wasmtime/src/runtime/vm/mmap.rs @@ -93,17 +93,20 @@ impl Mmap { data: AlignedLength {}, }) } else { - let mut result = Mmap { + let result = Mmap { sys: mmap::Mmap::reserve(mapping_size) .context(format!("mmap failed to reserve {mapping_size:#x} bytes"))?, data: AlignedLength {}, }; if !accessible_size.is_zero() { - result - .make_accessible(HostAlignedByteCount::ZERO, accessible_size) - .context(format!( - "mmap failed to allocate {accessible_size:#x} bytes" - ))?; + // SAFETY: result was just created and is not in use. + unsafe { + result + .make_accessible(HostAlignedByteCount::ZERO, accessible_size) + .context(format!( + "mmap failed to allocate {accessible_size:#x} bytes" + ))?; + } } Ok(result) } @@ -133,11 +136,16 @@ impl Mmap { /// accessible. `start` and `len` must be native page-size multiples and /// describe a range within `self`'s reserved memory. /// + /// # Safety + /// + /// There must not be any other references to the region of memory being + /// made accessible. + /// /// # Panics /// /// Panics if `start + len >= self.len()`. - pub fn make_accessible( - &mut self, + pub unsafe fn make_accessible( + &self, start: HostAlignedByteCount, len: HostAlignedByteCount, ) -> Result<()> { @@ -331,12 +339,12 @@ mod tests { let pagex3 = page_size.checked_mul(3).unwrap(); let pagex4 = page_size.checked_mul(4).unwrap(); - let mut mem = Mmap::accessible_reserved(pagex2, pagex4).expect("allocated memory"); - - mem.make_accessible(pagex3, HostAlignedByteCount::ZERO) - .expect("make_accessible succeeded"); + let mem = Mmap::accessible_reserved(pagex2, pagex4).expect("allocated memory"); unsafe { + mem.make_accessible(pagex3, HostAlignedByteCount::ZERO) + .expect("make_accessible succeeded"); + mem.make_executable(pagex3.byte_count()..pagex3.byte_count(), false) .expect("make_executable succeeded"); diff --git a/crates/wasmtime/src/runtime/vm/sys/custom/mmap.rs b/crates/wasmtime/src/runtime/vm/sys/custom/mmap.rs index 1bcd9b2bfd0f..650bc070d444 100644 --- a/crates/wasmtime/src/runtime/vm/sys/custom/mmap.rs +++ b/crates/wasmtime/src/runtime/vm/sys/custom/mmap.rs @@ -51,8 +51,8 @@ impl Mmap { anyhow::bail!("not supported on this platform"); } - pub fn make_accessible( - &mut self, + pub unsafe fn make_accessible( + &self, start: HostAlignedByteCount, len: HostAlignedByteCount, ) -> Result<()> { diff --git a/crates/wasmtime/src/runtime/vm/sys/miri/mmap.rs b/crates/wasmtime/src/runtime/vm/sys/miri/mmap.rs index 05bd596e9658..eae0ed29fc9f 100644 --- a/crates/wasmtime/src/runtime/vm/sys/miri/mmap.rs +++ b/crates/wasmtime/src/runtime/vm/sys/miri/mmap.rs @@ -30,8 +30,11 @@ impl Mmap { } pub fn new(size: HostAlignedByteCount) -> Result { - let mut ret = Mmap::reserve(size)?; - ret.make_accessible(HostAlignedByteCount::ZERO, size)?; + let ret = Mmap::reserve(size)?; + // SAFETY: The memory was just created so no one else has access to it. + unsafe { + ret.make_accessible(HostAlignedByteCount::ZERO, size)?; + } Ok(ret) } @@ -54,8 +57,8 @@ impl Mmap { bail!("not supported on miri"); } - pub fn make_accessible( - &mut self, + pub unsafe fn make_accessible( + &self, start: HostAlignedByteCount, len: HostAlignedByteCount, ) -> Result<()> { diff --git a/crates/wasmtime/src/runtime/vm/sys/unix/mmap.rs b/crates/wasmtime/src/runtime/vm/sys/unix/mmap.rs index c2a00e0f1abe..a711089510eb 100644 --- a/crates/wasmtime/src/runtime/vm/sys/unix/mmap.rs +++ b/crates/wasmtime/src/runtime/vm/sys/unix/mmap.rs @@ -109,8 +109,8 @@ impl Mmap { Ok(Mmap { memory }) } - pub fn make_accessible( - &mut self, + pub unsafe fn make_accessible( + &self, start: HostAlignedByteCount, len: HostAlignedByteCount, ) -> Result<()> { diff --git a/crates/wasmtime/src/runtime/vm/sys/windows/mmap.rs b/crates/wasmtime/src/runtime/vm/sys/windows/mmap.rs index b45c3488c445..91e58fbbabe5 100644 --- a/crates/wasmtime/src/runtime/vm/sys/windows/mmap.rs +++ b/crates/wasmtime/src/runtime/vm/sys/windows/mmap.rs @@ -146,8 +146,8 @@ impl Mmap { } } - pub fn make_accessible( - &mut self, + pub unsafe fn make_accessible( + &self, start: HostAlignedByteCount, len: HostAlignedByteCount, ) -> Result<()> { From 71cb94be43e479de17f4917c9f2a27afd14dd4b5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Dec 2024 09:57:45 -0700 Subject: [PATCH 03/21] Burn down the `allow_attributes_without_reason` backlog (#9712) * Burn down the `allow_attributes_without_reason` backlog Just a bit, not everything fixed. * Fix wasi-nn annotations * Tweak `#[cfg]` --- benches/call.rs | 6 ++---- cranelift/filetests/src/function_runner.rs | 5 ++++- cranelift/filetests/src/lib.rs | 1 - cranelift/filetests/src/subtest.rs | 2 +- cranelift/filetests/src/test_unwind.rs | 2 +- cranelift/frontend/src/lib.rs | 3 --- cranelift/frontend/src/switch.rs | 2 +- cranelift/module/src/lib.rs | 1 - cranelift/module/src/module.rs | 9 ++------- cranelift/reader/src/lexer.rs | 2 -- cranelift/reader/src/lib.rs | 3 +-- cranelift/reader/src/run_command.rs | 2 +- crates/component-macro/tests/codegen.rs | 5 +---- crates/wasi-keyvalue/tests/main.rs | 4 +--- crates/wasi-nn/tests/check/mod.rs | 6 +----- crates/wasi-nn/tests/check/onnx.rs | 3 --- examples/mpk.rs | 3 --- 17 files changed, 16 insertions(+), 43 deletions(-) diff --git a/benches/call.rs b/benches/call.rs index 9eca3bc6cd53..8e7d95aa8ffb 100644 --- a/benches/call.rs +++ b/benches/call.rs @@ -1,5 +1,3 @@ -#![expect(clippy::allow_attributes_without_reason, reason = "crate not migrated")] - use criterion::measurement::WallTime; use criterion::{criterion_group, criterion_main, BenchmarkGroup, Criterion}; use std::fmt::Debug; @@ -445,7 +443,7 @@ trait ToVals { macro_rules! tuples { ($($t:ident)*) => ( - #[allow(non_snake_case)] + #[allow(non_snake_case, reason = "macro-generated code")] impl<$($t:Copy + Into,)*> ToVals for ($($t,)*) { fn to_vals(&self) -> Vec { let mut _dst = Vec::new(); @@ -534,7 +532,7 @@ mod component { macro_rules! tuples { ($($t:ident)*) => ( - #[allow(non_snake_case)] + #[allow(non_snake_case, reason = "macro-generated code")] impl<$($t:Copy + ToComponentVal,)*> ToComponentVals for ($($t,)*) { fn to_component_vals(&self) -> Vec { let mut _dst = Vec::new(); diff --git a/cranelift/filetests/src/function_runner.rs b/cranelift/filetests/src/function_runner.rs index 2feae28e0183..bc00b1be7dbc 100644 --- a/cranelift/filetests/src/function_runner.rs +++ b/cranelift/filetests/src/function_runner.rs @@ -528,7 +528,10 @@ fn make_trampoline(name: UserFuncName, signature: &ir::Signature, isa: &dyn Targ #[cfg(target_arch = "x86_64")] use std::arch::x86_64::__m128i; #[cfg(target_arch = "x86_64")] -#[allow(improper_ctypes_definitions)] +#[expect( + improper_ctypes_definitions, + reason = "manually verified to work for now" +)] extern "C" fn __cranelift_x86_pshufb(a: __m128i, b: __m128i) -> __m128i { union U { reg: __m128i, diff --git a/cranelift/filetests/src/lib.rs b/cranelift/filetests/src/lib.rs index ab776ba5ea90..b09ba6560737 100644 --- a/cranelift/filetests/src/lib.rs +++ b/cranelift/filetests/src/lib.rs @@ -4,7 +4,6 @@ //! available filetest commands. #![deny(missing_docs)] -#![expect(clippy::allow_attributes_without_reason, reason = "crate not migrated")] pub use crate::function_runner::TestFileCompiler; use crate::runner::TestRunner; diff --git a/cranelift/filetests/src/subtest.rs b/cranelift/filetests/src/subtest.rs index a0761ad9ba21..5321a4e1c9f0 100644 --- a/cranelift/filetests/src/subtest.rs +++ b/cranelift/filetests/src/subtest.rs @@ -29,7 +29,7 @@ pub struct Context<'a> { pub isa: Option<&'a dyn TargetIsa>, /// Full path to the file containing the test. - #[allow(dead_code)] + #[expect(dead_code, reason = "may get used later")] pub file_path: &'a str, /// Context used to update the original `file_path` in-place with its test diff --git a/cranelift/filetests/src/test_unwind.rs b/cranelift/filetests/src/test_unwind.rs index f9fe196dff02..7b01873af06d 100644 --- a/cranelift/filetests/src/test_unwind.rs +++ b/cranelift/filetests/src/test_unwind.rs @@ -108,7 +108,7 @@ mod windowsx64 { version: u8, flags: u8, prologue_size: u8, - #[allow(dead_code)] + #[expect(dead_code, reason = "may get used later")] unwind_code_count_raw: u8, frame_register: u8, frame_register_offset: u8, diff --git a/cranelift/frontend/src/lib.rs b/cranelift/frontend/src/lib.rs index 8f97474b2486..7a9c80919910 100644 --- a/cranelift/frontend/src/lib.rs +++ b/cranelift/frontend/src/lib.rs @@ -157,10 +157,7 @@ #![deny(missing_docs)] #![no_std] -#![expect(clippy::allow_attributes_without_reason, reason = "crate not migrated")] -#[allow(unused_imports)] // #[macro_use] is required for no_std -#[macro_use] extern crate alloc; #[cfg(feature = "std")] diff --git a/cranelift/frontend/src/switch.rs b/cranelift/frontend/src/switch.rs index 24d0fb714bac..9605557a980a 100644 --- a/cranelift/frontend/src/switch.rs +++ b/cranelift/frontend/src/switch.rs @@ -348,8 +348,8 @@ mod tests { let block = bx.create_block(); bx.switch_to_block(block); let val = bx.ins().iconst(types::I8, 0); - #[allow(unused_mut)] let mut switch = Switch::new(); + let _ = &mut switch; $( let block = bx.create_block(); switch.set_entry($index, block); diff --git a/cranelift/module/src/lib.rs b/cranelift/module/src/lib.rs index eb78fcd5c46e..7528ad67caad 100644 --- a/cranelift/module/src/lib.rs +++ b/cranelift/module/src/lib.rs @@ -2,7 +2,6 @@ #![deny(missing_docs)] #![no_std] -#![expect(clippy::allow_attributes_without_reason, reason = "crate not migrated")] #[cfg(not(feature = "std"))] #[macro_use] diff --git a/cranelift/module/src/module.rs b/cranelift/module/src/module.rs index d9494b851ed2..4a32837787ca 100644 --- a/cranelift/module/src/module.rs +++ b/cranelift/module/src/module.rs @@ -220,12 +220,10 @@ impl From for ModuleRelocTarget { feature = "enable-serde", derive(serde_derive::Serialize, serde_derive::Deserialize) )] +#[allow(missing_docs, reason = "self-describing fields")] pub struct FunctionDeclaration { - #[allow(missing_docs)] pub name: Option, - #[allow(missing_docs)] pub linkage: Linkage, - #[allow(missing_docs)] pub signature: ir::Signature, } @@ -379,14 +377,11 @@ pub type ModuleResult = Result; feature = "enable-serde", derive(serde_derive::Serialize, serde_derive::Deserialize) )] +#[allow(missing_docs, reason = "self-describing fields")] pub struct DataDeclaration { - #[allow(missing_docs)] pub name: Option, - #[allow(missing_docs)] pub linkage: Linkage, - #[allow(missing_docs)] pub writable: bool, - #[allow(missing_docs)] pub tls: bool, } diff --git a/cranelift/reader/src/lexer.rs b/cranelift/reader/src/lexer.rs index 28d75feb5137..76b36e1920de 100644 --- a/cranelift/reader/src/lexer.rs +++ b/cranelift/reader/src/lexer.rs @@ -3,8 +3,6 @@ use crate::error::Location; use cranelift_codegen::ir::types; use cranelift_codegen::ir::{Block, Value}; -#[allow(unused_imports, deprecated)] -use std::ascii::AsciiExt; use std::str::CharIndices; use std::u16; diff --git a/cranelift/reader/src/lib.rs b/cranelift/reader/src/lib.rs index 7dbc732b28e6..e4d5ea95e030 100644 --- a/cranelift/reader/src/lib.rs +++ b/cranelift/reader/src/lib.rs @@ -4,7 +4,6 @@ //! testing Cranelift, but is not essential for a JIT compiler. #![deny(missing_docs)] -#![expect(clippy::allow_attributes_without_reason, reason = "crate not migrated")] pub use crate::error::{Location, ParseError, ParseResult}; pub use crate::isaspec::{parse_option, parse_options, IsaSpec, ParseOptionError}; @@ -30,7 +29,7 @@ use std::str::FromStr; use target_lexicon::Triple; /// Like `FlagsOrIsa`, but holds ownership. -#[allow(missing_docs)] +#[allow(missing_docs, reason = "self-describing variants")] pub enum OwnedFlagsOrIsa { Flags(settings::Flags), Isa(OwnedTargetIsa), diff --git a/cranelift/reader/src/run_command.rs b/cranelift/reader/src/run_command.rs index 0c1b2876d362..2fa616539694 100644 --- a/cranelift/reader/src/run_command.rs +++ b/cranelift/reader/src/run_command.rs @@ -105,7 +105,7 @@ impl Display for Invocation { } /// A CLIF comparison operation; e.g. `==`. -#[allow(missing_docs)] +#[allow(missing_docs, reason = "self-describing variants")] #[derive(Debug, PartialEq)] pub enum Comparison { Equals, diff --git a/crates/component-macro/tests/codegen.rs b/crates/component-macro/tests/codegen.rs index c9124aa665cb..73d61fd99539 100644 --- a/crates/component-macro/tests/codegen.rs +++ b/crates/component-macro/tests/codegen.rs @@ -1,5 +1,4 @@ -#![allow(dead_code)] -#![expect(clippy::allow_attributes_without_reason, reason = "crate not migrated")] +#![allow(dead_code, reason = "lots of macro-generated code")] macro_rules! gentest { ($id:ident $name:tt $path:tt) => { @@ -135,7 +134,6 @@ mod trappable_errors_with_versioned_and_unversioned_packages { }, }); - #[allow(dead_code)] type MyX = u64; } @@ -177,7 +175,6 @@ mod trappable_errors { }, }); - #[allow(dead_code)] type MyX = u32; } diff --git a/crates/wasi-keyvalue/tests/main.rs b/crates/wasi-keyvalue/tests/main.rs index b84e9b059ad0..6ae8eee18a56 100644 --- a/crates/wasi-keyvalue/tests/main.rs +++ b/crates/wasi-keyvalue/tests/main.rs @@ -1,5 +1,3 @@ -#![expect(clippy::allow_attributes_without_reason, reason = "crate not migrated")] - use anyhow::{anyhow, Result}; use test_programs_artifacts::{foreach_keyvalue, KEYVALUE_MAIN_COMPONENT}; use wasmtime::{ @@ -48,7 +46,7 @@ async fn run_wasi(path: &str, ctx: Ctx) -> Result<()> { macro_rules! assert_test_exists { ($name:ident) => { - #[allow(unused_imports)] + #[expect(unused_imports, reason = "just here to assert it exists")] use self::$name as _; }; } diff --git a/crates/wasi-nn/tests/check/mod.rs b/crates/wasi-nn/tests/check/mod.rs index ff21fee38d4d..32e175cdff7a 100644 --- a/crates/wasi-nn/tests/check/mod.rs +++ b/crates/wasi-nn/tests/check/mod.rs @@ -4,10 +4,6 @@ //! - that various backends can be located on the system (see sub-modules) //! - that certain ML model artifacts can be downloaded and cached. -#![expect(clippy::allow_attributes_without_reason, reason = "crate not migrated")] - -#[allow(unused_imports)] -use anyhow::{anyhow, Context, Result}; use std::{ env, path::{Path, PathBuf}, @@ -15,7 +11,7 @@ use std::{ sync::Mutex, }; -#[cfg(any(feature = "onnx", feature = "winml"))] +#[cfg(any(feature = "onnx", all(feature = "winml", target_os = "windows")))] pub mod onnx; #[cfg(feature = "openvino")] pub mod openvino; diff --git a/crates/wasi-nn/tests/check/onnx.rs b/crates/wasi-nn/tests/check/onnx.rs index b5a451e0373f..cdbec420de22 100644 --- a/crates/wasi-nn/tests/check/onnx.rs +++ b/crates/wasi-nn/tests/check/onnx.rs @@ -1,8 +1,5 @@ -#![allow(unused)] - use super::{artifacts_dir, download, DOWNLOAD_LOCK}; use anyhow::{Context, Result}; -use std::sync::Mutex; use std::{env, fs}; /// Return `Ok` if we find the cached MobileNet test artifacts; this will diff --git a/examples/mpk.rs b/examples/mpk.rs index 59edaaabf086..8b850d2edbdb 100644 --- a/examples/mpk.rs +++ b/examples/mpk.rs @@ -31,8 +31,6 @@ //! $ sysctl vm.max_map_count=$LARGER_LIMIT //! ``` -#![expect(clippy::allow_attributes_without_reason, reason = "crate not migrated")] - use anyhow::anyhow; use bytesize::ByteSize; use clap::Parser; @@ -115,7 +113,6 @@ fn probe_engine_size(args: &Args, mpk: MpkEnabled) -> Result { } #[derive(Debug)] -#[allow(dead_code)] struct Pool { num_memories: u32, mapped_bytes: usize, From 9034e10103f103e37291c179245d1702612b0968 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Dec 2024 11:27:28 -0700 Subject: [PATCH 04/21] Rely on `core::error::Error` (#9702) * Rely on `core::error::Error` With Wasmtime's new MSRV at 1.81 this means that `core::error::Error` is available which means that in `no_std` mode the `Error` trait can be used. This has been integrated into `anyhow::Error` already upstream and means that we can remove our own local hacks such as the `Err2Anyhow` trait. This commit removes the `Err2Anyhow` trait and all usage, going back to idiomatic Rust error propagation and conversion even in the `no_std` world. This should make code more portable by default and remove some weird idioms we had for supporting this. prtest:full * Add some trusted vets * Audit object crate update * Disable backtraces on CI --- .github/workflows/main.yml | 11 --- Cargo.lock | 72 +++++++-------- Cargo.toml | 6 +- crates/environ/src/compile/mod.rs | 3 +- crates/environ/src/obj.rs | 20 ++++ crates/environ/src/prelude.rs | 58 ------------ crates/environ/src/trap_encoding.rs | 3 +- crates/environ/src/types.rs | 3 +- crates/wasmtime/src/engine/serialization.rs | 12 +-- crates/wasmtime/src/runtime/code_memory.rs | 6 +- .../src/runtime/component/component.rs | 2 +- crates/wasmtime/src/runtime/component/func.rs | 4 +- .../src/runtime/component/func/host.rs | 8 +- .../src/runtime/component/func/options.rs | 8 +- .../src/runtime/component/func/typed.rs | 37 +++----- .../wasmtime/src/runtime/component/values.rs | 8 +- crates/wasmtime/src/runtime/debug.rs | 3 +- .../wasmtime/src/runtime/externals/table.rs | 11 +-- crates/wasmtime/src/runtime/gc.rs | 3 +- .../src/runtime/gc/enabled/arrayref.rs | 4 +- .../src/runtime/gc/enabled/externref.rs | 4 - .../src/runtime/gc/enabled/structref.rs | 4 +- crates/wasmtime/src/runtime/linker.rs | 6 +- crates/wasmtime/src/runtime/module.rs | 22 ++--- crates/wasmtime/src/runtime/store.rs | 4 +- crates/wasmtime/src/runtime/trap.rs | 4 +- crates/wasmtime/src/runtime/types.rs | 1 - crates/wasmtime/src/runtime/vm/byte_count.rs | 6 +- .../src/runtime/vm/component/libcalls.rs | 2 +- crates/wasmtime/src/runtime/vm/cow.rs | 34 +++---- .../wasmtime/src/runtime/vm/gc/enabled/drc.rs | 2 +- .../src/runtime/vm/gc/enabled/free_list.rs | 1 - .../src/runtime/vm/gc/enabled/null.rs | 4 +- .../src/runtime/vm/instance/allocator.rs | 29 +++--- .../instance/allocator/pooling/table_pool.rs | 4 +- .../allocator/pooling/unix_stack_pool.rs | 2 - crates/wasmtime/src/runtime/vm/libcalls.rs | 91 +++++++------------ .../wasmtime/src/runtime/vm/memory/malloc.rs | 12 +-- crates/wasmtime/src/runtime/vm/memory/mmap.rs | 10 +- crates/wasmtime/src/runtime/vm/mmap.rs | 2 +- .../wasmtime/src/runtime/vm/sys/unix/mmap.rs | 17 ++-- crates/wasmtime/src/runtime/vm/sys/unix/vm.rs | 19 ++-- .../src/runtime/vm/sys/windows/mmap.rs | 10 +- supply-chain/audits.toml | 14 ++- supply-chain/imports.lock | 20 ++-- 45 files changed, 231 insertions(+), 375 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0705df14dc4a..dfab1f43af94 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -641,12 +641,8 @@ jobs: - run: cmake -Sexamples -Bexamples/build -DBUILD_SHARED_LIBS=OFF - run: cmake --build examples/build --config Debug - run: cmake -E env CTEST_OUTPUT_ON_FAILURE=1 cmake --build examples/build --config Debug --target RUN_TESTS - env: - RUST_BACKTRACE: 1 if: matrix.os == 'windows-latest' - run: cmake -E env CTEST_OUTPUT_ON_FAILURE=1 cmake --build examples/build --config Debug --target test - env: - RUST_BACKTRACE: 1 if: matrix.os != 'windows-latest' # Perform all tests (debug mode) for `wasmtime`. @@ -771,8 +767,6 @@ jobs: # Build and test all features - run: ./ci/run-tests.sh --locked ${{ matrix.bucket }} - env: - RUST_BACKTRACE: 1 # NB: the test job here is explicitly lacking in cancellation of this run if # something goes wrong. These take the longest anyway and otherwise if @@ -817,8 +811,6 @@ jobs: # Run the tests! - run: cargo test -p wasmtime-wasi-nn --features ${{ matrix.feature }} - env: - RUST_BACKTRACE: 1 # common logic to cancel the entire run if this job fails - run: gh run cancel ${{ github.run_id }} @@ -843,8 +835,6 @@ jobs: # Run the tests - run: | cargo test -p wasmtime-fuzzing -p wasm-spec-interpreter - env: - RUST_BACKTRACE: 1 # common logic to cancel the entire run if this job fails - run: gh run cancel ${{ github.run_id }} @@ -871,7 +861,6 @@ jobs: sudo ln -s /usr/lib/llvm-15/lib/python3.10/dist-packages/lldb/* /usr/lib/python3/dist-packages/lldb/ cargo test --test all -- --ignored --test-threads 1 debug:: env: - RUST_BACKTRACE: 1 LLDB: lldb-15 # override default version, 14 # common logic to cancel the entire run if this job fails diff --git a/Cargo.lock b/Cargo.lock index 8767bb186385..7372d2d717f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,9 +133,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arbitrary" @@ -160,7 +160,7 @@ checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -227,7 +227,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.60", + "syn 2.0.90", "which 4.4.2", ] @@ -579,7 +579,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -627,7 +627,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -1086,7 +1086,7 @@ checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -2019,7 +2019,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.8.5", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -2224,12 +2224,12 @@ checksum = "17b02fc0ff9a9e4b35b3342880f48e896ebf69f2967921fe8646bf5b7125956a" [[package]] name = "object" -version = "0.36.0" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "crc32fast", - "hashbrown 0.14.3", + "hashbrown 0.15.2", "indexmap 2.2.6", "memchr", ] @@ -2431,14 +2431,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -2835,22 +2835,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.188" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -3077,9 +3077,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -3222,7 +3222,7 @@ checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -3313,7 +3313,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -3408,7 +3408,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -3717,7 +3717,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", "wasm-bindgen-shared", ] @@ -3739,7 +3739,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4174,7 +4174,7 @@ dependencies = [ "serde", "serde_json", "similar", - "syn 2.0.60", + "syn 2.0.90", "tracing", "wasmtime", "wasmtime-component-util", @@ -4369,7 +4369,7 @@ dependencies = [ "anyhow", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", "wasmtime-wast-util", ] @@ -4379,7 +4379,7 @@ version = "28.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -4644,7 +4644,7 @@ dependencies = [ "proc-macro2", "quote", "shellexpand", - "syn 2.0.60", + "syn 2.0.90", "witx", ] @@ -4654,7 +4654,7 @@ version = "28.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", "wiggle", "wiggle-generate", ] @@ -4747,7 +4747,7 @@ checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -4758,7 +4758,7 @@ checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] @@ -4974,7 +4974,7 @@ dependencies = [ "heck 0.5.0", "indexmap 2.2.6", "prettyplease", - "syn 2.0.60", + "syn 2.0.90", "wasm-metadata 0.220.0", "wit-bindgen-core", "wit-component 0.220.0", @@ -4990,7 +4990,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -5109,7 +5109,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.90", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c31a6de45d4f..2ec821c79311 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -291,10 +291,10 @@ wasm-wave = "0.221.2" # Non-Bytecode Alliance maintained dependencies: # -------------------------- cc = "1.0" -object = { version = "0.36", default-features = false, features = ['read_core', 'elf'] } +object = { version = "0.36.5", default-features = false, features = ['read_core', 'elf'] } gimli = { version = "0.31.0", default-features = false, features = ['read'] } addr2line = { version = "0.24.1", default-features = false } -anyhow = { version = "1.0.22", default-features = false } +anyhow = { version = "1.0.93", default-features = false } windows-sys = "0.59.0" env_logger = "0.11.5" log = { version = "0.4.8", default-features = false } @@ -317,7 +317,7 @@ proptest = "1.0.0" rand = { version = "0.8.3", features = ["small_rng"] } sptr = "0.3.2" # serde and serde_derive must have the same version -serde = { version = "1.0.188", default-features = false, features = ['alloc'] } +serde = { version = "1.0.215", default-features = false, features = ['alloc'] } serde_derive = "1.0.188" serde_json = "1.0.80" glob = "0.3.0" diff --git a/crates/environ/src/compile/mod.rs b/crates/environ/src/compile/mod.rs index 51da11a9f672..de12ba29f3f0 100644 --- a/crates/environ/src/compile/mod.rs +++ b/crates/environ/src/compile/mod.rs @@ -59,8 +59,7 @@ impl From for CompileError { } } -#[cfg(feature = "std")] -impl std::error::Error for CompileError { +impl core::error::Error for CompileError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { CompileError::Wasm(e) => Some(e), diff --git a/crates/environ/src/obj.rs b/crates/environ/src/obj.rs index 2b904d76b48d..d50b5b1eca0a 100644 --- a/crates/environ/src/obj.rs +++ b/crates/environ/src/obj.rs @@ -1,6 +1,8 @@ //! Utilities for working with object files that operate as Wasmtime's //! serialization and intermediate format for compiled modules. +use core::fmt; + /// Filler for the `os_abi` field of the ELF header. /// /// This is just a constant that seems reasonable in the sense it's unlikely to @@ -177,3 +179,21 @@ libcalls! { FmaF64 = "libcall_fmaf64" X86Pshufb = "libcall_x86_pshufb" } + +/// Workaround to implement `core::error::Error` until +/// gimli-rs/object#747 is settled. +pub struct ObjectCrateErrorWrapper(pub object::Error); + +impl fmt::Debug for ObjectCrateErrorWrapper { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl fmt::Display for ObjectCrateErrorWrapper { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl core::error::Error for ObjectCrateErrorWrapper {} diff --git a/crates/environ/src/prelude.rs b/crates/environ/src/prelude.rs index 43168d1f1748..94d30d3b1363 100644 --- a/crates/environ/src/prelude.rs +++ b/crates/environ/src/prelude.rs @@ -26,61 +26,3 @@ pub use alloc::string::{String, ToString}; pub use alloc::vec; pub use alloc::vec::Vec; pub use wasmparser::collections::{IndexMap, IndexSet}; - -/// Convenience trait for converting `Result` into `anyhow::Result` -/// -/// Typically this is automatically done with the `?` operator in Rust and -/// by default this trait isn't necessary. With the `anyhow` crate's `std` -/// feature disabled, however, the `?` operator won't work because the `Error` -/// trait is not defined. This trait helps to bridge this gap. -/// -/// This does the same thing as `?` when the `std` feature is enabled, and when -/// `std` is disabled it'll use different trait bounds to create an -/// `anyhow::Error`. -/// -/// This trait is not suitable as a public interface because features change -/// what implements the trait. It's good enough for a wasmtime internal -/// implementation detail, however. -pub trait Err2Anyhow { - /// Convert `self` to `anyhow::Result`. - fn err2anyhow(self) -> anyhow::Result; -} - -impl Err2Anyhow for Result { - fn err2anyhow(self) -> anyhow::Result { - match self { - Ok(e) => Ok(e), - Err(e) => Err(e.into_anyhow()), - } - } -} - -/// Convenience trait to convert a value into `anyhow::Error` -/// -/// This trait is not a suitable public interface of Wasmtime so it's just an -/// internal implementation detail for now. This trait is conditionally -/// implemented on the `std` feature with different bounds. -pub trait IntoAnyhow { - /// Converts `self` into an `anyhow::Error`. - fn into_anyhow(self) -> anyhow::Error; -} - -#[cfg(feature = "std")] -impl IntoAnyhow for T -where - T: Into, -{ - fn into_anyhow(self) -> anyhow::Error { - self.into() - } -} - -#[cfg(not(feature = "std"))] -impl IntoAnyhow for T -where - T: core::fmt::Display + core::fmt::Debug + Send + Sync + 'static, -{ - fn into_anyhow(self) -> anyhow::Error { - anyhow::Error::msg(self) - } -} diff --git a/crates/environ/src/trap_encoding.rs b/crates/environ/src/trap_encoding.rs index b735f8d9e3ce..0006d3e3ec9a 100644 --- a/crates/environ/src/trap_encoding.rs +++ b/crates/environ/src/trap_encoding.rs @@ -159,8 +159,7 @@ impl fmt::Display for Trap { } } -#[cfg(feature = "std")] -impl std::error::Error for Trap {} +impl core::error::Error for Trap {} /// Decodes the provided trap information section and attempts to find the trap /// code corresponding to the `offset` specified. diff --git a/crates/environ/src/types.rs b/crates/environ/src/types.rs index 2d70bc698a6e..ed6065291e52 100644 --- a/crates/environ/src/types.rs +++ b/crates/environ/src/types.rs @@ -1887,8 +1887,7 @@ impl fmt::Display for SizeOverflow { } } -#[cfg(feature = "std")] -impl std::error::Error for SizeOverflow {} +impl core::error::Error for SizeOverflow {} impl From for Memory { fn from(ty: wasmparser::MemoryType) -> Memory { diff --git a/crates/wasmtime/src/engine/serialization.rs b/crates/wasmtime/src/engine/serialization.rs index 6f42c35772ed..94b3ad37607c 100644 --- a/crates/wasmtime/src/engine/serialization.rs +++ b/crates/wasmtime/src/engine/serialization.rs @@ -57,7 +57,7 @@ pub fn check_compatible(engine: &Engine, mmap: &[u8], expected: ObjectKind) -> R // a perf issue right now so doing that is left for another day's // refactoring. let obj = ElfFile64::::parse(mmap) - .err2anyhow() + .map_err(obj::ObjectCrateErrorWrapper) .context("failed to parse precompiled artifact as an ELF")?; let expected_e_flags = match expected { ObjectKind::Module => obj::EF_WASMTIME_MODULE, @@ -76,7 +76,7 @@ pub fn check_compatible(engine: &Engine, mmap: &[u8], expected: ObjectKind) -> R .section_by_name(obj::ELF_WASM_ENGINE) .ok_or_else(|| anyhow!("failed to find section `{}`", obj::ELF_WASM_ENGINE))? .data() - .err2anyhow()?; + .map_err(obj::ObjectCrateErrorWrapper)?; let (first, data) = data .split_first() .ok_or_else(|| anyhow!("invalid engine section"))?; @@ -95,7 +95,7 @@ pub fn check_compatible(engine: &Engine, mmap: &[u8], expected: ObjectKind) -> R match &engine.config().module_version { ModuleVersionStrategy::WasmtimeVersion => { - let version = core::str::from_utf8(version).err2anyhow()?; + let version = core::str::from_utf8(version)?; if version != env!("CARGO_PKG_VERSION") { bail!( "Module was compiled with incompatible Wasmtime version '{}'", @@ -104,7 +104,7 @@ pub fn check_compatible(engine: &Engine, mmap: &[u8], expected: ObjectKind) -> R } } ModuleVersionStrategy::Custom(v) => { - let version = core::str::from_utf8(&version).err2anyhow()?; + let version = core::str::from_utf8(&version)?; if version != v { bail!( "Module was compiled with incompatible version '{}'", @@ -114,9 +114,7 @@ pub fn check_compatible(engine: &Engine, mmap: &[u8], expected: ObjectKind) -> R } ModuleVersionStrategy::None => { /* ignore the version info, accept all */ } } - postcard::from_bytes::>(data) - .err2anyhow()? - .check_compatible(engine) + postcard::from_bytes::>(data)?.check_compatible(engine) } #[cfg(any(feature = "cranelift", feature = "winch"))] diff --git a/crates/wasmtime/src/runtime/code_memory.rs b/crates/wasmtime/src/runtime/code_memory.rs index b1eb98caef7a..8ad04f789b71 100644 --- a/crates/wasmtime/src/runtime/code_memory.rs +++ b/crates/wasmtime/src/runtime/code_memory.rs @@ -58,7 +58,7 @@ impl CodeMemory { /// `publish` method is used to actually make the memory executable. pub fn new(mmap: MmapVec) -> Result { let obj = ElfFile64::::parse(&mmap[..]) - .err2anyhow() + .map_err(obj::ObjectCrateErrorWrapper) .with_context(|| "failed to parse internal compilation artifact")?; let mut relocations = Vec::new(); @@ -75,8 +75,8 @@ impl CodeMemory { let mut info_data = 0..0; let mut wasm_dwarf = 0..0; for section in obj.sections() { - let data = section.data().err2anyhow()?; - let name = section.name().err2anyhow()?; + let data = section.data().map_err(obj::ObjectCrateErrorWrapper)?; + let name = section.name().map_err(obj::ObjectCrateErrorWrapper)?; let range = subslice_range(data, &mmap); // Double-check that sections are all aligned properly. diff --git a/crates/wasmtime/src/runtime/component/component.rs b/crates/wasmtime/src/runtime/component/component.rs index c32f319bdfb4..10af60dc94ec 100644 --- a/crates/wasmtime/src/runtime/component/component.rs +++ b/crates/wasmtime/src/runtime/component/component.rs @@ -388,7 +388,7 @@ impl Component { static_modules, } = match artifacts { Some(artifacts) => artifacts, - None => postcard::from_bytes(code_memory.wasmtime_info()).err2anyhow()?, + None => postcard::from_bytes(code_memory.wasmtime_info())?, }; // Validate that the component can be used with the current instance diff --git a/crates/wasmtime/src/runtime/component/func.rs b/crates/wasmtime/src/runtime/component/func.rs index 6643f6ecef7b..9ac5329af7ce 100644 --- a/crates/wasmtime/src/runtime/component/func.rs +++ b/crates/wasmtime/src/runtime/component/func.rs @@ -669,8 +669,8 @@ impl Func { src: &mut core::slice::Iter<'_, ValRaw>, ) -> Result<()> { // FIXME: needs to read an i64 for memory64 - let ptr = usize::try_from(src.next().unwrap().get_u32()).err2anyhow()?; - if ptr % usize::try_from(results_ty.abi.align32).err2anyhow()? != 0 { + let ptr = usize::try_from(src.next().unwrap().get_u32())?; + if ptr % usize::try_from(results_ty.abi.align32)? != 0 { bail!("return pointer not aligned"); } diff --git a/crates/wasmtime/src/runtime/component/func/host.rs b/crates/wasmtime/src/runtime/component/func/host.rs index f53df1b6b6f6..d55ac2ce5237 100644 --- a/crates/wasmtime/src/runtime/component/func/host.rs +++ b/crates/wasmtime/src/runtime/component/func/host.rs @@ -275,8 +275,8 @@ where fn validate_inbounds(memory: &[u8], ptr: &ValRaw) -> Result { // FIXME: needs memory64 support - let ptr = usize::try_from(ptr.get_u32()).err2anyhow()?; - if ptr % usize::try_from(T::ALIGN32).err2anyhow()? != 0 { + let ptr = usize::try_from(ptr.get_u32())?; + if ptr % usize::try_from(T::ALIGN32)? != 0 { bail!("pointer not aligned"); } let end = match ptr.checked_add(T::SIZE32) { @@ -407,8 +407,8 @@ where fn validate_inbounds_dynamic(abi: &CanonicalAbiInfo, memory: &[u8], ptr: &ValRaw) -> Result { // FIXME: needs memory64 support - let ptr = usize::try_from(ptr.get_u32()).err2anyhow()?; - if ptr % usize::try_from(abi.align32).err2anyhow()? != 0 { + let ptr = usize::try_from(ptr.get_u32())?; + if ptr % usize::try_from(abi.align32)? != 0 { bail!("pointer not aligned"); } let end = match ptr.checked_add(usize::try_from(abi.size32).unwrap()) { diff --git a/crates/wasmtime/src/runtime/component/func/options.rs b/crates/wasmtime/src/runtime/component/func/options.rs index 83accf3dee97..cd0482965e21 100644 --- a/crates/wasmtime/src/runtime/component/func/options.rs +++ b/crates/wasmtime/src/runtime/component/func/options.rs @@ -89,10 +89,10 @@ impl Options { let realloc = self.realloc.unwrap(); let params = ( - u32::try_from(old).err2anyhow()?, - u32::try_from(old_size).err2anyhow()?, + u32::try_from(old)?, + u32::try_from(old_size)?, old_align, - u32::try_from(new_size).err2anyhow()?, + u32::try_from(new_size)?, ); type ReallocFunc = crate::TypedFunc<(u32, u32, u32, u32), u32>; @@ -108,7 +108,7 @@ impl Options { if result % old_align != 0 { bail!("realloc return: result not aligned"); } - let result = usize::try_from(result).err2anyhow()?; + let result = usize::try_from(result)?; let memory = self.memory_mut(store.0); diff --git a/crates/wasmtime/src/runtime/component/func/typed.rs b/crates/wasmtime/src/runtime/component/func/typed.rs index a2ab99c55ba8..4dd5050e000d 100644 --- a/crates/wasmtime/src/runtime/component/func/typed.rs +++ b/crates/wasmtime/src/runtime/component/func/typed.rs @@ -315,8 +315,8 @@ where ) -> Result { assert!(Return::flatten_count() > MAX_FLAT_RESULTS); // FIXME: needs to read an i64 for memory64 - let ptr = usize::try_from(dst.get_u32()).err2anyhow()?; - if ptr % usize::try_from(Return::ALIGN32).err2anyhow()? != 0 { + let ptr = usize::try_from(dst.get_u32())?; + if ptr % usize::try_from(Return::ALIGN32)? != 0 { bail!("return pointer not aligned"); } @@ -1053,7 +1053,7 @@ unsafe impl Lift for char { #[inline] fn lift(_cx: &mut LiftContext<'_>, ty: InterfaceType, src: &Self::Lower) -> Result { debug_assert!(matches!(ty, InterfaceType::Char)); - Ok(char::try_from(src.get_u32()).err2anyhow()?) + Ok(char::try_from(src.get_u32())?) } #[inline] @@ -1061,7 +1061,7 @@ unsafe impl Lift for char { debug_assert!(matches!(ty, InterfaceType::Char)); debug_assert!((bytes.as_ptr() as usize) % Self::SIZE32 == 0); let bits = u32::from_le_bytes(bytes.try_into().unwrap()); - Ok(char::try_from(bits).err2anyhow()?) + Ok(char::try_from(bits)?) } } @@ -1337,9 +1337,7 @@ impl WasmStr { // Note that bounds-checking already happen in construction of `WasmStr` // so this is never expected to panic. This could theoretically be // unchecked indexing if we're feeling wild enough. - Ok(str::from_utf8(&memory[self.ptr..][..self.len]) - .err2anyhow()? - .into()) + Ok(str::from_utf8(&memory[self.ptr..][..self.len])?.into()) } fn decode_utf16<'a>(&self, memory: &'a [u8], len: usize) -> Result> { @@ -1350,8 +1348,7 @@ impl WasmStr { .chunks(2) .map(|chunk| u16::from_le_bytes(chunk.try_into().unwrap())), ) - .collect::>() - .err2anyhow()? + .collect::>()? .into()) } @@ -1385,10 +1382,7 @@ unsafe impl Lift for WasmStr { // FIXME: needs memory64 treatment let ptr = src[0].get_u32(); let len = src[1].get_u32(); - let (ptr, len) = ( - usize::try_from(ptr).err2anyhow()?, - usize::try_from(len).err2anyhow()?, - ); + let (ptr, len) = (usize::try_from(ptr)?, usize::try_from(len)?); WasmStr::new(ptr, len, cx) } @@ -1399,10 +1393,7 @@ unsafe impl Lift for WasmStr { // FIXME: needs memory64 treatment let ptr = u32::from_le_bytes(bytes[..4].try_into().unwrap()); let len = u32::from_le_bytes(bytes[4..].try_into().unwrap()); - let (ptr, len) = ( - usize::try_from(ptr).err2anyhow()?, - usize::try_from(len).err2anyhow()?, - ); + let (ptr, len) = (usize::try_from(ptr)?, usize::try_from(len)?); WasmStr::new(ptr, len, cx) } } @@ -1539,7 +1530,7 @@ impl WasmList { Some(n) if n <= cx.memory().len() => {} _ => bail!("list pointer/length out of bounds of memory"), } - if ptr % usize::try_from(T::ALIGN32).err2anyhow()? != 0 { + if ptr % usize::try_from(T::ALIGN32)? != 0 { bail!("list pointer is not aligned") } Ok(WasmList { @@ -1695,10 +1686,7 @@ unsafe impl Lift for WasmList { // FIXME: needs memory64 treatment let ptr = src[0].get_u32(); let len = src[1].get_u32(); - let (ptr, len) = ( - usize::try_from(ptr).err2anyhow()?, - usize::try_from(len).err2anyhow()?, - ); + let (ptr, len) = (usize::try_from(ptr)?, usize::try_from(len)?); WasmList::new(ptr, len, cx, elem) } @@ -1711,10 +1699,7 @@ unsafe impl Lift for WasmList { // FIXME: needs memory64 treatment let ptr = u32::from_le_bytes(bytes[..4].try_into().unwrap()); let len = u32::from_le_bytes(bytes[4..].try_into().unwrap()); - let (ptr, len) = ( - usize::try_from(ptr).err2anyhow()?, - usize::try_from(len).err2anyhow()?, - ); + let (ptr, len) = (usize::try_from(ptr)?, usize::try_from(len)?); WasmList::new(ptr, len, cx, elem) } } diff --git a/crates/wasmtime/src/runtime/component/values.rs b/crates/wasmtime/src/runtime/component/values.rs index 423158c0047d..15d99847897d 100644 --- a/crates/wasmtime/src/runtime/component/values.rs +++ b/crates/wasmtime/src/runtime/component/values.rs @@ -439,9 +439,7 @@ impl Val { ty: InterfaceType, offset: usize, ) -> Result<()> { - debug_assert!( - offset % usize::try_from(cx.types.canonical_abi(&ty).align32).err2anyhow()? == 0 - ); + debug_assert!(offset % usize::try_from(cx.types.canonical_abi(&ty).align32)? == 0); match (ty, self) { (InterfaceType::Bool, Val::Bool(value)) => value.store(cx, ty, offset), @@ -832,7 +830,7 @@ fn load_list(cx: &mut LiftContext<'_>, ty: TypeListIndex, ptr: usize, len: usize Some(n) if n <= cx.memory().len() => {} _ => bail!("list pointer/length out of bounds of memory"), } - if ptr % usize::try_from(element_alignment).err2anyhow()? != 0 { + if ptr % usize::try_from(element_alignment)? != 0 { bail!("list pointer is not aligned") } @@ -914,7 +912,7 @@ fn lower_list( items: &[Val], ) -> Result<(usize, usize)> { let abi = cx.types.canonical_abi(&element_type); - let elt_size = usize::try_from(abi.size32).err2anyhow()?; + let elt_size = usize::try_from(abi.size32)?; let elt_align = abi.align32; let size = items .len() diff --git a/crates/wasmtime/src/runtime/debug.rs b/crates/wasmtime/src/runtime/debug.rs index 6636e19b56e0..1fa4d430b88d 100644 --- a/crates/wasmtime/src/runtime/debug.rs +++ b/crates/wasmtime/src/runtime/debug.rs @@ -7,6 +7,7 @@ use object::{ File, NativeEndian as NE, Object, ObjectSection, ObjectSymbol, RelocationEncoding, RelocationKind, RelocationTarget, U64Bytes, }; +use wasmtime_environ::obj; pub(crate) fn create_gdbjit_image( mut bytes: Vec, @@ -32,7 +33,7 @@ pub(crate) fn create_gdbjit_image( fn relocate_dwarf_sections(bytes: &mut [u8], code_region: (*const u8, usize)) -> Result<(), Error> { let mut relocations = Vec::new(); - let obj = File::parse(&bytes[..]).err2anyhow()?; + let obj = File::parse(&bytes[..]).map_err(obj::ObjectCrateErrorWrapper)?; for section in obj.sections() { let section_start = match section.file_range() { Some((start, _)) => start, diff --git a/crates/wasmtime/src/runtime/externals/table.rs b/crates/wasmtime/src/runtime/externals/table.rs index ea765f12bab5..24f611a4c005 100644 --- a/crates/wasmtime/src/runtime/externals/table.rs +++ b/crates/wasmtime/src/runtime/externals/table.rs @@ -111,9 +111,7 @@ impl Table { unsafe { let table = Table::from_wasmtime_table(wasmtime_export, store); let wasmtime_table = table.wasmtime_table(store, iter::empty()); - (*wasmtime_table) - .fill(store.optional_gc_store_mut()?, 0, init, ty.minimum()) - .err2anyhow()?; + (*wasmtime_table).fill(store.optional_gc_store_mut()?, 0, init, ty.minimum())?; Ok(table) } } @@ -344,8 +342,7 @@ impl Table { dst_index, src_index, len, - ) - .err2anyhow()?; + )?; } Ok(()) } @@ -373,9 +370,7 @@ impl Table { let table = self.wasmtime_table(store, iter::empty()); unsafe { - (*table) - .fill(store.optional_gc_store_mut()?, dst, val, len) - .err2anyhow()?; + (*table).fill(store.optional_gc_store_mut()?, dst, val, len)?; } Ok(()) diff --git a/crates/wasmtime/src/runtime/gc.rs b/crates/wasmtime/src/runtime/gc.rs index bcce10e76f62..6c972e287c8d 100644 --- a/crates/wasmtime/src/runtime/gc.rs +++ b/crates/wasmtime/src/runtime/gc.rs @@ -80,8 +80,7 @@ impl fmt::Display for GcHeapOutOfMemory { } } -#[cfg(feature = "std")] -impl std::error::Error for GcHeapOutOfMemory {} +impl core::error::Error for GcHeapOutOfMemory {} impl GcHeapOutOfMemory { pub(crate) fn new(inner: T) -> Self { diff --git a/crates/wasmtime/src/runtime/gc/enabled/arrayref.rs b/crates/wasmtime/src/runtime/gc/enabled/arrayref.rs index 22661caea007..14ee5b783856 100644 --- a/crates/wasmtime/src/runtime/gc/enabled/arrayref.rs +++ b/crates/wasmtime/src/runtime/gc/enabled/arrayref.rs @@ -321,10 +321,8 @@ impl ArrayRef { let arrayref = store .gc_store_mut()? .alloc_uninit_array(allocator.type_index(), len, allocator.layout()) - .err2anyhow() .context("unrecoverable error when allocating new `arrayref`")? - .ok_or_else(|| GcHeapOutOfMemory::new(())) - .err2anyhow()?; + .ok_or_else(|| GcHeapOutOfMemory::new(()))?; // From this point on, if we get any errors, then the array is not // fully initialized, so we need to eagerly deallocate it before the diff --git a/crates/wasmtime/src/runtime/gc/enabled/externref.rs b/crates/wasmtime/src/runtime/gc/enabled/externref.rs index 3db2fc5dbdd4..995477f2fa73 100644 --- a/crates/wasmtime/src/runtime/gc/enabled/externref.rs +++ b/crates/wasmtime/src/runtime/gc/enabled/externref.rs @@ -209,10 +209,8 @@ impl ExternRef { let gc_ref = ctx .gc_store_mut()? .alloc_externref(value) - .err2anyhow() .context("unrecoverable error when allocating new `externref`")? .map_err(|x| GcHeapOutOfMemory::::new(*x.downcast().unwrap())) - .err2anyhow() .context("failed to allocate `externref`")?; let mut ctx = AutoAssertNoGc::new(ctx); @@ -320,10 +318,8 @@ impl ExternRef { let gc_ref = ctx .gc_store_mut()? .alloc_externref(value) - .err2anyhow() .context("unrecoverable error when allocating new `externref`")? .map_err(|x| GcHeapOutOfMemory::::new(*x.downcast().unwrap())) - .err2anyhow() .context("failed to allocate `externref`")?; let mut ctx = AutoAssertNoGc::new(ctx); diff --git a/crates/wasmtime/src/runtime/gc/enabled/structref.rs b/crates/wasmtime/src/runtime/gc/enabled/structref.rs index c3171008a152..e111c2f2e633 100644 --- a/crates/wasmtime/src/runtime/gc/enabled/structref.rs +++ b/crates/wasmtime/src/runtime/gc/enabled/structref.rs @@ -269,10 +269,8 @@ impl StructRef { let structref = store .gc_store_mut()? .alloc_uninit_struct(allocator.type_index(), &allocator.layout()) - .err2anyhow() .context("unrecoverable error when allocating new `structref`")? - .ok_or_else(|| GcHeapOutOfMemory::new(())) - .err2anyhow()?; + .ok_or_else(|| GcHeapOutOfMemory::new(()))?; // From this point on, if we get any errors, then the struct is not // fully initialized, so we need to eagerly deallocate it before the diff --git a/crates/wasmtime/src/runtime/linker.rs b/crates/wasmtime/src/runtime/linker.rs index 1bb0d83565ab..95cbb548447b 100644 --- a/crates/wasmtime/src/runtime/linker.rs +++ b/crates/wasmtime/src/runtime/linker.rs @@ -1199,8 +1199,7 @@ impl Linker { let mut imports = module .imports() .map(|import| self._get_by_import(&import)) - .collect::, _>>() - .err2anyhow()?; + .collect::, _>>()?; if let Some(store) = store { for import in imports.iter_mut() { import.update_size(store); @@ -1494,5 +1493,4 @@ impl fmt::Display for UnknownImportError { } } -#[cfg(feature = "std")] -impl std::error::Error for UnknownImportError {} +impl core::error::Error for UnknownImportError {} diff --git a/crates/wasmtime/src/runtime/module.rs b/crates/wasmtime/src/runtime/module.rs index 92450efd5944..9f2c99a540b9 100644 --- a/crates/wasmtime/src/runtime/module.rs +++ b/crates/wasmtime/src/runtime/module.rs @@ -476,7 +476,7 @@ impl Module { // already. let (info, types) = match info_and_types { Some((info, types)) => (info, types), - None => postcard::from_bytes(code_memory.wasmtime_info()).err2anyhow()?, + None => postcard::from_bytes(code_memory.wasmtime_info())?, }; // Register function type signatures into the engine for the lifetime @@ -546,8 +546,8 @@ impl Module { let mut functions = Vec::new(); for payload in Parser::new(0).parse_all(binary) { - let payload = payload.err2anyhow()?; - if let ValidPayload::Func(a, b) = validator.payload(&payload).err2anyhow()? { + let payload = payload?; + if let ValidPayload::Func(a, b) = validator.payload(&payload)? { functions.push((a, b)); } if let wasmparser::Payload::Version { encoding, .. } = &payload { @@ -557,15 +557,13 @@ impl Module { } } - engine - .run_maybe_parallel(functions, |(validator, body)| { - // FIXME: it would be best here to use a rayon-specific parallel - // iterator that maintains state-per-thread to share the function - // validator allocations (`Default::default` here) across multiple - // functions. - validator.into_validator(Default::default()).validate(&body) - }) - .err2anyhow()?; + engine.run_maybe_parallel(functions, |(validator, body)| { + // FIXME: it would be best here to use a rayon-specific parallel + // iterator that maintains state-per-thread to share the function + // validator allocations (`Default::default` here) across multiple + // functions. + validator.into_validator(Default::default()).validate(&body) + })?; Ok(()) } diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs index 810283bd29c4..7651c7900a88 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs @@ -2626,7 +2626,7 @@ unsafe impl crate::runtime::vm::VMStore for StoreInner { fn out_of_gas(&mut self) -> Result<()> { if !self.refuel() { - return Err(Trap::OutOfFuel).err2anyhow(); + return Err(Trap::OutOfFuel.into()); } #[cfg(feature = "async")] if self.fuel_yield_interval.is_some() { @@ -2640,7 +2640,7 @@ unsafe impl crate::runtime::vm::VMStore for StoreInner { // multiple times. let mut behavior = self.epoch_deadline_behavior.take(); let delta_result = match &mut behavior { - None => Err(Trap::Interrupt).err2anyhow(), + None => Err(Trap::Interrupt.into()), Some(callback) => callback((&mut *self).as_context_mut()).and_then(|update| { let delta = match update { UpdateDeadline::Continue(delta) => delta, diff --git a/crates/wasmtime/src/runtime/trap.rs b/crates/wasmtime/src/runtime/trap.rs index 608f055756f6..358a96519abb 100644 --- a/crates/wasmtime/src/runtime/trap.rs +++ b/crates/wasmtime/src/runtime/trap.rs @@ -99,7 +99,7 @@ pub(crate) fn from_runtime_box( faulting_addr, trap, } => { - let mut err: Error = trap.into_anyhow(); + let mut err: Error = trap.into(); // If a fault address was present, for example with segfaults, // then simultaneously assert that it's within a known linear memory @@ -110,7 +110,7 @@ pub(crate) fn from_runtime_box( } (err, Some(pc)) } - crate::runtime::vm::TrapReason::Wasm(trap_code) => (trap_code.into_anyhow(), None), + crate::runtime::vm::TrapReason::Wasm(trap_code) => (trap_code.into(), None), }; if let Some(bt) = backtrace { diff --git a/crates/wasmtime/src/runtime/types.rs b/crates/wasmtime/src/runtime/types.rs index 1fa7743061c3..65a17d6510a4 100644 --- a/crates/wasmtime/src/runtime/types.rs +++ b/crates/wasmtime/src/runtime/types.rs @@ -2629,7 +2629,6 @@ impl MemoryTypeBuilder { let min = self .ty .minimum_byte_size() - .err2anyhow() .context("memory's minimum byte size must fit in a u64")?; if min > absolute_max { bail!("minimum size is too large for this memory type's index type"); diff --git a/crates/wasmtime/src/runtime/vm/byte_count.rs b/crates/wasmtime/src/runtime/vm/byte_count.rs index 4fff11a51ca3..5c963b2faad5 100644 --- a/crates/wasmtime/src/runtime/vm/byte_count.rs +++ b/crates/wasmtime/src/runtime/vm/byte_count.rs @@ -233,8 +233,7 @@ impl fmt::Display for ByteCountNotAligned { } } -#[cfg(feature = "std")] -impl std::error::Error for ByteCountNotAligned {} +impl core::error::Error for ByteCountNotAligned {} #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct ByteCountOutOfBounds(ByteCountOutOfBoundsKind); @@ -245,8 +244,7 @@ impl fmt::Display for ByteCountOutOfBounds { } } -#[cfg(feature = "std")] -impl std::error::Error for ByteCountOutOfBounds {} +impl core::error::Error for ByteCountOutOfBounds {} #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum ByteCountOutOfBoundsKind { diff --git a/crates/wasmtime/src/runtime/vm/component/libcalls.rs b/crates/wasmtime/src/runtime/vm/component/libcalls.rs index 7135524bf0bf..31671f5fe6a6 100644 --- a/crates/wasmtime/src/runtime/vm/component/libcalls.rs +++ b/crates/wasmtime/src/runtime/vm/component/libcalls.rs @@ -566,5 +566,5 @@ unsafe fn resource_exit_call(vmctx: *mut VMComponentContext) -> Result<()> { } unsafe fn trap(_vmctx: *mut VMComponentContext, code: u8) -> Result<()> { - Err(wasmtime_environ::Trap::from_u8(code).unwrap()).err2anyhow() + Err(wasmtime_environ::Trap::from_u8(code).unwrap().into()) } diff --git a/crates/wasmtime/src/runtime/vm/cow.rs b/crates/wasmtime/src/runtime/vm/cow.rs index d2ff38aa8134..37ba1864c140 100644 --- a/crates/wasmtime/src/runtime/vm/cow.rs +++ b/crates/wasmtime/src/runtime/vm/cow.rs @@ -119,7 +119,7 @@ impl MemoryImage { // If `mmap` doesn't come from a file then platform-specific mechanisms // may be used to place the data in a form that's amenable to an mmap. - if let Some(source) = MemoryImageSource::from_data(data).err2anyhow()? { + if let Some(source) = MemoryImageSource::from_data(data)? { return Ok(Some(MemoryImage { source, source_offset: 0, @@ -132,23 +132,19 @@ impl MemoryImage { } unsafe fn map_at(&self, base: *mut u8) -> Result<()> { - self.source - .map_at( - base.add(self.linear_memory_offset.byte_count()), - self.len.byte_count(), - self.source_offset, - ) - .err2anyhow()?; + self.source.map_at( + base.add(self.linear_memory_offset.byte_count()), + self.len.byte_count(), + self.source_offset, + )?; Ok(()) } unsafe fn remap_as_zeros_at(&self, base: *mut u8) -> Result<()> { - self.source - .remap_as_zeros_at( - base.add(self.linear_memory_offset.byte_count()), - self.len.byte_count(), - ) - .err2anyhow()?; + self.source.remap_as_zeros_at( + base.add(self.linear_memory_offset.byte_count()), + self.len.byte_count(), + )?; Ok(()) } } @@ -364,7 +360,7 @@ impl MemoryImageSlot { } pub(crate) fn set_heap_limit(&mut self, size_bytes: usize) -> Result<()> { - let size_bytes_aligned = HostAlignedByteCount::new_rounded_up(size_bytes).err2anyhow()?; + let size_bytes_aligned = HostAlignedByteCount::new_rounded_up(size_bytes)?; assert!(size_bytes <= self.static_size); assert!(size_bytes_aligned.byte_count() <= self.static_size); @@ -414,7 +410,7 @@ impl MemoryImageSlot { assert!(!self.dirty); assert!(initial_size_bytes <= self.static_size); let initial_size_bytes_page_aligned = - HostAlignedByteCount::new_rounded_up(initial_size_bytes).err2anyhow()?; + HostAlignedByteCount::new_rounded_up(initial_size_bytes)?; // First order of business is to blow away the previous linear memory // image if it doesn't match the image specified here. If one is @@ -707,9 +703,9 @@ impl MemoryImageSlot { unsafe { let start = self.base.as_ptr().add(range.start.byte_count()); if readwrite { - vm::expose_existing_mapping(start, len.byte_count()).err2anyhow()?; + vm::expose_existing_mapping(start, len.byte_count())?; } else { - vm::hide_existing_mapping(start, len.byte_count()).err2anyhow()?; + vm::hide_existing_mapping(start, len.byte_count())?; } } @@ -735,7 +731,7 @@ impl MemoryImageSlot { } unsafe { - vm::erase_existing_mapping(self.base.as_ptr(), self.static_size).err2anyhow()?; + vm::erase_existing_mapping(self.base.as_ptr(), self.static_size)?; } self.image = None; diff --git a/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs b/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs index fb6f81c71adf..9ac172a52bf9 100644 --- a/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs +++ b/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs @@ -550,7 +550,7 @@ unsafe impl GcHeap for DrcHeap { let size = u32::try_from(layout.size()).unwrap(); if !VMGcKind::value_fits_in_unused_bits(size) { - return Err(crate::Trap::AllocationTooLarge.into_anyhow()); + return Err(crate::Trap::AllocationTooLarge.into()); } let gc_ref = match self.free_list.alloc(layout)? { diff --git a/crates/wasmtime/src/runtime/vm/gc/enabled/free_list.rs b/crates/wasmtime/src/runtime/vm/gc/enabled/free_list.rs index bc79d1c15b83..e1d2a3f923e6 100644 --- a/crates/wasmtime/src/runtime/vm/gc/enabled/free_list.rs +++ b/crates/wasmtime/src/runtime/vm/gc/enabled/free_list.rs @@ -60,7 +60,6 @@ impl FreeList { ); let alloc_size = u32::try_from(layout.size()) - .err2anyhow() .context("requested allocation's size does not fit in a u32")?; alloc_size .checked_next_multiple_of(ALIGN_U32) diff --git a/crates/wasmtime/src/runtime/vm/gc/enabled/null.rs b/crates/wasmtime/src/runtime/vm/gc/enabled/null.rs index a423bccb1537..776b3aabd1fb 100644 --- a/crates/wasmtime/src/runtime/vm/gc/enabled/null.rs +++ b/crates/wasmtime/src/runtime/vm/gc/enabled/null.rs @@ -111,7 +111,7 @@ impl VMNullExternRef { } fn oom() -> Error { - GcHeapOutOfMemory::new(()).into_anyhow() + GcHeapOutOfMemory::new(()).into() } impl NullHeap { @@ -144,7 +144,7 @@ impl NullHeap { } }) { Some(size) => size, - None => return Err(crate::Trap::AllocationTooLarge.into_anyhow()), + None => return Err(crate::Trap::AllocationTooLarge.into()), }; let next = *self.next.get_mut(); diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator.rs b/crates/wasmtime/src/runtime/vm/instance/allocator.rs index 7e32791f515e..1f3ee06ccfab 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator.rs @@ -583,7 +583,7 @@ fn initialize_tables( let gc_store = store.gc_store_mut()?; let items = (0..table.size()) .map(|_| gc_ref.as_ref().map(|r| gc_store.clone_gc_ref(r))); - table.init_gc_refs(0, items).err2anyhow()?; + table.init_gc_refs(0, items)?; } WasmHeapTopType::Any => { @@ -591,13 +591,13 @@ fn initialize_tables( let gc_store = store.gc_store_mut()?; let items = (0..table.size()) .map(|_| gc_ref.as_ref().map(|r| gc_store.clone_gc_ref(r))); - table.init_gc_refs(0, items).err2anyhow()?; + table.init_gc_refs(0, items)?; } WasmHeapTopType::Func => { let funcref = NonNull::new(raw.get_funcref().cast::()); let items = (0..table.size()).map(|_| funcref); - table.init_func(0, items).err2anyhow()?; + table.init_func(0, items)?; } } } @@ -617,18 +617,15 @@ fn initialize_tables( .eval(store, context, &segment.offset) .expect("const expression should be valid") }; - context - .instance - .table_init_segment( - store, - const_evaluator, - segment.table_index, - &segment.elements, - start.get_u64(), - 0, - segment.elements.len(), - ) - .err2anyhow()?; + context.instance.table_init_segment( + store, + const_evaluator, + segment.table_index, + &segment.elements, + start.get_u64(), + 0, + segment.elements.len(), + )?; } Ok(()) @@ -762,7 +759,7 @@ fn initialize_memories( const_evaluator, }); if !ok { - return Err(Trap::MemoryOutOfBounds).err2anyhow(); + return Err(Trap::MemoryOutOfBounds.into()); } Ok(()) 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 5c60deeea744..7510d56b17bb 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 @@ -34,15 +34,13 @@ impl TablePool { mem::size_of::<*mut u8>() .checked_mul(config.limits.table_elements) .ok_or_else(|| anyhow!("table size exceeds addressable memory"))?, - ) - .err2anyhow()?; + )?; let max_total_tables = usize::try_from(config.limits.total_tables).unwrap(); let tables_per_instance = usize::try_from(config.limits.max_tables_per_module).unwrap(); let allocation_size = table_size .checked_mul(max_total_tables) - .err2anyhow() .context("total size of tables exceeds addressable memory")?; let mapping = Mmap::accessible_reserved(allocation_size, allocation_size) 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 c443adb228a9..c4ef3fd91bd1 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 @@ -40,7 +40,6 @@ impl StackPool { } else { HostAlignedByteCount::new_rounded_up(config.stack_size) .and_then(|size| size.checked_add(HostAlignedByteCount::host_page_size())) - .err2anyhow() .context("stack size exceeds addressable memory")? }; @@ -48,7 +47,6 @@ impl StackPool { let allocation_size = stack_size .checked_mul(max_stacks) - .err2anyhow() .context("total size of execution stacks exceeds addressable memory")?; let mapping = Mmap::accessible_reserved(allocation_size, allocation_size) diff --git a/crates/wasmtime/src/runtime/vm/libcalls.rs b/crates/wasmtime/src/runtime/vm/libcalls.rs index f7f3728d9239..e048c24387a8 100644 --- a/crates/wasmtime/src/runtime/vm/libcalls.rs +++ b/crates/wasmtime/src/runtime/vm/libcalls.rs @@ -281,9 +281,7 @@ unsafe fn table_fill_func_ref( match table.element_type() { TableElementType::Func => { let val = NonNull::new(val.cast::()); - table - .fill(store.optional_gc_store_mut()?, dst, val.into(), len) - .err2anyhow()?; + table.fill(store.optional_gc_store_mut()?, dst, val.into(), len)?; Ok(()) } TableElementType::GcRef => unreachable!(), @@ -307,9 +305,7 @@ unsafe fn table_fill_gc_ref( let gc_store = store.store_opaque_mut().unwrap_gc_store_mut(); let gc_ref = VMGcRef::from_raw_u32(val); let gc_ref = gc_ref.map(|r| gc_store.clone_gc_ref(&r)); - table - .fill(Some(gc_store), dst, gc_ref.into(), len) - .err2anyhow()?; + table.fill(Some(gc_store), dst, gc_ref.into(), len)?; Ok(()) } } @@ -333,7 +329,7 @@ unsafe fn table_copy( let src_range = src..(src.checked_add(len).unwrap_or(u64::MAX)); let src_table = instance.get_table_with_lazy_init(src_table_index, src_range); let gc_store = store.optional_gc_store_mut()?; - Table::copy(gc_store, dst_table, src_table, dst, src, len).err2anyhow()?; + Table::copy(gc_store, dst_table, src_table, dst, src, len)?; Ok(()) } @@ -540,8 +536,7 @@ unsafe fn gc_alloc_raw( store .unwrap_gc_store_mut() .alloc_raw(header, layout)? - .ok_or_else(|| GcHeapOutOfMemory::new(())) - .err2anyhow()? + .ok_or_else(|| GcHeapOutOfMemory::new(()))? } }; @@ -634,15 +629,15 @@ unsafe fn array_new_data( let byte_len = len .checked_mul(one_elem_size) .and_then(|x| usize::try_from(x).ok()) - .ok_or_else(|| Trap::MemoryOutOfBounds.into_anyhow())?; + .ok_or_else(|| Trap::MemoryOutOfBounds)?; // Get the data from the segment, checking bounds. - let src = usize::try_from(src).map_err(|_| Trap::MemoryOutOfBounds.into_anyhow())?; + let src = usize::try_from(src).map_err(|_| Trap::MemoryOutOfBounds)?; let data = instance .wasm_data(data_range) .get(src..) .and_then(|d| d.get(..byte_len)) - .ok_or_else(|| Trap::MemoryOutOfBounds.into_anyhow())?; + .ok_or_else(|| Trap::MemoryOutOfBounds)?; // Allocate the (uninitialized) array. let gc_layout = store @@ -666,7 +661,7 @@ unsafe fn array_new_data( .store_opaque_mut() .unwrap_gc_store_mut() .alloc_uninit_array(shared_ty, u32::try_from(byte_len).unwrap(), &array_layout)? - .ok_or_else(|| GcHeapOutOfMemory::new(()).into_anyhow())? + .ok_or_else(|| GcHeapOutOfMemory::new(()))? } }; @@ -709,24 +704,20 @@ unsafe fn array_init_data( ); // Null check the array. - let gc_ref = VMGcRef::from_raw_u32(array).ok_or_else(|| Trap::NullReference.into_anyhow())?; + let gc_ref = VMGcRef::from_raw_u32(array).ok_or_else(|| Trap::NullReference)?; let array = gc_ref .into_arrayref(&*store.unwrap_gc_store().gc_heap) .expect("gc ref should be an array"); - let dst = usize::try_from(dst).map_err(|_| Trap::MemoryOutOfBounds.into_anyhow())?; - let src = usize::try_from(src).map_err(|_| Trap::MemoryOutOfBounds.into_anyhow())?; - let len = usize::try_from(len).map_err(|_| Trap::MemoryOutOfBounds.into_anyhow())?; + let dst = usize::try_from(dst).map_err(|_| Trap::MemoryOutOfBounds)?; + let src = usize::try_from(src).map_err(|_| Trap::MemoryOutOfBounds)?; + let len = usize::try_from(len).map_err(|_| Trap::MemoryOutOfBounds)?; // Bounds check the array. let array_len = array.len(store.store_opaque()); - let array_len = usize::try_from(array_len).map_err(|_| Trap::ArrayOutOfBounds.into_anyhow())?; - if dst - .checked_add(len) - .ok_or_else(|| Trap::ArrayOutOfBounds.into_anyhow())? - > array_len - { - return Err(Trap::ArrayOutOfBounds.into_anyhow()); + let array_len = usize::try_from(array_len).map_err(|_| Trap::ArrayOutOfBounds)?; + if dst.checked_add(len).ok_or_else(|| Trap::ArrayOutOfBounds)? > array_len { + return Err(Trap::ArrayOutOfBounds.into()); } // Calculate the byte length from the array length. @@ -738,7 +729,7 @@ unsafe fn array_init_data( .expect("Wasm validation ensures that this type have a defined byte size"); let data_len = len .checked_mul(usize::try_from(one_elem_size).unwrap()) - .ok_or_else(|| Trap::MemoryOutOfBounds.into_anyhow())?; + .ok_or_else(|| Trap::MemoryOutOfBounds)?; // Get the data from the segment, checking its bounds. let data_range = instance.wasm_data_range(data_index); @@ -746,7 +737,7 @@ unsafe fn array_init_data( .wasm_data(data_range) .get(src..) .and_then(|d| d.get(..data_len)) - .ok_or_else(|| Trap::MemoryOutOfBounds.into_anyhow())?; + .ok_or_else(|| Trap::MemoryOutOfBounds)?; // Copy the data into the array. @@ -795,8 +786,8 @@ unsafe fn array_new_elem( let mut storage = None; let elements = instance.passive_element_segment(&mut storage, elem_index); - let src = usize::try_from(src).map_err(|_| Trap::TableOutOfBounds.into_anyhow())?; - let len = usize::try_from(len).map_err(|_| Trap::TableOutOfBounds.into_anyhow())?; + let src = usize::try_from(src).map_err(|_| Trap::TableOutOfBounds)?; + let len = usize::try_from(len).map_err(|_| Trap::TableOutOfBounds)?; let shared_ty = instance.engine_type_index(array_type_index); let array_ty = ArrayType::from_shared_type_index(store.engine(), shared_ty); @@ -811,7 +802,7 @@ unsafe fn array_new_elem( vals.extend( fs.get(src..) .and_then(|s| s.get(..len)) - .ok_or_else(|| Trap::TableOutOfBounds.into_anyhow())? + .ok_or_else(|| Trap::TableOutOfBounds)? .iter() .map(|f| { let raw_func_ref = instance.get_func_ref(*f); @@ -824,7 +815,7 @@ unsafe fn array_new_elem( let xs = xs .get(src..) .and_then(|s| s.get(..len)) - .ok_or_else(|| Trap::TableOutOfBounds.into_anyhow())?; + .ok_or_else(|| Trap::TableOutOfBounds)?; let mut const_context = ConstEvalContext::new(instance); let mut const_evaluator = ConstExprEvaluator::default(); @@ -887,7 +878,7 @@ unsafe fn array_init_elem( ); // Convert the raw GC ref into a `Rooted`. - let array = VMGcRef::from_raw_u32(array).ok_or_else(|| Trap::NullReference.into_anyhow())?; + let array = VMGcRef::from_raw_u32(array).ok_or_else(|| Trap::NullReference)?; let array = store.unwrap_gc_store_mut().clone_gc_ref(&array); let array = { let mut no_gc = AutoAssertNoGc::new(&mut store); @@ -897,12 +888,8 @@ unsafe fn array_init_elem( // Bounds check the destination within the array. let array_len = array._len(&store)?; log::trace!("array_len = {array_len}"); - if dst - .checked_add(len) - .ok_or_else(|| Trap::ArrayOutOfBounds.into_anyhow())? - > array_len - { - return Err(Trap::ArrayOutOfBounds.into_anyhow()); + if dst.checked_add(len).ok_or_else(|| Trap::ArrayOutOfBounds)? > array_len { + return Err(Trap::ArrayOutOfBounds.into()); } // Get the passive element segment. @@ -910,15 +897,15 @@ unsafe fn array_init_elem( let elements = instance.passive_element_segment(&mut storage, elem_index); // Convert array offsets into `usize`s. - let src = usize::try_from(src).map_err(|_| Trap::TableOutOfBounds.into_anyhow())?; - let len = usize::try_from(len).map_err(|_| Trap::TableOutOfBounds.into_anyhow())?; + let src = usize::try_from(src).map_err(|_| Trap::TableOutOfBounds)?; + let len = usize::try_from(len).map_err(|_| Trap::TableOutOfBounds)?; // Turn the elements into `Val`s. let vals = match elements { TableSegmentElements::Functions(fs) => fs .get(src..) .and_then(|s| s.get(..len)) - .ok_or_else(|| Trap::TableOutOfBounds.into_anyhow())? + .ok_or_else(|| Trap::TableOutOfBounds)? .iter() .map(|f| { let raw_func_ref = instance.get_func_ref(*f); @@ -935,7 +922,7 @@ unsafe fn array_init_elem( xs.get(src..) .and_then(|s| s.get(..len)) - .ok_or_else(|| Trap::TableOutOfBounds.into_anyhow())? + .ok_or_else(|| Trap::TableOutOfBounds)? .iter() .map(|x| unsafe { let raw = const_evaluator @@ -982,33 +969,23 @@ unsafe fn array_copy( let mut store = AutoAssertNoGc::new(&mut store); // Convert the raw GC refs into `Rooted`s. - let dst_array = - VMGcRef::from_raw_u32(dst_array).ok_or_else(|| Trap::NullReference.into_anyhow())?; + let dst_array = VMGcRef::from_raw_u32(dst_array).ok_or_else(|| Trap::NullReference)?; let dst_array = store.unwrap_gc_store_mut().clone_gc_ref(&dst_array); let dst_array = ArrayRef::from_cloned_gc_ref(&mut store, dst_array); - let src_array = - VMGcRef::from_raw_u32(src_array).ok_or_else(|| Trap::NullReference.into_anyhow())?; + let src_array = VMGcRef::from_raw_u32(src_array).ok_or_else(|| Trap::NullReference)?; let src_array = store.unwrap_gc_store_mut().clone_gc_ref(&src_array); let src_array = ArrayRef::from_cloned_gc_ref(&mut store, src_array); // Bounds check the destination array's elements. let dst_array_len = dst_array._len(&store)?; - if dst - .checked_add(len) - .ok_or_else(|| Trap::ArrayOutOfBounds.into_anyhow())? - > dst_array_len - { - return Err(Trap::ArrayOutOfBounds.into_anyhow()); + if dst.checked_add(len).ok_or_else(|| Trap::ArrayOutOfBounds)? > dst_array_len { + return Err(Trap::ArrayOutOfBounds.into()); } // Bounds check the source array's elements. let src_array_len = src_array._len(&store)?; - if src - .checked_add(len) - .ok_or_else(|| Trap::ArrayOutOfBounds.into_anyhow())? - > src_array_len - { - return Err(Trap::ArrayOutOfBounds.into_anyhow()); + if src.checked_add(len).ok_or_else(|| Trap::ArrayOutOfBounds)? > src_array_len { + return Err(Trap::ArrayOutOfBounds.into()); } let mut store = AutoAssertNoGc::new(&mut store); diff --git a/crates/wasmtime/src/runtime/vm/memory/malloc.rs b/crates/wasmtime/src/runtime/vm/memory/malloc.rs index 95378ee3c604..b822a376acc3 100644 --- a/crates/wasmtime/src/runtime/vm/memory/malloc.rs +++ b/crates/wasmtime/src/runtime/vm/memory/malloc.rs @@ -39,17 +39,12 @@ impl MallocMemory { } let initial_allocation_byte_size = minimum - .checked_add( - tunables - .memory_reservation_for_growth - .try_into() - .err2anyhow()?, - ) + .checked_add(tunables.memory_reservation_for_growth.try_into()?) .context("memory allocation size too large")?; let initial_allocation_len = byte_size_to_element_len(initial_allocation_byte_size); let mut storage = Vec::new(); - storage.try_reserve(initial_allocation_len).err2anyhow()?; + storage.try_reserve(initial_allocation_len)?; let initial_len = byte_size_to_element_len(minimum); if initial_len > 0 { @@ -76,8 +71,7 @@ impl RuntimeLinearMemory for MallocMemory { let new_element_len = byte_size_to_element_len(new_size); if new_element_len > self.storage.len() { self.storage - .try_reserve(new_element_len - self.storage.len()) - .err2anyhow()?; + .try_reserve(new_element_len - self.storage.len())?; grow_storage_to(&mut self.storage, new_element_len); self.base_ptr = SendSyncPtr::new(NonNull::new(self.storage.as_mut_ptr()).unwrap()).cast(); diff --git a/crates/wasmtime/src/runtime/vm/memory/mmap.rs b/crates/wasmtime/src/runtime/vm/memory/mmap.rs index de95793032ad..0d536d1d2737 100644 --- a/crates/wasmtime/src/runtime/vm/memory/mmap.rs +++ b/crates/wasmtime/src/runtime/vm/memory/mmap.rs @@ -59,7 +59,6 @@ impl MmapMemory { // Also be sure to round up to the host page size for this value. let offset_guard_bytes = HostAlignedByteCount::new_rounded_up_u64(tunables.memory_guard_size) - .err2anyhow() .context("tunable.memory_guard_size overflows")?; let pre_guard_bytes = if tunables.guard_before_linear_memory { offset_guard_bytes @@ -93,23 +92,20 @@ impl MmapMemory { // Convert `alloc_bytes` and `extra_to_reserve_on_growth` to // page-aligned `usize` values. let alloc_bytes = HostAlignedByteCount::new_rounded_up_u64(alloc_bytes) - .err2anyhow() .context("tunables.memory_reservation overflows")?; let extra_to_reserve_on_growth = HostAlignedByteCount::new_rounded_up_u64(extra_to_reserve_on_growth) - .err2anyhow() .context("tunables.memory_reservation_for_growth overflows")?; let request_bytes = pre_guard_bytes .checked_add(alloc_bytes) .and_then(|i| i.checked_add(offset_guard_bytes)) - .err2anyhow() .with_context(|| format!("cannot allocate {minimum} with guard regions"))?; let mmap = Mmap::accessible_reserved(HostAlignedByteCount::ZERO, request_bytes)?; if minimum > 0 { - let accessible = HostAlignedByteCount::new_rounded_up(minimum).err2anyhow()?; + let accessible = HostAlignedByteCount::new_rounded_up(minimum)?; // SAFETY: mmap is not in use right now so it's safe to make it accessible. unsafe { mmap.make_accessible(pre_guard_bytes, accessible)?; @@ -156,7 +152,7 @@ impl RuntimeLinearMemory for MmapMemory { } fn grow_to(&mut self, new_size: usize) -> Result<()> { - let new_accessible = HostAlignedByteCount::new_rounded_up(new_size).err2anyhow()?; + let new_accessible = HostAlignedByteCount::new_rounded_up(new_size)?; let current_capacity = self.current_capacity(); if new_accessible > current_capacity { // If the new size of this heap exceeds the current size of the @@ -168,7 +164,6 @@ impl RuntimeLinearMemory for MmapMemory { .checked_add(new_accessible) .and_then(|s| s.checked_add(self.extra_to_reserve_on_growth)) .and_then(|s| s.checked_add(self.offset_guard_size)) - .err2anyhow() .context("overflow calculating size of memory allocation")?; let mut new_mmap = @@ -212,7 +207,6 @@ impl RuntimeLinearMemory for MmapMemory { self.mmap.make_accessible( self.pre_guard_size .checked_add(self.accessible()) - .err2anyhow() .context("overflow calculating new accessible region")?, difference, )?; diff --git a/crates/wasmtime/src/runtime/vm/mmap.rs b/crates/wasmtime/src/runtime/vm/mmap.rs index a6b76c67db35..c16ec11e812f 100644 --- a/crates/wasmtime/src/runtime/vm/mmap.rs +++ b/crates/wasmtime/src/runtime/vm/mmap.rs @@ -63,7 +63,7 @@ impl Mmap { /// Create a new `Mmap` pointing to at least `size` bytes of page-aligned /// accessible memory. pub fn with_at_least(size: usize) -> Result { - let rounded_size = HostAlignedByteCount::new_rounded_up(size).err2anyhow()?; + let rounded_size = HostAlignedByteCount::new_rounded_up(size)?; Self::accessible_reserved(rounded_size, rounded_size) } diff --git a/crates/wasmtime/src/runtime/vm/sys/unix/mmap.rs b/crates/wasmtime/src/runtime/vm/sys/unix/mmap.rs index a711089510eb..50512070d7b5 100644 --- a/crates/wasmtime/src/runtime/vm/sys/unix/mmap.rs +++ b/crates/wasmtime/src/runtime/vm/sys/unix/mmap.rs @@ -9,7 +9,7 @@ use std::{fs::File, path::Path}; /// Open a file so that it can be mmap'd for executing. #[cfg(feature = "std")] pub fn open_file_for_mmap(path: &Path) -> Result { - File::open(path).err2anyhow().context("failed to open file") + File::open(path).context("failed to open file") } #[derive(Debug)] @@ -48,8 +48,7 @@ impl Mmap { size.byte_count(), rustix::mm::ProtFlags::READ | rustix::mm::ProtFlags::WRITE, rustix::mm::MapFlags::PRIVATE | MMAP_NORESERVE_FLAG, - ) - .err2anyhow()? + )? }; let memory = std::ptr::slice_from_raw_parts_mut(ptr.cast(), size.byte_count()); let memory = SendSyncPtr::new(NonNull::new(memory).unwrap()); @@ -74,8 +73,7 @@ impl Mmap { // Virtual memory that cannot be accessed should not have a backing store reserved // for it. Hence, passing in NORESERVE is correct here. rustix::mm::MapFlags::PRIVATE | MMAP_NORESERVE_FLAG, - ) - .err2anyhow()? + )? }; let memory = std::ptr::slice_from_raw_parts_mut(ptr.cast(), size.byte_count()); @@ -87,7 +85,6 @@ impl Mmap { pub fn from_file(file: &File) -> Result { let len = file .metadata() - .err2anyhow() .context("failed to get file metadata")? .len(); let len = usize::try_from(len).map_err(|_| anyhow::anyhow!("file too large to map"))?; @@ -100,7 +97,6 @@ impl Mmap { &file, 0, ) - .err2anyhow() .context(format!("mmap failed to allocate {len:#x} bytes"))? }; let memory = std::ptr::slice_from_raw_parts_mut(ptr.cast(), len); @@ -120,8 +116,7 @@ impl Mmap { ptr.byte_add(start.byte_count()).cast(), len.byte_count(), MprotectFlags::READ | MprotectFlags::WRITE, - ) - .err2anyhow()?; + )?; } Ok(()) @@ -168,7 +163,7 @@ impl Mmap { flags }; - mprotect(base, len, flags).err2anyhow()?; + mprotect(base, len, flags)?; Ok(()) } @@ -177,7 +172,7 @@ impl Mmap { let base = self.memory.as_ptr().byte_add(range.start).cast(); let len = range.end - range.start; - mprotect(base, len, MprotectFlags::READ).err2anyhow()?; + mprotect(base, len, MprotectFlags::READ)?; Ok(()) } diff --git a/crates/wasmtime/src/runtime/vm/sys/unix/vm.rs b/crates/wasmtime/src/runtime/vm/sys/unix/vm.rs index 0f3114bfdf78..6d457ba5f191 100644 --- a/crates/wasmtime/src/runtime/vm/sys/unix/vm.rs +++ b/crates/wasmtime/src/runtime/vm/sys/unix/vm.rs @@ -102,7 +102,6 @@ impl MemoryImageSource { // in-memory file to represent the heap image. This anonymous // file is then used as the basis for further mmaps. - use crate::prelude::*; use std::io::{ErrorKind, Write}; // Create the memfd. It needs a name, but the documentation for @@ -118,9 +117,9 @@ impl MemoryImageSource { Err(memfd::Error::Create(err)) if err.kind() == ErrorKind::Unsupported => { return Ok(None) } - Err(e) => return Err(e.into_anyhow()), + Err(e) => return Err(e.into()), }; - memfd.as_file().write_all(data).err2anyhow()?; + memfd.as_file().write_all(data)?; // Seal the memfd's data and length. // @@ -137,14 +136,12 @@ impl MemoryImageSource { // extra-super-sure that it never changes, and because // this costs very little, we use the kernel's "seal" API // to make the memfd image permanently read-only. - memfd - .add_seals(&[ - memfd::FileSeal::SealGrow, - memfd::FileSeal::SealShrink, - memfd::FileSeal::SealWrite, - memfd::FileSeal::SealSeal, - ]) - .err2anyhow()?; + memfd.add_seals(&[ + memfd::FileSeal::SealGrow, + memfd::FileSeal::SealShrink, + memfd::FileSeal::SealWrite, + memfd::FileSeal::SealSeal, + ])?; Ok(Some(MemoryImageSource::Memfd(memfd))) } diff --git a/crates/wasmtime/src/runtime/vm/sys/windows/mmap.rs b/crates/wasmtime/src/runtime/vm/sys/windows/mmap.rs index 91e58fbbabe5..9f23e0f2066d 100644 --- a/crates/wasmtime/src/runtime/vm/sys/windows/mmap.rs +++ b/crates/wasmtime/src/runtime/vm/sys/windows/mmap.rs @@ -22,7 +22,6 @@ pub fn open_file_for_mmap(path: &Path) -> Result { .access_mode(FILE_GENERIC_READ | FILE_GENERIC_EXECUTE) .share_mode(FILE_SHARE_READ) .open(path) - .err2anyhow() .context("failed to open file") } @@ -85,7 +84,6 @@ impl Mmap { unsafe { let len = file .metadata() - .err2anyhow() .context("failed to get file metadata")? .len(); let len = usize::try_from(len).map_err(|_| anyhow!("file too large to map"))?; @@ -105,8 +103,7 @@ impl Mmap { ptr::null(), ); if mapping == INVALID_HANDLE_VALUE { - return Err(io::Error::last_os_error().into_anyhow()) - .context("failed to create file mapping"); + return Err(io::Error::last_os_error()).context("failed to create file mapping"); } // Create a view for the entire file using all our requisite @@ -123,8 +120,7 @@ impl Mmap { let err = io::Error::last_os_error(); CloseHandle(mapping); if ptr.is_null() { - return Err(err.into_anyhow()) - .context(format!("failed to create map view of {:#x} bytes", len)); + return Err(err).context(format!("failed to create map view of {:#x} bytes", len)); } let memory = std::ptr::slice_from_raw_parts_mut(ptr.cast(), len); @@ -138,7 +134,7 @@ impl Mmap { // remove the execute bit) let mut old = 0; if VirtualProtect(ret.as_mut_ptr().cast(), ret.len(), PAGE_WRITECOPY, &mut old) == 0 { - return Err(io::Error::last_os_error().into_anyhow()) + return Err(io::Error::last_os_error()) .context("failed change pages to `PAGE_READONLY`"); } diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index b0c24e598424..0235a67f4f16 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -2354,6 +2354,12 @@ No `unsafe` code in this update. Lots of changes but all object-file-format-related, everything looks good. """ +[[audits.object]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.36.0 -> 0.36.5" +notes = "No new unsafe code, lots of new relocations/objects support, everything looks nominal" + [[audits.once_cell]] who = "Chris Fallin " criteria = "safe-to-deploy" @@ -3939,7 +3945,7 @@ end = "2025-09-20" criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-10-05" -end = "2024-09-01" +end = "2025-12-02" [[trusted.async-trait]] criteria = "safe-to-deploy" @@ -4281,13 +4287,13 @@ end = "2024-07-06" criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-03-01" -end = "2024-07-06" +end = "2025-12-02" [[trusted.serde_derive]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-03-01" -end = "2024-07-06" +end = "2025-12-02" [[trusted.serde_json]] criteria = "safe-to-deploy" @@ -4305,7 +4311,7 @@ end = "2025-02-12" criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-03-01" -end = "2024-07-06" +end = "2025-12-02" [[trusted.system-interface]] criteria = "safe-to-deploy" diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index cb0cbaa3cd7a..df1c28beda17 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -236,8 +236,8 @@ user-login = "epage" user-name = "Ed Page" [[publisher.anyhow]] -version = "1.0.75" -when = "2023-08-17" +version = "1.0.93" +when = "2024-11-06" user-id = 3618 user-login = "dtolnay" user-name = "David Tolnay" @@ -660,8 +660,8 @@ user-login = "dtolnay" user-name = "David Tolnay" [[publisher.proc-macro2]] -version = "1.0.81" -when = "2024-04-17" +version = "1.0.92" +when = "2024-11-21" user-id = 3618 user-login = "dtolnay" user-name = "David Tolnay" @@ -750,15 +750,15 @@ user-login = "BurntSushi" user-name = "Andrew Gallant" [[publisher.serde]] -version = "1.0.188" -when = "2023-08-26" +version = "1.0.215" +when = "2024-11-11" user-id = 3618 user-login = "dtolnay" user-name = "David Tolnay" [[publisher.serde_derive]] -version = "1.0.188" -when = "2023-08-26" +version = "1.0.215" +when = "2024-11-11" user-id = 3618 user-login = "dtolnay" user-name = "David Tolnay" @@ -791,8 +791,8 @@ user-login = "dtolnay" user-name = "David Tolnay" [[publisher.syn]] -version = "2.0.60" -when = "2024-04-17" +version = "2.0.90" +when = "2024-11-29" user-id = 3618 user-login = "dtolnay" user-name = "David Tolnay" From 75a4d27932c1e84b153bf45b684d6d1247808366 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Dec 2024 11:32:25 -0700 Subject: [PATCH 05/21] pulley: Implement `get_frame_pointer` (#9658) * pulley: Implement `get_frame_pointer` This commit implements the CLIF `get_frame_pointer` instruction which will be needed by trampolines in Wasmtime. This is implemented by generalizing the preexisting `GetSp` `MInst` into a "get special". This the additionally removes the extended `get_sp` opcode in Pulley as it's not necessary as `xmov` can operate on this register. * Review comments --- .../codegen/src/isa/pulley_shared/inst.isle | 23 ++++-- .../src/isa/pulley_shared/inst/args.rs | 14 ++++ .../src/isa/pulley_shared/inst/emit.rs | 2 +- .../codegen/src/isa/pulley_shared/inst/mod.rs | 11 ++- .../codegen/src/isa/pulley_shared/lower.isle | 7 +- .../src/isa/pulley_shared/lower/isle.rs | 9 +++ .../isa/pulley32/get_stack_pointer.clif | 18 ----- .../filetests/isa/pulley32/special_regs.clif | 70 +++++++++++++++++++ .../isa/pulley64/get_stack_pointer.clif | 18 ----- .../filetests/isa/pulley64/special_regs.clif | 70 +++++++++++++++++++ pulley/fuzz/src/interp.rs | 1 - pulley/src/interp.rs | 6 -- pulley/src/lib.rs | 2 - 13 files changed, 194 insertions(+), 57 deletions(-) delete mode 100644 cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif create mode 100644 cranelift/filetests/filetests/isa/pulley32/special_regs.clif delete mode 100644 cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif create mode 100644 cranelift/filetests/filetests/isa/pulley64/special_regs.clif diff --git a/cranelift/codegen/src/isa/pulley_shared/inst.isle b/cranelift/codegen/src/isa/pulley_shared/inst.isle index 2ad356f622fd..6ad0c4998931 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst.isle +++ b/cranelift/codegen/src/isa/pulley_shared/inst.isle @@ -39,8 +39,11 @@ ;; Nothing. (Nop) - ;; Get the stack pointer. - (GetSp (dst WritableXReg)) + ;; Move a special register (e.g. sp, fp, lr, etc) in to a general-purpose + ;; register. + (GetSpecial + (dst WritableXReg) + (reg XReg)) ;; Return. (Ret) @@ -378,11 +381,17 @@ (rule (pulley_trap_if cond size src1 src2 code) (SideEffectNoResult.Inst (MInst.TrapIf cond size src1 src2 code))) -(decl pulley_get_sp () XReg) -(rule (pulley_get_sp) - (let ((reg WritableXReg (temp_writable_xreg)) - (_ Unit (emit (MInst.GetSp reg)))) - reg)) +(decl sp_reg () XReg) +(extern constructor sp_reg sp_reg) + +(decl fp_reg () XReg) +(extern constructor fp_reg fp_reg) + +(decl pulley_get_special (XReg) XReg) +(rule (pulley_get_special reg) + (let ((dst WritableXReg (temp_writable_xreg)) + (_ Unit (emit (MInst.GetSpecial dst reg)))) + dst)) (decl pulley_xconst8 (i8) XReg) (rule (pulley_xconst8 x) diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/args.rs b/cranelift/codegen/src/isa/pulley_shared/inst/args.rs index 468f31a13643..3affe26e9348 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/args.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/args.rs @@ -126,6 +126,20 @@ impl XReg { /// Index of the first "special" register, or the end of which registers /// regalloc is allowed to use. pub const SPECIAL_START: u8 = pulley_interpreter::regs::XReg::SPECIAL_START; + + /// Returns whether this is a "special" physical register for pulley. + pub fn is_special(&self) -> bool { + match self.as_pulley() { + Some(reg) => reg.is_special(), + None => false, + } + } + + /// Returns the pulley-typed register, if this is a phyiscal register. + pub fn as_pulley(&self) -> Option { + let enc = self.to_real_reg()?.hw_enc(); + Some(pulley_interpreter::XReg::new(enc).unwrap()) + } } pub use super::super::lower::isle::generated_code::ExtKind; diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs index 3382fc1d1ee2..e15cdf59fec7 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs @@ -188,7 +188,7 @@ fn pulley_emit

( Inst::Nop => todo!(), - Inst::GetSp { dst } => enc::get_sp(sink, dst), + Inst::GetSpecial { dst, reg } => enc::xmov(sink, dst, reg), Inst::Ret => enc::ret(sink), diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs b/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs index 2bfb34cdc8a7..e81bc63109b8 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs @@ -79,8 +79,12 @@ fn pulley_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { collector.reg_use(src2); } - Inst::GetSp { dst } => { + Inst::GetSpecial { dst, reg } => { collector.reg_def(dst); + // Note that this is explicitly ignored as this is only used for + // special registers that don't participate in register allocation + // such as the stack pointer, frame pointer, etc. + assert!(reg.is_special()); } Inst::LoadExtName { @@ -568,9 +572,10 @@ impl Inst { Inst::Ret => format!("ret"), - Inst::GetSp { dst } => { + Inst::GetSpecial { dst, reg } => { let dst = format_reg(*dst.to_reg()); - format!("{dst} = get_sp") + let reg = format_reg(**reg); + format!("xmov {dst}, {reg}") } Inst::LoadExtName { dst, name, offset } => { diff --git a/cranelift/codegen/src/isa/pulley_shared/lower.isle b/cranelift/codegen/src/isa/pulley_shared/lower.isle index b03d3b1e33d5..7670b31339ad 100644 --- a/cranelift/codegen/src/isa/pulley_shared/lower.isle +++ b/cranelift/codegen/src/isa/pulley_shared/lower.isle @@ -114,7 +114,12 @@ ;;;; Rules for `get_stack_pointer` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (rule (lower (get_stack_pointer)) - (pulley_get_sp)) + (pulley_get_special (sp_reg))) + +;;;; Rules for `get_frame_pointer` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(rule (lower (get_frame_pointer)) + (pulley_get_special (fp_reg))) ;;;; Rules for `return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs b/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs index f75fe027f239..1f696123d16a 100644 --- a/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs +++ b/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs @@ -10,6 +10,7 @@ use crate::ir::{condcodes::*, immediates::*, types::*, *}; use crate::isa::pulley_shared::{ abi::*, inst::{FReg, OperandSize, VReg, WritableFReg, WritableVReg, WritableXReg, XReg}, + lower::regs, *, }; use crate::machinst::{ @@ -101,6 +102,14 @@ where fn emit(&mut self, arg0: &MInst) -> Unit { self.lower_ctx.emit(arg0.clone().into()); } + + fn sp_reg(&mut self) -> XReg { + XReg::new(regs::stack_reg()).unwrap() + } + + fn fp_reg(&mut self) -> XReg { + XReg::new(regs::fp_reg()).unwrap() + } } /// The main entry point for lowering with ISLE. diff --git a/cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif b/cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif deleted file mode 100644 index f269efa92e36..000000000000 --- a/cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif +++ /dev/null @@ -1,18 +0,0 @@ -test compile precise-output -target pulley32 - -function %get_stack_pointer() -> i32 { -block0: - v0 = get_stack_pointer.i32 - return v0 -} - -; VCode: -; block0: -; x0 = get_sp -; ret -; -; Disassembled: -; get_sp x0 -; ret - diff --git a/cranelift/filetests/filetests/isa/pulley32/special_regs.clif b/cranelift/filetests/filetests/isa/pulley32/special_regs.clif new file mode 100644 index 000000000000..d46e04c741f5 --- /dev/null +++ b/cranelift/filetests/filetests/isa/pulley32/special_regs.clif @@ -0,0 +1,70 @@ +test compile precise-output +set preserve_frame_pointers +target pulley32 + +function %get_stack_pointer() -> i32 { +block0: + v0 = get_stack_pointer.i32 + return v0 +} + +; VCode: +; x30 = xconst8 -16 +; x27 = xadd32 x27, x30 +; store64 sp+8, x28 // flags = notrap aligned +; store64 sp+0, x29 // flags = notrap aligned +; x29 = xmov x27 +; block0: +; xmov x0, x27 +; x28 = load64_u sp+8 // flags = notrap aligned +; x29 = load64_u sp+0 // flags = notrap aligned +; x30 = xconst8 16 +; x27 = xadd32 x27, x30 +; ret +; +; Disassembled: +; xconst8 spilltmp0, -16 +; xadd32 sp, sp, spilltmp0 +; store64_offset8 sp, 8, lr +; store64 sp, fp +; xmov fp, sp +; xmov x0, sp +; load64_offset8 lr, sp, 8 +; load64 fp, sp +; xconst8 spilltmp0, 16 +; xadd32 sp, sp, spilltmp0 +; ret + +function %get_frame_pointer() -> i32 { +block0: + v0 = get_frame_pointer.i32 + return v0 +} + +; VCode: +; x30 = xconst8 -16 +; x27 = xadd32 x27, x30 +; store64 sp+8, x28 // flags = notrap aligned +; store64 sp+0, x29 // flags = notrap aligned +; x29 = xmov x27 +; block0: +; xmov x0, x29 +; x28 = load64_u sp+8 // flags = notrap aligned +; x29 = load64_u sp+0 // flags = notrap aligned +; x30 = xconst8 16 +; x27 = xadd32 x27, x30 +; ret +; +; Disassembled: +; xconst8 spilltmp0, -16 +; xadd32 sp, sp, spilltmp0 +; store64_offset8 sp, 8, lr +; store64 sp, fp +; xmov fp, sp +; xmov x0, fp +; load64_offset8 lr, sp, 8 +; load64 fp, sp +; xconst8 spilltmp0, 16 +; xadd32 sp, sp, spilltmp0 +; ret + diff --git a/cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif b/cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif deleted file mode 100644 index e3df1187e779..000000000000 --- a/cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif +++ /dev/null @@ -1,18 +0,0 @@ -test compile precise-output -target pulley64 - -function %get_stack_pointer() -> i64 { -block0: - v0 = get_stack_pointer.i64 - return v0 -} - -; VCode: -; block0: -; x0 = get_sp -; ret -; -; Disassembled: -; get_sp x0 -; ret - diff --git a/cranelift/filetests/filetests/isa/pulley64/special_regs.clif b/cranelift/filetests/filetests/isa/pulley64/special_regs.clif new file mode 100644 index 000000000000..ad0dcac017b5 --- /dev/null +++ b/cranelift/filetests/filetests/isa/pulley64/special_regs.clif @@ -0,0 +1,70 @@ +test compile precise-output +set preserve_frame_pointers +target pulley64 + +function %get_stack_pointer() -> i64 { +block0: + v0 = get_stack_pointer.i64 + return v0 +} + +; VCode: +; x30 = xconst8 -16 +; x27 = xadd32 x27, x30 +; store64 sp+8, x28 // flags = notrap aligned +; store64 sp+0, x29 // flags = notrap aligned +; x29 = xmov x27 +; block0: +; xmov x0, x27 +; x28 = load64_u sp+8 // flags = notrap aligned +; x29 = load64_u sp+0 // flags = notrap aligned +; x30 = xconst8 16 +; x27 = xadd32 x27, x30 +; ret +; +; Disassembled: +; xconst8 spilltmp0, -16 +; xadd32 sp, sp, spilltmp0 +; store64_offset8 sp, 8, lr +; store64 sp, fp +; xmov fp, sp +; xmov x0, sp +; load64_offset8 lr, sp, 8 +; load64 fp, sp +; xconst8 spilltmp0, 16 +; xadd32 sp, sp, spilltmp0 +; ret + +function %get_frame_pointer() -> i64 { +block0: + v0 = get_frame_pointer.i64 + return v0 +} + +; VCode: +; x30 = xconst8 -16 +; x27 = xadd32 x27, x30 +; store64 sp+8, x28 // flags = notrap aligned +; store64 sp+0, x29 // flags = notrap aligned +; x29 = xmov x27 +; block0: +; xmov x0, x29 +; x28 = load64_u sp+8 // flags = notrap aligned +; x29 = load64_u sp+0 // flags = notrap aligned +; x30 = xconst8 16 +; x27 = xadd32 x27, x30 +; ret +; +; Disassembled: +; xconst8 spilltmp0, -16 +; xadd32 sp, sp, spilltmp0 +; store64_offset8 sp, 8, lr +; store64 sp, fp +; xmov fp, sp +; xmov x0, fp +; load64_offset8 lr, sp, 8 +; load64 fp, sp +; xconst8 spilltmp0, 16 +; xadd32 sp, sp, spilltmp0 +; ret + diff --git a/pulley/fuzz/src/interp.rs b/pulley/fuzz/src/interp.rs index 826d0ad30f86..e0f990e7ea93 100644 --- a/pulley/fuzz/src/interp.rs +++ b/pulley/fuzz/src/interp.rs @@ -125,7 +125,6 @@ fn extended_op_is_safe_for_fuzzing(op: &ExtendedOp) -> bool { match op { ExtendedOp::Trap(_) => true, ExtendedOp::Nop(_) => true, - ExtendedOp::GetSp(GetSp { dst, .. }) => !dst.is_special(), ExtendedOp::CallIndirectHost(_) => false, } } diff --git a/pulley/src/interp.rs b/pulley/src/interp.rs index 1724f2a7d910..536606923308 100644 --- a/pulley/src/interp.rs +++ b/pulley/src/interp.rs @@ -1248,12 +1248,6 @@ impl ExtendedOpVisitor for Interpreter<'_> { ControlFlow::Break(Done::Trap(self.pc.as_ptr())) } - fn get_sp(&mut self, dst: XReg) -> ControlFlow { - let sp = self.state[XReg::sp].get_u64(); - self.state[dst].set_u64(sp); - ControlFlow::Continue(()) - } - fn call_indirect_host(&mut self, sig: u8) -> ControlFlow { let _ = sig; // TODO: should stash this somewhere ControlFlow::Break(Done::ReturnToHost) diff --git a/pulley/src/lib.rs b/pulley/src/lib.rs index abb91df56b01..06f882ec9fdf 100644 --- a/pulley/src/lib.rs +++ b/pulley/src/lib.rs @@ -203,8 +203,6 @@ macro_rules! for_each_extended_op { /// Do nothing. nop = Nop; - /// Copy the special `sp` stack pointer register into an `x` register. - get_sp = GetSp { dst: XReg }; /// A special opcode to use an indirect function call to reenter the /// host from the interpreter. /// From db956669a5bc7de1ac247c63b4ad895965469144 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Dec 2024 12:28:16 -0700 Subject: [PATCH 06/21] pulley: Implement getting the link register (#9720) Fill out `get_return_address` lowering in Cranelift. --- .../codegen/src/isa/pulley_shared/abi.rs | 6 ++-- .../codegen/src/isa/pulley_shared/inst.isle | 3 ++ .../src/isa/pulley_shared/inst/regs.rs | 2 +- .../codegen/src/isa/pulley_shared/lower.isle | 5 +++ .../src/isa/pulley_shared/lower/isle.rs | 4 +++ .../filetests/isa/pulley32/special_regs.clif | 33 ++++++++++++++++++ .../filetests/isa/pulley64/special_regs.clif | 34 +++++++++++++++++++ 7 files changed, 83 insertions(+), 4 deletions(-) diff --git a/cranelift/codegen/src/isa/pulley_shared/abi.rs b/cranelift/codegen/src/isa/pulley_shared/abi.rs index 067f593caf02..2c290f4bfd9d 100644 --- a/cranelift/codegen/src/isa/pulley_shared/abi.rs +++ b/cranelift/codegen/src/isa/pulley_shared/abi.rs @@ -296,7 +296,7 @@ where insts.push( Inst::gen_store( Amode::SpOffset { offset: 8 }, - link_reg(), + lr_reg(), I64, MemFlags::trusted(), ) @@ -345,7 +345,7 @@ where if frame_layout.setup_area_size > 0 { insts.push( Inst::gen_load( - writable_link_reg(), + writable_lr_reg(), Amode::SpOffset { offset: 8 }, I64, MemFlags::trusted(), @@ -405,7 +405,7 @@ where insts.push( Inst::gen_store( Amode::SpOffset { offset: 8 }, - link_reg(), + lr_reg(), I64, MemFlags::trusted(), ) diff --git a/cranelift/codegen/src/isa/pulley_shared/inst.isle b/cranelift/codegen/src/isa/pulley_shared/inst.isle index 6ad0c4998931..298c7d5eb253 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst.isle +++ b/cranelift/codegen/src/isa/pulley_shared/inst.isle @@ -387,6 +387,9 @@ (decl fp_reg () XReg) (extern constructor fp_reg fp_reg) +(decl lr_reg () XReg) +(extern constructor lr_reg lr_reg) + (decl pulley_get_special (XReg) XReg) (rule (pulley_get_special reg) (let ((dst WritableXReg (temp_writable_xreg)) diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/regs.rs b/cranelift/codegen/src/isa/pulley_shared/inst/regs.rs index 16da50b582f0..f274db871142 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/regs.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/regs.rs @@ -91,7 +91,7 @@ define_registers! { x_reg(26) => x26, writable_x26; x_reg(27) => stack_reg, writable_stack_reg; - x_reg(28) => link_reg, writable_link_reg; + x_reg(28) => lr_reg, writable_lr_reg; x_reg(29) => fp_reg, writable_fp_reg; x_reg(30) => spilltmp_reg, writable_spilltmp_reg; x_reg(31) => spilltmp2_reg, writable_spilltmp2_reg; diff --git a/cranelift/codegen/src/isa/pulley_shared/lower.isle b/cranelift/codegen/src/isa/pulley_shared/lower.isle index 7670b31339ad..00de3b70838c 100644 --- a/cranelift/codegen/src/isa/pulley_shared/lower.isle +++ b/cranelift/codegen/src/isa/pulley_shared/lower.isle @@ -121,6 +121,11 @@ (rule (lower (get_frame_pointer)) (pulley_get_special (fp_reg))) +;;;; Rules for `get_return_address` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(rule (lower (get_return_address)) + (pulley_get_special (lr_reg))) + ;;;; Rules for `return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; N.B.: the `ret` itself is generated by the ABI. diff --git a/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs b/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs index 1f696123d16a..ae61bbc18fbc 100644 --- a/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs +++ b/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs @@ -110,6 +110,10 @@ where fn fp_reg(&mut self) -> XReg { XReg::new(regs::fp_reg()).unwrap() } + + fn lr_reg(&mut self) -> XReg { + XReg::new(regs::lr_reg()).unwrap() + } } /// The main entry point for lowering with ISLE. diff --git a/cranelift/filetests/filetests/isa/pulley32/special_regs.clif b/cranelift/filetests/filetests/isa/pulley32/special_regs.clif index d46e04c741f5..8b7a8beb8404 100644 --- a/cranelift/filetests/filetests/isa/pulley32/special_regs.clif +++ b/cranelift/filetests/filetests/isa/pulley32/special_regs.clif @@ -68,3 +68,36 @@ block0: ; xadd32 sp, sp, spilltmp0 ; ret +function %get_return_address() -> i32 { +block0: + v0 = get_return_address.i32 + return v0 +} + +; VCode: +; x30 = xconst8 -16 +; x27 = xadd32 x27, x30 +; store64 sp+8, x28 // flags = notrap aligned +; store64 sp+0, x29 // flags = notrap aligned +; x29 = xmov x27 +; block0: +; xmov x0, x28 +; x28 = load64_u sp+8 // flags = notrap aligned +; x29 = load64_u sp+0 // flags = notrap aligned +; x30 = xconst8 16 +; x27 = xadd32 x27, x30 +; ret +; +; Disassembled: +; xconst8 spilltmp0, -16 +; xadd32 sp, sp, spilltmp0 +; store64_offset8 sp, 8, lr +; store64 sp, fp +; xmov fp, sp +; xmov x0, lr +; load64_offset8 lr, sp, 8 +; load64 fp, sp +; xconst8 spilltmp0, 16 +; xadd32 sp, sp, spilltmp0 +; ret + diff --git a/cranelift/filetests/filetests/isa/pulley64/special_regs.clif b/cranelift/filetests/filetests/isa/pulley64/special_regs.clif index ad0dcac017b5..97fa1d6b43c1 100644 --- a/cranelift/filetests/filetests/isa/pulley64/special_regs.clif +++ b/cranelift/filetests/filetests/isa/pulley64/special_regs.clif @@ -68,3 +68,37 @@ block0: ; xadd32 sp, sp, spilltmp0 ; ret + +function %get_return_address() -> i64 { +block0: + v0 = get_return_address.i64 + return v0 +} + +; VCode: +; x30 = xconst8 -16 +; x27 = xadd32 x27, x30 +; store64 sp+8, x28 // flags = notrap aligned +; store64 sp+0, x29 // flags = notrap aligned +; x29 = xmov x27 +; block0: +; xmov x0, x28 +; x28 = load64_u sp+8 // flags = notrap aligned +; x29 = load64_u sp+0 // flags = notrap aligned +; x30 = xconst8 16 +; x27 = xadd32 x27, x30 +; ret +; +; Disassembled: +; xconst8 spilltmp0, -16 +; xadd32 sp, sp, spilltmp0 +; store64_offset8 sp, 8, lr +; store64 sp, fp +; xmov fp, sp +; xmov x0, lr +; load64_offset8 lr, sp, 8 +; load64 fp, sp +; xconst8 spilltmp0, 16 +; xadd32 sp, sp, spilltmp0 +; ret + From 27ffc5e246531384cc2889ee885df5ad3c9f4892 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Tue, 3 Dec 2024 15:18:08 -0800 Subject: [PATCH 07/21] Fix field type matching for subtyping and mutability (#9724) Similar to https://github.com/bytecodealliance/wasm-tools/pull/1934 but for `wasmtime::FieldType`. --- crates/wasmtime/src/runtime/type_registry.rs | 5 + crates/wasmtime/src/runtime/types.rs | 46 ++++--- tests/all/types.rs | 121 +++++++++++++------ 3 files changed, 121 insertions(+), 51 deletions(-) diff --git a/crates/wasmtime/src/runtime/type_registry.rs b/crates/wasmtime/src/runtime/type_registry.rs index cdbfa6d42fb0..0a10b88e8f29 100644 --- a/crates/wasmtime/src/runtime/type_registry.rs +++ b/crates/wasmtime/src/runtime/type_registry.rs @@ -1235,11 +1235,16 @@ impl TypeRegistry { } /// Is type `sub` a subtype of `sup`? + #[inline] pub fn is_subtype(&self, sub: VMSharedTypeIndex, sup: VMSharedTypeIndex) -> bool { if sub == sup { return true; } + self.is_subtype_slow(sub, sup) + } + + fn is_subtype_slow(&self, sub: VMSharedTypeIndex, sup: VMSharedTypeIndex) -> bool { // Do the O(1) subtype checking trick: // // In a type system with single inheritance, the subtyping relationships diff --git a/crates/wasmtime/src/runtime/types.rs b/crates/wasmtime/src/runtime/types.rs index 65a17d6510a4..954df787969d 100644 --- a/crates/wasmtime/src/runtime/types.rs +++ b/crates/wasmtime/src/runtime/types.rs @@ -1362,7 +1362,14 @@ impl StorageType { /// Panics if either type is associated with a different engine from the /// other. pub fn eq(a: &Self, b: &Self) -> bool { - a.matches(b) && b.matches(a) + match (a, b) { + (StorageType::I8, StorageType::I8) => true, + (StorageType::I8, _) => false, + (StorageType::I16, StorageType::I16) => true, + (StorageType::I16, _) => false, + (StorageType::ValType(a), StorageType::ValType(b)) => ValType::eq(a, b), + (StorageType::ValType(_), _) => false, + } } pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool { @@ -1457,8 +1464,21 @@ impl FieldType { /// Panics if either type is associated with a different engine from the /// other. pub fn matches(&self, other: &Self) -> bool { - (other.mutability == Mutability::Var || self.mutability == Mutability::Const) - && self.element_type.matches(&other.element_type) + // Our storage type must match `other`'s storage type and either + // + // 1. Both field types are immutable, or + // + // 2. Both field types are mutable and `other`'s storage type must match + // ours, i.e. the storage types are exactly the same. + use Mutability as M; + match (self.mutability, other.mutability) { + // Case 1 + (M::Const, M::Const) => self.element_type.matches(&other.element_type), + // Case 2 + (M::Var, M::Var) => StorageType::eq(&self.element_type, &other.element_type), + // Does not match. + _ => false, + } } /// Is field type `a` precisely equal to field type `b`? @@ -1676,13 +1696,9 @@ impl StructType { pub fn matches(&self, other: &StructType) -> bool { assert!(self.comes_from_same_engine(other.engine())); - // Avoid matching on structure for subtyping checks when we have - // precisely the same type. - if self.type_index() == other.type_index() { - return true; - } - - Self::fields_match(self.fields(), other.fields()) + self.engine() + .signatures() + .is_subtype(self.type_index(), other.type_index()) } fn fields_match( @@ -1940,13 +1956,9 @@ impl ArrayType { pub fn matches(&self, other: &ArrayType) -> bool { assert!(self.comes_from_same_engine(other.engine())); - // Avoid matching on structure for subtyping checks when we have - // precisely the same type. - if self.type_index() == other.type_index() { - return true; - } - - self.field_type().matches(&other.field_type()) + self.engine() + .signatures() + .is_subtype(self.type_index(), other.type_index()) } /// Is array type `a` precisely equal to array type `b`? diff --git a/tests/all/types.rs b/tests/all/types.rs index 993a5354bc39..d3dc2c4a3626 100644 --- a/tests/all/types.rs +++ b/tests/all/types.rs @@ -7,6 +7,13 @@ fn field(heap_ty: HeapType) -> FieldType { ) } +fn imm_field(heap_ty: HeapType) -> FieldType { + FieldType::new( + Mutability::Const, + StorageType::ValType(RefType::new(true, heap_ty).into()), + ) +} + fn valty(heap_ty: HeapType) -> ValType { ValType::Ref(RefType::new(true, heap_ty)) } @@ -81,25 +88,57 @@ fn basic_struct_types() -> Result<()> { fn struct_type_matches() -> Result<()> { let engine = Engine::default(); - let super_ty = StructType::new(&engine, [field(HeapType::Func)])?; + let super_ty = StructType::with_finality_and_supertype( + &engine, + Finality::NonFinal, + None, + [imm_field(HeapType::Func)], + )?; // Depth. - let sub_ty = StructType::new(&engine, [field(HeapType::NoFunc)])?; + let sub_ty = StructType::with_finality_and_supertype( + &engine, + Finality::Final, + Some(&super_ty), + [imm_field(HeapType::NoFunc)], + )?; assert!(sub_ty.matches(&super_ty)); + let not_sub_ty = StructType::new(&engine, [imm_field(HeapType::NoFunc)])?; + assert!(!not_sub_ty.matches(&super_ty)); // Width. - let sub_ty = StructType::new(&engine, [field(HeapType::Func), field(HeapType::Extern)])?; + let sub_ty = StructType::with_finality_and_supertype( + &engine, + Finality::Final, + Some(&super_ty), + [imm_field(HeapType::Func), imm_field(HeapType::Extern)], + )?; assert!(sub_ty.matches(&super_ty)); + let not_sub_ty = StructType::new( + &engine, + [imm_field(HeapType::Func), imm_field(HeapType::Extern)], + )?; + assert!(!not_sub_ty.matches(&super_ty)); // Depth and width. - let sub_ty = StructType::new(&engine, [field(HeapType::NoFunc), field(HeapType::Extern)])?; + let sub_ty = StructType::with_finality_and_supertype( + &engine, + Finality::Final, + Some(&super_ty), + [imm_field(HeapType::NoFunc), imm_field(HeapType::Extern)], + )?; assert!(sub_ty.matches(&super_ty)); + let not_sub_ty = StructType::new( + &engine, + [imm_field(HeapType::NoFunc), imm_field(HeapType::Extern)], + )?; + assert!(!not_sub_ty.matches(&super_ty)); - // Not depth. + // Unrelated structs. + let not_sub_ty = StructType::new(&engine, [imm_field(HeapType::Extern)])?; + assert!(!not_sub_ty.matches(&super_ty)); let not_sub_ty = StructType::new(&engine, [field(HeapType::Extern)])?; assert!(!not_sub_ty.matches(&super_ty)); - - // Not width. let not_sub_ty = StructType::new(&engine, [])?; assert!(!not_sub_ty.matches(&super_ty)); @@ -109,29 +148,41 @@ fn struct_type_matches() -> Result<()> { #[test] fn struct_subtyping_fields_must_match() -> Result<()> { let engine = Engine::default(); + let a = StructType::with_finality_and_supertype( &engine, Finality::NonFinal, None, - [field(HeapType::Any)], + [imm_field(HeapType::Any)], )?; - for (expected, fields) in [ - // Missing field. - (false, vec![]), - // Non-matching field. - (false, vec![field(HeapType::Extern)]), - // Exact match is okay. - (true, vec![field(HeapType::Any)]), - // Subtype of the field is okay. - (true, vec![field(HeapType::Eq)]), - // Extra fields are okay. - (true, vec![field(HeapType::Any), field(HeapType::Extern)]), + for (msg, expected, fields) in [ + ("Missing field", false, vec![]), + ( + "Non-matching field", + false, + vec![imm_field(HeapType::Extern)], + ), + ("Wrong mutability field", false, vec![field(HeapType::Any)]), + ("Exact match is okay", true, vec![imm_field(HeapType::Any)]), + ( + "Subtype of the field is okay", + true, + vec![imm_field(HeapType::Eq)], + ), + ( + "Extra fields are okay", + true, + vec![imm_field(HeapType::Any), imm_field(HeapType::Extern)], + ), ] { let actual = StructType::with_finality_and_supertype(&engine, Finality::NonFinal, Some(&a), fields) .is_ok(); - assert_eq!(expected, actual); + assert_eq!( + expected, actual, + "expected valid? {expected}; actually valid? {actual}; {msg}" + ); } Ok(()) @@ -263,16 +314,18 @@ fn array_subtyping_field_must_match() -> Result<()> { &engine, Finality::NonFinal, None, - field(HeapType::Any), + imm_field(HeapType::Any), )?; for (expected, field) in [ // Non-matching field. - (false, field(HeapType::Extern)), + (false, imm_field(HeapType::Extern)), + // Wrong mutability field. + (false, field(HeapType::Any)), // Exact match is okay. - (true, field(HeapType::Any)), + (true, imm_field(HeapType::Any)), // Subtype of the field is okay. - (true, field(HeapType::Eq)), + (true, imm_field(HeapType::Eq)), ] { let actual = ArrayType::with_finality_and_supertype(&engine, Finality::NonFinal, Some(&a), field) @@ -322,61 +375,61 @@ fn array_subtyping() -> Result<()> { &engine, Finality::NonFinal, None, - field(HeapType::Any), + imm_field(HeapType::Any), )?; let a = ArrayType::with_finality_and_supertype( &engine, Finality::NonFinal, Some(&base), - field(HeapType::Any), + imm_field(HeapType::Any), )?; let b = ArrayType::with_finality_and_supertype( &engine, Finality::NonFinal, Some(&base), - field(HeapType::Eq), + imm_field(HeapType::Eq), )?; let c = ArrayType::with_finality_and_supertype( &engine, Finality::NonFinal, Some(&a), - field(HeapType::Any), + imm_field(HeapType::Any), )?; let d = ArrayType::with_finality_and_supertype( &engine, Finality::NonFinal, Some(&a), - field(HeapType::Eq), + imm_field(HeapType::Eq), )?; let e = ArrayType::with_finality_and_supertype( &engine, Finality::NonFinal, Some(&c), - field(HeapType::Any), + imm_field(HeapType::Any), )?; let f = ArrayType::with_finality_and_supertype( &engine, Finality::NonFinal, Some(&e), - field(HeapType::Any), + imm_field(HeapType::Any), )?; let g = ArrayType::with_finality_and_supertype( &engine, Finality::NonFinal, None, - field(HeapType::Eq), + imm_field(HeapType::Eq), )?; let h = ArrayType::with_finality_and_supertype( &engine, Finality::NonFinal, Some(&g), - field(HeapType::Eq), + imm_field(HeapType::Eq), )?; let i = ArrayType::with_finality_and_supertype( &engine, Finality::NonFinal, Some(&h), - field(HeapType::Eq), + imm_field(HeapType::Eq), )?; for (expected, sub_name, sub, sup_name, sup) in [ From 3b6dc591a1366ab1e41cb7381bbd858b27092859 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Dec 2024 17:37:12 -0700 Subject: [PATCH 08/21] pulley: Remove virtual sp offset (#9722) This fixes the output of the pulley cranelift backend with respect to virtual stack offsets and adjustments for calls with stack parameters and results. Previously the virtual stack pointer was updated but the rest of the backend assumed the real stack pointer was updated. This updates the pulley backend to match the other backends in this respects and fixes a test on my "more complete pulley integration" branch. --- .../codegen/src/isa/pulley_shared/abi.rs | 4 + .../src/isa/pulley_shared/inst/args.rs | 2 +- .../src/isa/pulley_shared/inst/emit.rs | 22 ++-- .../filetests/isa/pulley64/call.clif | 100 ++++++++++++++++++ 4 files changed, 113 insertions(+), 15 deletions(-) diff --git a/cranelift/codegen/src/isa/pulley_shared/abi.rs b/cranelift/codegen/src/isa/pulley_shared/abi.rs index 2c290f4bfd9d..15b6e8f41a6c 100644 --- a/cranelift/codegen/src/isa/pulley_shared/abi.rs +++ b/cranelift/codegen/src/isa/pulley_shared/abi.rs @@ -254,6 +254,10 @@ where } fn gen_sp_reg_adjust(amount: i32) -> SmallInstVec { + if amount == 0 { + return smallvec![]; + } + let temp = WritableXReg::try_from(writable_spilltmp_reg()).unwrap(); let imm = if let Ok(x) = i8::try_from(amount) { diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/args.rs b/cranelift/codegen/src/isa/pulley_shared/inst/args.rs index 3affe26e9348..e70dfbaf2249 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/args.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/args.rs @@ -180,7 +180,7 @@ impl Amode { + frame_layout.outgoing_args_size; i64::from(sp_offset) - offset } - StackAMode::Slot(offset) => *offset + state.virtual_sp_offset, + StackAMode::Slot(offset) => *offset, StackAMode::OutgoingArg(offset) => *offset, }, } diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs index e15cdf59fec7..8806737b7cc4 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs @@ -4,7 +4,6 @@ use super::*; use crate::ir; use crate::isa::pulley_shared::abi::PulleyMachineDeps; use crate::isa::pulley_shared::PointerWidth; -use crate::trace; use core::marker::PhantomData; use cranelift_control::ControlPlane; use pulley_interpreter::encode as enc; @@ -40,7 +39,6 @@ where _phantom: PhantomData

, ctrl_plane: ControlPlane, user_stack_map: Option, - pub virtual_sp_offset: i64, frame_layout: FrameLayout, } @@ -51,13 +49,6 @@ where fn take_stack_map(&mut self) -> Option { self.user_stack_map.take() } - - pub(crate) fn adjust_virtual_sp_offset(&mut self, amount: i64) { - let old = self.virtual_sp_offset; - let new = self.virtual_sp_offset + amount; - trace!("adjust virtual sp offset by {amount:#x}: {old:#x} -> {new:#x}",); - self.virtual_sp_offset = new; - } } impl

MachInstEmitState> for EmitState

@@ -69,7 +60,6 @@ where _phantom: PhantomData, ctrl_plane, user_stack_map: None, - virtual_sp_offset: 0, frame_layout: abi.frame_layout().clone(), } } @@ -211,8 +201,10 @@ fn pulley_emit

( } sink.add_call_site(); - let callee_pop_size = i64::from(info.callee_pop_size); - state.adjust_virtual_sp_offset(-callee_pop_size); + let adjust = -i32::try_from(info.callee_pop_size).unwrap(); + for i in PulleyMachineDeps::

::gen_sp_reg_adjust(adjust) { + >::from(i).emit(sink, emit_info, state); + } } Inst::IndirectCall { info } => { @@ -225,8 +217,10 @@ fn pulley_emit

( sink.add_call_site(); - let callee_pop_size = i64::from(info.callee_pop_size); - state.adjust_virtual_sp_offset(-callee_pop_size); + let adjust = -i32::try_from(info.callee_pop_size).unwrap(); + for i in PulleyMachineDeps::

::gen_sp_reg_adjust(adjust) { + >::from(i).emit(sink, emit_info, state); + } } Inst::IndirectCallHost { info } => { diff --git a/cranelift/filetests/filetests/isa/pulley64/call.clif b/cranelift/filetests/filetests/isa/pulley64/call.clif index de51731bf798..c3829b55cb7f 100644 --- a/cranelift/filetests/filetests/isa/pulley64/call.clif +++ b/cranelift/filetests/filetests/isa/pulley64/call.clif @@ -443,3 +443,103 @@ block0(v0: i64): ; xadd32 sp, sp, spilltmp0 ; ret +function %colocated_with_stack_args() { + fn0 = colocated %g( + i64, i64, i64, i64, i64, i64, i64, i64, + i64, i64, i64, i64, i64, i64, i64, i64, + i64, i64, i64, i64, i64, i64, i64, i64 + ) + +block0: + v0 = iconst.i64 0 + call fn0( + v0, v0, v0, v0, v0, v0, v0, v0, + v0, v0, v0, v0, v0, v0, v0, v0, + v0, v0, v0, v0, v0, v0, v0, v0 + ) + return +} + +; VCode: +; x30 = xconst8 -16 +; x27 = xadd32 x27, x30 +; store64 sp+8, x28 // flags = notrap aligned +; store64 sp+0, x29 // flags = notrap aligned +; x29 = xmov x27 +; x30 = xconst8 -64 +; x27 = xadd32 x27, x30 +; block0: +; x15 = xconst8 0 +; store64 OutgoingArg(0), x15 // flags = notrap aligned +; store64 OutgoingArg(8), x15 // flags = notrap aligned +; store64 OutgoingArg(16), x15 // flags = notrap aligned +; store64 OutgoingArg(24), x15 // flags = notrap aligned +; store64 OutgoingArg(32), x15 // flags = notrap aligned +; store64 OutgoingArg(40), x15 // flags = notrap aligned +; store64 OutgoingArg(48), x15 // flags = notrap aligned +; store64 OutgoingArg(56), x15 // flags = notrap aligned +; x0 = xmov x15 +; x1 = xmov x15 +; x2 = xmov x15 +; x3 = xmov x15 +; x4 = xmov x15 +; x5 = xmov x15 +; x6 = xmov x15 +; x7 = xmov x15 +; x8 = xmov x15 +; x9 = xmov x15 +; x10 = xmov x15 +; x11 = xmov x15 +; x12 = xmov x15 +; x13 = xmov x15 +; x14 = xmov x15 +; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }, CallArgPair { vreg: p10i, preg: p10i }, CallArgPair { vreg: p11i, preg: p11i }, CallArgPair { vreg: p12i, preg: p12i }, CallArgPair { vreg: p13i, preg: p13i }, CallArgPair { vreg: p14i, preg: p14i }, CallArgPair { vreg: p15i, preg: p15i }], defs: [], clobbers: PRegSet { bits: [65535, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } +; x30 = xconst8 64 +; x27 = xadd32 x27, x30 +; x28 = load64_u sp+8 // flags = notrap aligned +; x29 = load64_u sp+0 // flags = notrap aligned +; x30 = xconst8 16 +; x27 = xadd32 x27, x30 +; ret +; +; Disassembled: +; xconst8 spilltmp0, -16 +; xadd32 sp, sp, spilltmp0 +; store64_offset8 sp, 8, lr +; store64 sp, fp +; xmov fp, sp +; xconst8 spilltmp0, -64 +; xadd32 sp, sp, spilltmp0 +; xconst8 x15, 0 +; store64 sp, x15 +; store64_offset8 sp, 8, x15 +; store64_offset8 sp, 16, x15 +; store64_offset8 sp, 24, x15 +; store64_offset8 sp, 32, x15 +; store64_offset8 sp, 40, x15 +; store64_offset8 sp, 48, x15 +; store64_offset8 sp, 56, x15 +; xmov x0, x15 +; xmov x1, x15 +; xmov x2, x15 +; xmov x3, x15 +; xmov x4, x15 +; xmov x5, x15 +; xmov x6, x15 +; xmov x7, x15 +; xmov x8, x15 +; xmov x9, x15 +; xmov x10, x15 +; xmov x11, x15 +; xmov x12, x15 +; xmov x13, x15 +; xmov x14, x15 +; call 0x0 // target = 0x65 +; xconst8 spilltmp0, 64 +; xadd32 sp, sp, spilltmp0 +; load64_offset8 lr, sp, 8 +; load64 fp, sp +; xconst8 spilltmp0, 16 +; xadd32 sp, sp, spilltmp0 +; ret + From 30ff4bfca9b7f096b2ffc16f64f5bd10f0642e22 Mon Sep 17 00:00:00 2001 From: caelunshun Date: Tue, 3 Dec 2024 21:54:54 -0700 Subject: [PATCH 09/21] cranelift-entity: Make PackedOption and EntityList have guaranteed layout (#9697) * cranelift-entity: Make PackedOption and EntityList have guaranteed layout * cranelift-entity: Add docs for PackedOption and EntityList layout --- cranelift/entity/src/list.rs | 3 ++- cranelift/entity/src/packed_option.rs | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/cranelift/entity/src/list.rs b/cranelift/entity/src/list.rs index 65d54d43e0e6..29a6293c19bc 100644 --- a/cranelift/entity/src/list.rs +++ b/cranelift/entity/src/list.rs @@ -45,7 +45,7 @@ use serde_derive::{Deserialize, Serialize}; /// The `EntityList` itself is designed to have the smallest possible footprint. This is important /// because it is used inside very compact data structures like `InstructionData`. The list /// contains only a 32-bit index into the pool's memory vector, pointing to the first element of -/// the list. +/// the list. A zero value represents the empty list, which is returned by `EntityList::default`. /// /// The pool is just a single `Vec` containing all of the allocated lists. Each list is /// represented as three contiguous parts: @@ -64,6 +64,7 @@ use serde_derive::{Deserialize, Serialize}; /// reserved for the empty list which isn't allocated in the vector. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[repr(C)] pub struct EntityList { index: u32, unused: PhantomData, diff --git a/cranelift/entity/src/packed_option.rs b/cranelift/entity/src/packed_option.rs index e6d0eed1468c..e4b949f34818 100644 --- a/cranelift/entity/src/packed_option.rs +++ b/cranelift/entity/src/packed_option.rs @@ -22,8 +22,12 @@ pub trait ReservedValue { } /// Packed representation of `Option`. +/// +/// This is a wrapper around a `T`, using `T::reserved_value` to represent +/// `None`. #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[repr(transparent)] pub struct PackedOption(T); impl PackedOption { From 8df32f7fb2c0cd6295239471822f4032b8223c0e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Dec 2024 22:03:52 -0700 Subject: [PATCH 10/21] Pin some runner images (#9717) For the larger test/build jobs use some variables in the `*.js` files calculating the matrix to pin the images to fixed versions of GitHub actions images. For the `main.yml` file instead of changing everything over to a pin only do the ones that are currently failing on the `ubuntu-24.04` update. The hope is that there's only a few locations to update pinned versions in the future, and we'll need to keep an eye on CI warnings and such to know when to update these pins in the future. --- .github/workflows/main.yml | 4 ++-- ci/build-build-matrix.js | 28 ++++++++++++++++------------ ci/build-test-matrix.js | 26 +++++++++++++++----------- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dfab1f43af94..c9aab08a996b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -80,7 +80,7 @@ jobs: # Note that `wasmtime-platform.h` is excluded here as it's auto-generated. clangformat: name: Clang format - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # FIXME: fails on `ubuntu-24.04` right now steps: - uses: actions/checkout@v4 with: @@ -847,7 +847,7 @@ jobs: needs: determine if: needs.determine.outputs.run-dwarf name: Test DWARF debugging - runs-on: 'ubuntu-latest' + runs-on: ubuntu-22.04 # FIXME: fails on `ubuntu-24.04` right now steps: - uses: actions/checkout@v4 with: diff --git a/ci/build-build-matrix.js b/ci/build-build-matrix.js index 4cda1079e535..a52c11315d07 100644 --- a/ci/build-build-matrix.js +++ b/ci/build-build-matrix.js @@ -4,69 +4,73 @@ // This is a separate script primarily to write out all the release // targets/platforms once and then duplicate them all with a "min" build. +const ubuntu = 'ubuntu-22.04'; +const windows = 'windows-2022'; +const macos = 'macos-14'; + const array = [ { // The name of the build which shows up in the name of the artifact for // Wasmtime's github releases. "build": "x86_64-linux", // The GitHub Actions platform that this build runs on - "os": "ubuntu-latest", + "os": ubuntu, // The Rust target that will be used for the build. "target": "x86_64-unknown-linux-gnu", }, { "build": "aarch64-linux", - "os": "ubuntu-latest", + "os": ubuntu, "target": "aarch64-unknown-linux-gnu", }, { "build": "s390x-linux", - "os": "ubuntu-latest", + "os": ubuntu, "target": "s390x-unknown-linux-gnu", }, { "build": "riscv64gc-linux", - "os": "ubuntu-latest", + "os": ubuntu, "target": "riscv64gc-unknown-linux-gnu", }, { "build": "x86_64-macos", - "os": "macos-latest", + "os": macos, "target": "x86_64-apple-darwin", }, { "build": "aarch64-macos", - "os": "macos-latest", + "os": macos, "target": "aarch64-apple-darwin", }, { "build": "x86_64-windows", - "os": "windows-latest", + "os": windows, "target": "x86_64-pc-windows-msvc", }, { "build": "x86_64-mingw", - "os": "windows-latest", + "os": windows, "target": "x86_64-pc-windows-gnu", }, { "build": "aarch64-android", - "os": "ubuntu-latest", + "os": ubuntu, "target": "aarch64-linux-android", }, { "build": "x86_64-android", - "os": "ubuntu-latest", + "os": ubuntu, "target": "x86_64-linux-android", }, { "build": "x86_64-musl", - "os": "ubuntu-latest", + "os": ubuntu, "target": "x86_64-unknown-linux-musl", }, { "build": "aarch64-windows", - "os": "windows-latest", + "os": windows, "target": "aarch64-pc-windows-msvc", }, ]; diff --git a/ci/build-test-matrix.js b/ci/build-test-matrix.js index 09e5965b5886..f2ed1735ce4a 100644 --- a/ci/build-test-matrix.js +++ b/ci/build-test-matrix.js @@ -15,11 +15,15 @@ const GENERIC_BUCKETS = 3; // compile-and-test crates. const SINGLE_CRATE_BUCKETS = ["wasmtime", "wasmtime-cli", "wasmtime-wasi"]; +const ubuntu = 'ubuntu-22.04'; +const windows = 'windows-2022'; +const macos = 'macos-14'; + // This is the small, fast-to-execute matrix we use for PRs before they enter // the merge queue. Same schema as `FULL_MATRIX`. const FAST_MATRIX = [ { - "os": "ubuntu-latest", + "os": ubuntu, "name": "Test Linux x86_64", "filter": "linux-x64", "isa": "x64", @@ -64,14 +68,14 @@ function supports32Bit(pkg) { const FULL_MATRIX = [ ...FAST_MATRIX, { - "os": "ubuntu-latest", + "os": ubuntu, "name": "Test MSRV on Linux x86_64", "filter": "linux-x64", "isa": "x64", "rust": "msrv", }, { - "os": "ubuntu-latest", + "os": ubuntu, "name": "Test Linux x86_64 with MPK", "filter": "linux-x64", "isa": "x64" @@ -82,24 +86,24 @@ const FULL_MATRIX = [ "filter": "macos-x64", }, { - "os": "macos-14", + "os": macos, "name": "Test macOS arm64", "filter": "macos-arm64", "target": "aarch64-apple-darwin", }, { - "os": "windows-latest", + "os": windows, "name": "Test Windows MSVC x86_64", "filter": "windows-x64", }, { - "os": "windows-latest", + "os": windows, "target": "x86_64-pc-windows-gnu", "name": "Test Windows MinGW x86_64", "filter": "mingw-x64" }, { - "os": "ubuntu-latest", + "os": ubuntu, "target": "aarch64-unknown-linux-gnu", "gcc_package": "gcc-aarch64-linux-gnu", "gcc": "aarch64-linux-gnu-gcc", @@ -110,7 +114,7 @@ const FULL_MATRIX = [ "isa": "aarch64", }, { - "os": "ubuntu-latest", + "os": ubuntu, "target": "s390x-unknown-linux-gnu", "gcc_package": "gcc-s390x-linux-gnu", "gcc": "s390x-linux-gnu-gcc", @@ -121,7 +125,7 @@ const FULL_MATRIX = [ "isa": "s390x" }, { - "os": "ubuntu-latest", + "os": ubuntu, "target": "riscv64gc-unknown-linux-gnu", "gcc_package": "gcc-riscv64-linux-gnu", "gcc": "riscv64-linux-gnu-gcc", @@ -134,7 +138,7 @@ const FULL_MATRIX = [ { "name": "Tests on i686-unknown-linux-gnu", "32-bit": true, - "os": "ubuntu-latest", + "os": ubuntu, "target": "i686-unknown-linux-gnu", "gcc_package": "gcc-i686-linux-gnu", "gcc": "i686-linux-gnu-gcc", @@ -142,7 +146,7 @@ const FULL_MATRIX = [ { "name": "Tests on armv7-unknown-linux-gnueabihf", "32-bit": true, - "os": "ubuntu-latest", + "os": ubuntu, "target": "armv7-unknown-linux-gnueabihf", "gcc_package": "gcc-arm-linux-gnueabihf", "gcc": "arm-linux-gnueabihf-gcc", From 45869dc6ab1fb5287626875c5627169203b07e45 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Dec 2024 08:29:37 -0700 Subject: [PATCH 11/21] Test out GitHub build attestations (#9711) Unsure what will happen, but it probably can't break things too much... right? cc #9698 --- .github/workflows/publish-artifacts.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/publish-artifacts.yml b/.github/workflows/publish-artifacts.yml index 4a108ff083a4..3f6565e2f28a 100644 --- a/.github/workflows/publish-artifacts.yml +++ b/.github/workflows/publish-artifacts.yml @@ -6,6 +6,8 @@ on: permissions: contents: write + id-token: write + attestations: write jobs: publish: @@ -34,6 +36,10 @@ jobs: with: path: "./gh-pages/gh-pages" + - uses: actions/attest-build-provenance@v1 + with: + subject-path: 'dist/*' + - run: npm install --production working-directory: .github/actions/github-release - name: Publish Release From f0a15de5d73e155164803b847c71fa71e797b21e Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Wed, 4 Dec 2024 16:30:37 +0100 Subject: [PATCH 12/21] [s390x] Fix SP unwind rule for the tail-call ABI (#9725) On s390x, the unwound SP is always at current CFA - 160. Therefore, the default rule used on most other platforms (which sets the unwound SP to the current CFA) is incorrect, so we need to provide an explicit DWARF CFI rule to unwind SP. With the platform ABI, the caller's SP is always stored in the register save area like other call-saved GPRs, so we can simply use a normal DW_CFA_offset rule. However, with the new tail-call ABI, the value saved in that slot is incorrect - it is not corrected for the incoming tail-call stack arguments that will have been removed as the tail call returns. To fix this without introducing unnecessary run-time overhead, we can simply use a DW_CFA_val_offset rule that will set the unwound SP to CFA - 160, which is always correct. However, the current UnwindInst abstraction does not allow any way to generate this DWARF CFI instruction. Therefore, we introduce a new UnwindInst::RegStackOffset rule for this purpose. Fixes: https://github.com/bytecodealliance/wasmtime/issues/9719 --- cranelift/codegen/src/isa/s390x/abi.rs | 19 +++++++++++++++++-- cranelift/codegen/src/isa/unwind.rs | 9 +++++++++ cranelift/codegen/src/isa/unwind/systemv.rs | 13 +++++++++++++ cranelift/codegen/src/isa/unwind/winarm64.rs | 3 +++ cranelift/codegen/src/isa/unwind/winx64.rs | 3 +++ 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/cranelift/codegen/src/isa/s390x/abi.rs b/cranelift/codegen/src/isa/s390x/abi.rs index 986663160300..57b213e4ea81 100644 --- a/cranelift/codegen/src/isa/s390x/abi.rs +++ b/cranelift/codegen/src/isa/s390x/abi.rs @@ -738,14 +738,29 @@ impl ABIMachineSpec for S390xMachineDeps { // Use STMG to save clobbered GPRs into save area. // Note that we always save SP (%r15) here if anything is saved. if let Some((first_clobbered_gpr, _)) = get_clobbered_gprs(frame_layout) { + let mut last_clobbered_gpr = 15; let offset = 8 * first_clobbered_gpr as i64 + incoming_tail_args_size as i64; insts.push(Inst::StoreMultiple64 { rt: gpr(first_clobbered_gpr), - rt2: gpr(15), + rt2: gpr(last_clobbered_gpr), mem: MemArg::reg_plus_off(stack_reg(), offset, MemFlags::trusted()), }); if flags.unwind_info() { - for i in first_clobbered_gpr..16 { + // Normally, we instruct the unwinder to restore the stack pointer + // from its slot in the save area. However, if we have incoming + // tail-call arguments, the value saved in that slot is incorrect. + // In that case, we instead instruct the unwinder to compute the + // unwound SP relative to the current CFA, as CFA == SP + 160. + if incoming_tail_args_size != 0 { + insts.push(Inst::Unwind { + inst: UnwindInst::RegStackOffset { + clobber_offset: frame_layout.clobber_size, + reg: gpr(last_clobbered_gpr).to_real_reg().unwrap(), + }, + }); + last_clobbered_gpr = last_clobbered_gpr - 1; + } + for i in first_clobbered_gpr..(last_clobbered_gpr + 1) { insts.push(Inst::Unwind { inst: UnwindInst::SaveReg { clobber_offset: frame_layout.clobber_size + (i * 8) as u32, diff --git a/cranelift/codegen/src/isa/unwind.rs b/cranelift/codegen/src/isa/unwind.rs index 305e7b4704a2..ada37b03ccbb 100644 --- a/cranelift/codegen/src/isa/unwind.rs +++ b/cranelift/codegen/src/isa/unwind.rs @@ -196,6 +196,15 @@ pub enum UnwindInst { /// The saved register. reg: RealReg, }, + /// Computes the value of the given register in the caller as stack offset. + /// Typically used to unwind the stack pointer if the default rule does not apply. + /// The `clobber_offset` is computed the same way as for the `SaveReg` rule. + RegStackOffset { + /// The offset from the start of the clobber area to this register's value. + clobber_offset: u32, + /// The register whose value is to be set. + reg: RealReg, + }, /// Defines if the aarch64-specific pointer authentication available for ARM v8.3+ devices /// is enabled for certain pointers or not. Aarch64SetPointerAuth { diff --git a/cranelift/codegen/src/isa/unwind/systemv.rs b/cranelift/codegen/src/isa/unwind/systemv.rs index ba77103394c5..5a721fbd8232 100644 --- a/cranelift/codegen/src/isa/unwind/systemv.rs +++ b/cranelift/codegen/src/isa/unwind/systemv.rs @@ -247,6 +247,19 @@ pub(crate) fn create_unwind_info_from_insts>( let off = (clobber_offset as i32) - (clobber_offset_to_cfa as i32); instructions.push((instruction_offset, CallFrameInstruction::Offset(reg, off))); } + &UnwindInst::RegStackOffset { + clobber_offset, + reg, + } => { + let reg = mr + .map(reg.into()) + .map_err(|e| CodegenError::RegisterMappingError(e))?; + let off = (clobber_offset as i32) - (clobber_offset_to_cfa as i32); + instructions.push(( + instruction_offset, + CallFrameInstruction::ValOffset(reg, off), + )); + } &UnwindInst::Aarch64SetPointerAuth { return_addresses } => { instructions.push(( instruction_offset, diff --git a/cranelift/codegen/src/isa/unwind/winarm64.rs b/cranelift/codegen/src/isa/unwind/winarm64.rs index a4ab147fb439..58a1b38b9df4 100644 --- a/cranelift/codegen/src/isa/unwind/winarm64.rs +++ b/cranelift/codegen/src/isa/unwind/winarm64.rs @@ -301,6 +301,9 @@ pub(crate) fn create_unwind_info_from_insts( } } } + &UnwindInst::RegStackOffset { .. } => { + unreachable!("only supported with DWARF"); + } &UnwindInst::Aarch64SetPointerAuth { return_addresses } => { assert!( return_addresses, diff --git a/cranelift/codegen/src/isa/unwind/winx64.rs b/cranelift/codegen/src/isa/unwind/winx64.rs index 8a23494b1f43..55014518b54f 100644 --- a/cranelift/codegen/src/isa/unwind/winx64.rs +++ b/cranelift/codegen/src/isa/unwind/winx64.rs @@ -285,6 +285,9 @@ pub(crate) fn create_unwind_info_from_insts { + unreachable!("only supported with DWARF"); + } &UnwindInst::Aarch64SetPointerAuth { .. } => { unreachable!("no aarch64 on x64"); } From 06103f74908411fde3fa28500e15eb298dcb1d74 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Dec 2024 09:28:57 -0700 Subject: [PATCH 13/21] Update build/test images to Ubuntu 24.04 (#9728) Manually updating some images after the pinning in #9717. There's a few more images after this but this should be the lion's share of the update. prtest:full --- .github/workflows/main.yml | 5 ++++- ci/build-build-matrix.js | 2 +- ci/build-test-matrix.js | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c9aab08a996b..5718ccf78fd2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -690,7 +690,7 @@ jobs: set -ex sudo apt-get update - sudo apt-get install -y ${{ matrix.gcc_package }} ninja-build + sudo apt-get install -y ${{ matrix.gcc_package }} # Configure Cargo for cross compilation and tell it how it can run # cross executables @@ -723,6 +723,9 @@ jobs: exit 0 fi + # Install build dependencies of QEMU itself. + sudo apt-get install -y libglib2.0-dev ninja-build + # Download and build qemu from source since the most recent release is # way faster at arm emulation than the current version github actions' # ubuntu image uses. Disable as much as we can to get it to build diff --git a/ci/build-build-matrix.js b/ci/build-build-matrix.js index a52c11315d07..135e78f6952f 100644 --- a/ci/build-build-matrix.js +++ b/ci/build-build-matrix.js @@ -4,7 +4,7 @@ // This is a separate script primarily to write out all the release // targets/platforms once and then duplicate them all with a "min" build. -const ubuntu = 'ubuntu-22.04'; +const ubuntu = 'ubuntu-24.04'; const windows = 'windows-2022'; const macos = 'macos-14'; diff --git a/ci/build-test-matrix.js b/ci/build-test-matrix.js index f2ed1735ce4a..3cf7e2687d8c 100644 --- a/ci/build-test-matrix.js +++ b/ci/build-test-matrix.js @@ -15,7 +15,7 @@ const GENERIC_BUCKETS = 3; // compile-and-test crates. const SINGLE_CRATE_BUCKETS = ["wasmtime", "wasmtime-cli", "wasmtime-wasi"]; -const ubuntu = 'ubuntu-22.04'; +const ubuntu = 'ubuntu-24.04'; const windows = 'windows-2022'; const macos = 'macos-14'; From da7c53b78716f14e091bb643b84b7be0931548ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Cabrera?= Date: Wed, 4 Dec 2024 11:53:36 -0500 Subject: [PATCH 14/21] winch: Prefer using `Context::without` for fuel checks (#9709) This commit is a follow-up to https://github.com/bytecodealliance/wasmtime/pull/9472. It ensures that the fuel checking code makes use of `Context::without` to retrieve the current fuel register. Even though no issues have been found, it is preferable to use `Context::without` in scenarios in which we have to introduce special out-of-band control flow and function calls to ensure that all the register allocation invariants are respected i.e., avoid holding onto to registers that: are not in the stack and that might be needed for function calls. --- winch/codegen/src/codegen/mod.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/winch/codegen/src/codegen/mod.rs b/winch/codegen/src/codegen/mod.rs index 08a306def6c6..a3721867b2c5 100644 --- a/winch/codegen/src/codegen/mod.rs +++ b/winch/codegen/src/codegen/mod.rs @@ -944,7 +944,14 @@ where /// performing a zero-comparison with the number of units stored in /// `VMRuntimeLimits`. pub fn emit_fuel_check(&mut self) { - let fuel_var = self.emit_load_fuel_consumed(); + let out_of_fuel = self.env.builtins.out_of_gas::(); + let fuel_var = + self.context + .without::(&out_of_fuel.sig().regs, self.masm, |cx, masm| { + cx.any_gpr(masm) + }); + + self.emit_load_fuel_consumed(fuel_var); let continuation = self.masm.get_label(); // Spill locals and registers to avoid conflicts at the out-of-fuel @@ -960,7 +967,6 @@ where OperandSize::S64, ); // Out-of-fuel branch. - let out_of_fuel = self.env.builtins.out_of_gas::(); FnCall::emit::( &mut self.env, self.masm, @@ -1018,10 +1024,9 @@ where /// Emits a series of instructions that load the `fuel_consumed` field from /// `VMRuntimeLimits`. - fn emit_load_fuel_consumed(&mut self) -> Reg { + fn emit_load_fuel_consumed(&mut self, fuel_var: Reg) { let limits_offset = self.env.vmoffsets.ptr.vmctx_runtime_limits(); let fuel_offset = self.env.vmoffsets.ptr.vmruntime_limits_fuel_consumed(); - let fuel_var = self.context.any_gpr(self.masm); self.masm.load_ptr( self.masm.address_at_vmctx(u32::from(limits_offset)), writable!(fuel_var), @@ -1033,8 +1038,6 @@ where // Fuel is an i64. OperandSize::S64, ); - - fuel_var } /// Hook to handle fuel before visiting an operator. From 94da01293f3553040deccba58f86c36b2e37a1a4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Dec 2024 10:05:49 -0700 Subject: [PATCH 15/21] Update clang-format to LLVM 18 (#9729) Update from Ubuntu 22.04 to Ubuntu 24.04, and update the version of clang used accordingly. --- .github/workflows/main.yml | 4 ++-- crates/wasmtime/src/runtime/vm/helpers.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5718ccf78fd2..baa49cf169bf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -80,7 +80,7 @@ jobs: # Note that `wasmtime-platform.h` is excluded here as it's auto-generated. clangformat: name: Clang format - runs-on: ubuntu-22.04 # FIXME: fails on `ubuntu-24.04` right now + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: @@ -89,7 +89,7 @@ jobs: git ls-files '*.h' '*.c' '*.cpp' | \ grep -v wasmtime-platform.h | \ grep -v wasm.h | \ - xargs clang-format-15 --dry-run --Werror --verbose + xargs clang-format-18 --dry-run --Werror --verbose # common logic to cancel the entire run if this job fails - run: gh run cancel ${{ github.run_id }} diff --git a/crates/wasmtime/src/runtime/vm/helpers.c b/crates/wasmtime/src/runtime/vm/helpers.c index cfae8f7c88e2..a3b5dc28287d 100644 --- a/crates/wasmtime/src/runtime/vm/helpers.c +++ b/crates/wasmtime/src/runtime/vm/helpers.c @@ -182,7 +182,7 @@ __declspec(dllexport) // important. __attribute__((weak)) #endif - struct JITDescriptor __jit_debug_descriptor = {1, 0, NULL, NULL}; +struct JITDescriptor __jit_debug_descriptor = {1, 0, NULL, NULL}; struct JITDescriptor *VERSIONED_SYMBOL(wasmtime_jit_debug_descriptor)() { return &__jit_debug_descriptor; From 350a6e21662b0eb686302aabf2f1db97aef61973 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Dec 2024 10:18:05 -0700 Subject: [PATCH 16/21] pulley: Fill out more bits and pieces of stack allocation (#9718) * pulley: Fill out more bits and pieces of stack allocation * Use `push_frame` and `pop_frame` in the Cranelift backend. * Use dedicated instructions for modifying the stack pointer * decrementing the stack pointer is always checked * incrementing the stack pointer is checked in debug mode * Disregard stack probes and stack_limit checks as they're both unnecessary for Pulley (all stack allocations are checked). * Fix pulley fuzz * Fix some tests from a rebase * Fix more tests --- .../codegen/src/isa/pulley_shared/abi.rs | 111 ++------- .../codegen/src/isa/pulley_shared/inst.isle | 6 + .../src/isa/pulley_shared/inst/emit.rs | 5 + .../codegen/src/isa/pulley_shared/inst/mod.rs | 12 + .../filetests/isa/pulley32/call.clif | 190 ++++----------- .../filetests/isa/pulley32/special_regs.clif | 66 +---- .../filetests/isa/pulley32/stack_addr.clif | 34 +-- .../filetests/isa/pulley64/call.clif | 226 ++++-------------- .../isa/pulley64/call_indirect_host.clif | 22 +- .../filetests/isa/pulley64/special_regs.clif | 67 +----- .../filetests/isa/pulley64/stack_addr.clif | 34 +-- crates/cranelift/src/compiler.rs | 40 ++-- crates/cranelift/src/func_environ.rs | 8 + pulley/fuzz/src/interp.rs | 2 + pulley/src/interp.rs | 14 ++ pulley/src/lib.rs | 10 +- tests/disas/pulley/br_table.wat | 37 +-- tests/disas/pulley/call.wat | 16 ++ tests/disas/pulley/i32_add/const.wat | 11 +- tests/disas/pulley/loads.wat | 34 +-- 20 files changed, 279 insertions(+), 666 deletions(-) create mode 100644 tests/disas/pulley/call.wat diff --git a/cranelift/codegen/src/isa/pulley_shared/abi.rs b/cranelift/codegen/src/isa/pulley_shared/abi.rs index 15b6e8f41a6c..3d2bfe43f8b2 100644 --- a/cranelift/codegen/src/isa/pulley_shared/abi.rs +++ b/cranelift/codegen/src/isa/pulley_shared/abi.rs @@ -220,18 +220,8 @@ where ] } - fn gen_stack_lower_bound_trap(limit_reg: Reg) -> SmallInstVec { - smallvec![Inst::TrapIf { - cond: ir::condcodes::IntCC::UnsignedLessThan, - size: match P::pointer_width() { - super::PointerWidth::PointerWidth32 => OperandSize::Size32, - super::PointerWidth::PointerWidth64 => OperandSize::Size64, - }, - src1: limit_reg.try_into().unwrap(), - src2: pulley_interpreter::regs::XReg::sp.into(), - code: ir::TrapCode::STACK_OVERFLOW, - } - .into()] + fn gen_stack_lower_bound_trap(_limit_reg: Reg) -> SmallInstVec { + unimplemented!("pulley shouldn't need stack bound checks") } fn gen_get_stack_addr(mem: StackAMode, dst: Writable) -> Self::I { @@ -258,29 +248,21 @@ where return smallvec![]; } - let temp = WritableXReg::try_from(writable_spilltmp_reg()).unwrap(); - - let imm = if let Ok(x) = i8::try_from(amount) { - Inst::Xconst8 { dst: temp, imm: x }.into() - } else if let Ok(x) = i16::try_from(amount) { - Inst::Xconst16 { dst: temp, imm: x }.into() + let inst = if amount < 0 { + let amount = amount.checked_neg().unwrap(); + if let Ok(amt) = u32::try_from(amount) { + Inst::StackAlloc32 { amt } + } else { + unreachable!() + } } else { - Inst::Xconst32 { - dst: temp, - imm: amount, + if let Ok(amt) = u32::try_from(amount) { + Inst::StackFree32 { amt } + } else { + unreachable!() } - .into() }; - - smallvec![ - imm, - Inst::Xadd32 { - dst: WritableXReg::try_from(writable_stack_reg()).unwrap(), - src1: XReg::new(stack_reg()).unwrap(), - src2: temp.to_reg(), - } - .into() - ] + smallvec![inst.into()] } fn gen_prologue_frame_setup( @@ -292,29 +274,7 @@ where let mut insts = SmallVec::new(); if frame_layout.setup_area_size > 0 { - // sp = sub sp, 16 ;; alloc stack space for frame pointer and return address. - // store sp+8, lr ;; save return address. - // store sp, fp ;; save old fp. - // mov sp, fp ;; set fp to sp. - insts.extend(Self::gen_sp_reg_adjust(-16)); - insts.push( - Inst::gen_store( - Amode::SpOffset { offset: 8 }, - lr_reg(), - I64, - MemFlags::trusted(), - ) - .into(), - ); - insts.push( - Inst::gen_store( - Amode::SpOffset { offset: 0 }, - fp_reg(), - I64, - MemFlags::trusted(), - ) - .into(), - ); + insts.push(Inst::PushFrame.into()); if flags.unwind_info() { insts.push( Inst::Unwind { @@ -325,13 +285,6 @@ where .into(), ); } - insts.push( - Inst::Xmov { - dst: Writable::from_reg(XReg::new(fp_reg()).unwrap()), - src: XReg::new(stack_reg()).unwrap(), - } - .into(), - ); } insts @@ -347,25 +300,7 @@ where let mut insts = SmallVec::new(); if frame_layout.setup_area_size > 0 { - insts.push( - Inst::gen_load( - writable_lr_reg(), - Amode::SpOffset { offset: 8 }, - I64, - MemFlags::trusted(), - ) - .into(), - ); - insts.push( - Inst::gen_load( - writable_fp_reg(), - Amode::SpOffset { offset: 0 }, - I64, - MemFlags::trusted(), - ) - .into(), - ); - insts.extend(Self::gen_sp_reg_adjust(16)); + insts.push(Inst::PopFrame.into()); } if frame_layout.tail_args_size > 0 { @@ -386,7 +321,8 @@ where } fn gen_probestack(_insts: &mut SmallInstVec, _frame_size: u32) { - todo!() + // Pulley doesn't implement stack probes since all stack pointer + // decrements are checked already. } fn gen_clobber_save( @@ -582,11 +518,15 @@ where } fn get_number_of_spillslots_for_value( - _rc: RegClass, + rc: RegClass, _target_vector_bytes: u32, _isa_flags: &PulleyFlags, ) -> u32 { - todo!() + match rc { + RegClass::Int => 1, + RegClass::Float => todo!(), + RegClass::Vector => unreachable!(), + } } fn get_machine_env(_flags: &settings::Flags, _call_conv: isa::CallConv) -> &MachineEnv { @@ -651,7 +591,8 @@ where _frame_size: u32, _guard_size: u32, ) { - todo!() + // Pulley doesn't need inline probestacks because it always checks stack + // decrements. } } diff --git a/cranelift/codegen/src/isa/pulley_shared/inst.isle b/cranelift/codegen/src/isa/pulley_shared/inst.isle index 298c7d5eb253..6a15e140148c 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst.isle +++ b/cranelift/codegen/src/isa/pulley_shared/inst.isle @@ -120,6 +120,12 @@ (BitcastIntFromFloat64 (dst WritableXReg) (src FReg)) (BitcastFloatFromInt32 (dst WritableFReg) (src XReg)) (BitcastFloatFromInt64 (dst WritableFReg) (src XReg)) + + ;; Stack manipulations + (PushFrame) + (PopFrame) + (StackAlloc32 (amt u32)) + (StackFree32 (amt u32)) ) ) diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs index 8806737b7cc4..b103e4fee04d 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs @@ -548,6 +548,11 @@ fn pulley_emit

( // the assertion that we're always under worst-case-size. *start_offset = sink.cur_offset(); } + + Inst::PushFrame => enc::push_frame(sink), + Inst::PopFrame => enc::pop_frame(sink), + Inst::StackAlloc32 { amt } => enc::stack_alloc32(sink, *amt), + Inst::StackFree32 { amt } => enc::stack_free32(sink, *amt), } } diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs b/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs index e81bc63109b8..7b8768c1ec99 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs @@ -252,6 +252,9 @@ fn pulley_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { Inst::BrTable { idx, .. } => { collector.reg_use(idx); } + + Inst::StackAlloc32 { .. } | Inst::StackFree32 { .. } | Inst::PushFrame | Inst::PopFrame => { + } } } @@ -862,6 +865,15 @@ impl Inst { let idx = format_reg(**idx); format!("br_table {idx} {default:?} {targets:?}") } + + Inst::StackAlloc32 { amt } => { + format!("stack_alloc32 {amt:#x}") + } + Inst::StackFree32 { amt } => { + format!("stack_free32 {amt:#x}") + } + Inst::PushFrame => format!("push_frame"), + Inst::PopFrame => format!("pop_frame"), } } } diff --git a/cranelift/filetests/filetests/isa/pulley32/call.clif b/cranelift/filetests/filetests/isa/pulley32/call.clif index b458e181a31c..6a162d085b50 100644 --- a/cranelift/filetests/filetests/isa/pulley32/call.clif +++ b/cranelift/filetests/filetests/isa/pulley32/call.clif @@ -13,34 +13,20 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; x0 = xconst8 0 ; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x0 = xconst8 1 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xconst8 x0, 0 -; call 0x0 // target = 0x13 +; call 0x0 // target = 0x4 ; xconst8 x0, 1 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret function %colocated_args_i32_rets_i32() -> i32 { @@ -54,34 +40,20 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; x0 = xconst8 0 ; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x0 = xconst8 1 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xconst8 x0, 0 -; call 0x0 // target = 0x13 +; call 0x0 // target = 0x4 ; xconst8 x0, 1 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret function %colocated_args_i64_i32_i64_i32() { @@ -97,38 +69,24 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; x0 = xconst8 0 ; x1 = xconst8 1 ; x2 = xconst8 2 ; x3 = xconst8 3 ; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [65535, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xconst8 x0, 0 ; xconst8 x1, 1 ; xconst8 x2, 2 ; xconst8 x3, 3 -; call 0x0 // target = 0x1c -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; call 0x0 // target = 0xd +; pop_frame ; ret function %colocated_rets_i64_i64_i64_i64() -> i64 { @@ -143,36 +101,22 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; call CallInfo { dest: TestCase(%g), uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }, CallRetPair { vreg: Writable { reg: p1i }, preg: p1i }, CallRetPair { vreg: Writable { reg: p2i }, preg: p2i }, CallRetPair { vreg: Writable { reg: p3i }, preg: p3i }], clobbers: PRegSet { bits: [65520, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x4 = xadd64 x0, x2 ; x3 = xadd64 x1, x3 ; x0 = xadd64 x4, x3 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp -; call 0x0 // target = 0x10 +; push_frame +; call 0x0 // target = 0x1 ; xadd64 x4, x0, x2 ; xadd64 x3, x1, x3 ; xadd64 x0, x4, x3 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret function %colocated_stack_args() { @@ -185,13 +129,8 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 -; x30 = xconst8 -48 -; x27 = xadd32 x27, x30 +; push_frame +; stack_alloc32 0x30 ; block0: ; x15 = xconst8 0 ; store64 OutgoingArg(0), x15 // flags = notrap aligned @@ -216,22 +155,13 @@ block0: ; x13 = xmov x15 ; x14 = xmov x15 ; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }, CallArgPair { vreg: p10i, preg: p10i }, CallArgPair { vreg: p11i, preg: p11i }, CallArgPair { vreg: p12i, preg: p12i }, CallArgPair { vreg: p13i, preg: p13i }, CallArgPair { vreg: p14i, preg: p14i }, CallArgPair { vreg: p15i, preg: p15i }], defs: [], clobbers: PRegSet { bits: [65535, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } -; x30 = xconst8 48 -; x27 = xadd32 x27, x30 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; stack_free32 0x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp -; xconst8 spilltmp0, -48 -; xadd32 sp, sp, spilltmp0 +; push_frame +; stack_alloc32 48 ; xconst8 x15, 0 ; store64 sp, x15 ; store64_offset8 sp, 8, x15 @@ -254,13 +184,9 @@ block0: ; xmov x12, x15 ; xmov x13, x15 ; xmov x14, x15 -; call 0x0 // target = 0x5d -; xconst8 spilltmp0, 48 -; xadd32 sp, sp, spilltmp0 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; call 0x0 // target = 0x4d +; stack_free32 48 +; pop_frame ; ret function %colocated_stack_rets() -> i64 { @@ -300,13 +226,8 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 -; x30 = xconst8 -64 -; x27 = xadd32 x27, x30 +; push_frame +; stack_alloc32 0x40 ; store64 sp+56, x18 // flags = notrap aligned ; store64 sp+48, x20 // flags = notrap aligned ; block0: @@ -346,26 +267,17 @@ block0: ; x0 = xadd64 x14, x13 ; x18 = load64_u sp+56 // flags = notrap aligned ; x20 = load64_u sp+48 // flags = notrap aligned -; x30 = xconst8 64 -; x27 = xadd32 x27, x30 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; stack_free32 0x40 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp -; xconst8 spilltmp0, -64 -; xadd32 sp, sp, spilltmp0 +; push_frame +; stack_alloc32 64 ; store64_offset8 sp, 56, x18 ; store64_offset8 sp, 48, x20 ; xmov x0, sp -; call 0x0 // target = 0x21 +; call 0x0 // target = 0x11 ; xmov x18, x13 ; xmov x20, x11 ; load64 x24, sp @@ -400,12 +312,8 @@ block0: ; xadd64 x0, x14, x13 ; load64_offset8 x18, sp, 56 ; load64_offset8 x20, sp, 48 -; xconst8 spilltmp0, 64 -; xadd32 sp, sp, spilltmp0 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; stack_free32 64 +; pop_frame ; ret function %call_indirect(i32) -> i64 { @@ -417,29 +325,15 @@ block0(v0: i32): } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; indirect_call x0, CallInfo { dest: XReg(p0i), uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Tail, caller_conv: Fast, callee_pop_size: 0 } -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; call_indirect x0 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret diff --git a/cranelift/filetests/filetests/isa/pulley32/special_regs.clif b/cranelift/filetests/filetests/isa/pulley32/special_regs.clif index 8b7a8beb8404..bdad9d89b973 100644 --- a/cranelift/filetests/filetests/isa/pulley32/special_regs.clif +++ b/cranelift/filetests/filetests/isa/pulley32/special_regs.clif @@ -9,30 +9,16 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; xmov x0, x27 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xmov x0, sp -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret function %get_frame_pointer() -> i32 { @@ -42,30 +28,16 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; xmov x0, x29 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xmov x0, fp -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret function %get_return_address() -> i32 { @@ -75,29 +47,15 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; xmov x0, x28 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xmov x0, lr -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret diff --git a/cranelift/filetests/filetests/isa/pulley32/stack_addr.clif b/cranelift/filetests/filetests/isa/pulley32/stack_addr.clif index c7c8261c14ad..ef6087e21c79 100644 --- a/cranelift/filetests/filetests/isa/pulley32/stack_addr.clif +++ b/cranelift/filetests/filetests/isa/pulley32/stack_addr.clif @@ -9,37 +9,19 @@ block0(): } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 +; push_frame +; stack_alloc32 0x10 ; block0: ; x0 = load_addr Slot(0) -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; stack_free32 0x10 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 +; push_frame +; stack_alloc32 16 ; xmov x0, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; stack_free32 16 +; pop_frame ; ret diff --git a/cranelift/filetests/filetests/isa/pulley64/call.clif b/cranelift/filetests/filetests/isa/pulley64/call.clif index c3829b55cb7f..9470d04a4a02 100644 --- a/cranelift/filetests/filetests/isa/pulley64/call.clif +++ b/cranelift/filetests/filetests/isa/pulley64/call.clif @@ -13,34 +13,20 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; x0 = xconst8 0 ; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x0 = xconst8 1 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xconst8 x0, 0 -; call 0x0 // target = 0x13 +; call 0x0 // target = 0x4 ; xconst8 x0, 1 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret function %colocated_args_i32_rets_i32() -> i32 { @@ -54,34 +40,20 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; x0 = xconst8 0 ; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x0 = xconst8 1 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xconst8 x0, 0 -; call 0x0 // target = 0x13 +; call 0x0 // target = 0x4 ; xconst8 x0, 1 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret function %colocated_args_i64_i32_i64_i32() { @@ -97,38 +69,24 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; x0 = xconst8 0 ; x1 = xconst8 1 ; x2 = xconst8 2 ; x3 = xconst8 3 ; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [65535, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xconst8 x0, 0 ; xconst8 x1, 1 ; xconst8 x2, 2 ; xconst8 x3, 3 -; call 0x0 // target = 0x1c -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; call 0x0 // target = 0xd +; pop_frame ; ret function %colocated_rets_i64_i64_i64_i64() -> i64 { @@ -143,36 +101,22 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; call CallInfo { dest: TestCase(%g), uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }, CallRetPair { vreg: Writable { reg: p1i }, preg: p1i }, CallRetPair { vreg: Writable { reg: p2i }, preg: p2i }, CallRetPair { vreg: Writable { reg: p3i }, preg: p3i }], clobbers: PRegSet { bits: [65520, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x4 = xadd64 x0, x2 ; x3 = xadd64 x1, x3 ; x0 = xadd64 x4, x3 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp -; call 0x0 // target = 0x10 +; push_frame +; call 0x0 // target = 0x1 ; xadd64 x4, x0, x2 ; xadd64 x3, x1, x3 ; xadd64 x0, x4, x3 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret function %colocated_stack_args() { @@ -185,13 +129,8 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 -; x30 = xconst8 -48 -; x27 = xadd32 x27, x30 +; push_frame +; stack_alloc32 0x30 ; block0: ; x15 = xconst8 0 ; store64 OutgoingArg(0), x15 // flags = notrap aligned @@ -216,22 +155,13 @@ block0: ; x13 = xmov x15 ; x14 = xmov x15 ; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }, CallArgPair { vreg: p10i, preg: p10i }, CallArgPair { vreg: p11i, preg: p11i }, CallArgPair { vreg: p12i, preg: p12i }, CallArgPair { vreg: p13i, preg: p13i }, CallArgPair { vreg: p14i, preg: p14i }, CallArgPair { vreg: p15i, preg: p15i }], defs: [], clobbers: PRegSet { bits: [65535, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } -; x30 = xconst8 48 -; x27 = xadd32 x27, x30 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; stack_free32 0x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp -; xconst8 spilltmp0, -48 -; xadd32 sp, sp, spilltmp0 +; push_frame +; stack_alloc32 48 ; xconst8 x15, 0 ; store64 sp, x15 ; store64_offset8 sp, 8, x15 @@ -254,13 +184,9 @@ block0: ; xmov x12, x15 ; xmov x13, x15 ; xmov x14, x15 -; call 0x0 // target = 0x5d -; xconst8 spilltmp0, 48 -; xadd32 sp, sp, spilltmp0 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; call 0x0 // target = 0x4d +; stack_free32 48 +; pop_frame ; ret function %colocated_stack_rets() -> i64 { @@ -300,13 +226,8 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 -; x30 = xconst8 -64 -; x27 = xadd32 x27, x30 +; push_frame +; stack_alloc32 0x40 ; store64 sp+56, x18 // flags = notrap aligned ; store64 sp+48, x20 // flags = notrap aligned ; block0: @@ -346,26 +267,17 @@ block0: ; x0 = xadd64 x14, x13 ; x18 = load64_u sp+56 // flags = notrap aligned ; x20 = load64_u sp+48 // flags = notrap aligned -; x30 = xconst8 64 -; x27 = xadd32 x27, x30 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; stack_free32 0x40 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp -; xconst8 spilltmp0, -64 -; xadd32 sp, sp, spilltmp0 +; push_frame +; stack_alloc32 64 ; store64_offset8 sp, 56, x18 ; store64_offset8 sp, 48, x20 ; xmov x0, sp -; call 0x0 // target = 0x21 +; call 0x0 // target = 0x11 ; xmov x18, x13 ; xmov x20, x11 ; load64 x24, sp @@ -400,12 +312,8 @@ block0: ; xadd64 x0, x14, x13 ; load64_offset8 x18, sp, 56 ; load64_offset8 x20, sp, 48 -; xconst8 spilltmp0, 64 -; xadd32 sp, sp, spilltmp0 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; stack_free32 64 +; pop_frame ; ret function %call_indirect(i64) -> i64 { @@ -417,30 +325,16 @@ block0(v0: i64): } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; indirect_call x0, CallInfo { dest: XReg(p0i), uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Tail, caller_conv: Fast, callee_pop_size: 0 } -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; call_indirect x0 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret function %colocated_with_stack_args() { @@ -461,13 +355,8 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 -; x30 = xconst8 -64 -; x27 = xadd32 x27, x30 +; push_frame +; stack_alloc32 0x40 ; block0: ; x15 = xconst8 0 ; store64 OutgoingArg(0), x15 // flags = notrap aligned @@ -494,22 +383,13 @@ block0: ; x13 = xmov x15 ; x14 = xmov x15 ; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }, CallArgPair { vreg: p10i, preg: p10i }, CallArgPair { vreg: p11i, preg: p11i }, CallArgPair { vreg: p12i, preg: p12i }, CallArgPair { vreg: p13i, preg: p13i }, CallArgPair { vreg: p14i, preg: p14i }, CallArgPair { vreg: p15i, preg: p15i }], defs: [], clobbers: PRegSet { bits: [65535, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } -; x30 = xconst8 64 -; x27 = xadd32 x27, x30 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; stack_free32 0x40 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp -; xconst8 spilltmp0, -64 -; xadd32 sp, sp, spilltmp0 +; push_frame +; stack_alloc32 64 ; xconst8 x15, 0 ; store64 sp, x15 ; store64_offset8 sp, 8, x15 @@ -534,12 +414,8 @@ block0: ; xmov x12, x15 ; xmov x13, x15 ; xmov x14, x15 -; call 0x0 // target = 0x65 -; xconst8 spilltmp0, 64 -; xadd32 sp, sp, spilltmp0 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; call 0x0 // target = 0x55 +; stack_free32 64 +; pop_frame ; ret diff --git a/cranelift/filetests/filetests/isa/pulley64/call_indirect_host.clif b/cranelift/filetests/filetests/isa/pulley64/call_indirect_host.clif index 4592004936bb..0d2b206dc972 100644 --- a/cranelift/filetests/filetests/isa/pulley64/call_indirect_host.clif +++ b/cranelift/filetests/filetests/isa/pulley64/call_indirect_host.clif @@ -9,29 +9,15 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; indirect_call_host CallInfo { dest: User(userextname0), uses: [], defs: [], clobbers: PRegSet { bits: [65535, 65279, 4294967295, 0] }, callee_conv: SystemV, caller_conv: Fast, callee_pop_size: 0 } -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; call_indirect_host 0 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret diff --git a/cranelift/filetests/filetests/isa/pulley64/special_regs.clif b/cranelift/filetests/filetests/isa/pulley64/special_regs.clif index 97fa1d6b43c1..448a806b6500 100644 --- a/cranelift/filetests/filetests/isa/pulley64/special_regs.clif +++ b/cranelift/filetests/filetests/isa/pulley64/special_regs.clif @@ -9,30 +9,16 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; xmov x0, x27 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xmov x0, sp -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret function %get_frame_pointer() -> i64 { @@ -42,33 +28,18 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; xmov x0, x29 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xmov x0, fp -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret - function %get_return_address() -> i64 { block0: v0 = get_return_address.i64 @@ -76,29 +47,15 @@ block0: } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 +; push_frame ; block0: ; xmov x0, x28 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp +; push_frame ; xmov x0, lr -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; pop_frame ; ret diff --git a/cranelift/filetests/filetests/isa/pulley64/stack_addr.clif b/cranelift/filetests/filetests/isa/pulley64/stack_addr.clif index d642b2492ec0..b9190587fc21 100644 --- a/cranelift/filetests/filetests/isa/pulley64/stack_addr.clif +++ b/cranelift/filetests/filetests/isa/pulley64/stack_addr.clif @@ -9,37 +9,19 @@ block0(): } ; VCode: -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 -; store64 sp+8, x28 // flags = notrap aligned -; store64 sp+0, x29 // flags = notrap aligned -; x29 = xmov x27 -; x30 = xconst8 -16 -; x27 = xadd32 x27, x30 +; push_frame +; stack_alloc32 0x10 ; block0: ; x0 = load_addr Slot(0) -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 -; x28 = load64_u sp+8 // flags = notrap aligned -; x29 = load64_u sp+0 // flags = notrap aligned -; x30 = xconst8 16 -; x27 = xadd32 x27, x30 +; stack_free32 0x10 +; pop_frame ; ret ; ; Disassembled: -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 -; store64_offset8 sp, 8, lr -; store64 sp, fp -; xmov fp, sp -; xconst8 spilltmp0, -16 -; xadd32 sp, sp, spilltmp0 +; push_frame +; stack_alloc32 16 ; xmov x0, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 -; load64_offset8 lr, sp, 8 -; load64 fp, sp -; xconst8 spilltmp0, 16 -; xadd32 sp, sp, spilltmp0 +; stack_free32 16 +; pop_frame ; ret diff --git a/crates/cranelift/src/compiler.rs b/crates/cranelift/src/compiler.rs index c4f9bfe05b77..4ec769398291 100644 --- a/crates/cranelift/src/compiler.rs +++ b/crates/cranelift/src/compiler.rs @@ -268,25 +268,27 @@ impl wasmtime_environ::Compiler for Compiler { // abort for the whole program since the runtime limits configured by // the embedder should cause wasm to trap before it reaches that // (ensuring the host has enough space as well for its functionality). - let vmctx = context - .func - .create_global_value(ir::GlobalValueData::VMContext); - let interrupts_ptr = context.func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: i32::from(func_env.offsets.ptr.vmctx_runtime_limits()).into(), - global_type: isa.pointer_type(), - flags: MemFlags::trusted().with_readonly(), - }); - let stack_limit = context.func.create_global_value(ir::GlobalValueData::Load { - base: interrupts_ptr, - offset: i32::from(func_env.offsets.ptr.vmruntime_limits_stack_limit()).into(), - global_type: isa.pointer_type(), - flags: MemFlags::trusted(), - }); - if func_env.signals_based_traps() { - context.func.stack_limit = Some(stack_limit); - } else { - func_env.stack_limit_at_function_entry = Some(stack_limit); + if !func_env.is_pulley() { + let vmctx = context + .func + .create_global_value(ir::GlobalValueData::VMContext); + let interrupts_ptr = context.func.create_global_value(ir::GlobalValueData::Load { + base: vmctx, + offset: i32::from(func_env.offsets.ptr.vmctx_runtime_limits()).into(), + global_type: isa.pointer_type(), + flags: MemFlags::trusted().with_readonly(), + }); + let stack_limit = context.func.create_global_value(ir::GlobalValueData::Load { + base: interrupts_ptr, + offset: i32::from(func_env.offsets.ptr.vmruntime_limits_stack_limit()).into(), + global_type: isa.pointer_type(), + flags: MemFlags::trusted(), + }); + if func_env.signals_based_traps() { + context.func.stack_limit = Some(stack_limit); + } else { + func_env.stack_limit_at_function_entry = Some(stack_limit); + } } let FunctionBodyData { validator, body } = input; let mut validator = diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs index 499411e6e093..61842d3b8b3d 100644 --- a/crates/cranelift/src/func_environ.rs +++ b/crates/cranelift/src/func_environ.rs @@ -1195,6 +1195,14 @@ impl<'module_environment> FuncEnvironment<'module_environment> { i32::from(self.offsets.ptr.vm_func_ref_type_index()), ) } + + pub fn is_pulley(&self) -> bool { + match self.isa.triple().architecture { + target_lexicon::Architecture::Pulley32 => true, + target_lexicon::Architecture::Pulley64 => true, + _ => false, + } + } } struct Call<'a, 'func, 'module_env> { diff --git a/pulley/fuzz/src/interp.rs b/pulley/fuzz/src/interp.rs index e0f990e7ea93..82f29ffe0c88 100644 --- a/pulley/fuzz/src/interp.rs +++ b/pulley/fuzz/src/interp.rs @@ -118,6 +118,8 @@ fn op_is_safe_for_fuzzing(op: &Op) -> bool { Op::XPush32Many(_) | Op::XPush64Many(_) => false, Op::XPop32Many(_) | Op::XPop64Many(_) => false, Op::BrTable32(_) => false, + Op::StackAlloc32(_) => false, + Op::StackFree32(_) => false, } } diff --git a/pulley/src/interp.rs b/pulley/src/interp.rs index 536606923308..4e13d385ef24 100644 --- a/pulley/src/interp.rs +++ b/pulley/src/interp.rs @@ -1237,6 +1237,20 @@ impl OpVisitor for Interpreter<'_> { let rel = unwrap_uninhabited(PcRelOffset::decode(&mut self.pc)); self.pc_rel_jump(rel, 0) } + + fn stack_alloc32(&mut self, amt: u32) -> ControlFlow { + let amt = usize::try_from(amt).unwrap(); + let new_sp = self.state[XReg::sp].get_ptr::().wrapping_sub(amt); + self.set_sp(new_sp)?; + ControlFlow::Continue(()) + } + + fn stack_free32(&mut self, amt: u32) -> ControlFlow { + let amt = usize::try_from(amt).unwrap(); + let new_sp = self.state[XReg::sp].get_ptr::().wrapping_add(amt); + self.set_sp_unchecked(new_sp); + ControlFlow::Continue(()) + } } impl ExtendedOpVisitor for Interpreter<'_> { diff --git a/pulley/src/lib.rs b/pulley/src/lib.rs index 06f882ec9fdf..30a9da64c0e5 100644 --- a/pulley/src/lib.rs +++ b/pulley/src/lib.rs @@ -163,11 +163,11 @@ macro_rules! for_each_op { /// `sp = fp; pop fp; pop lr` pop_frame = PopFrame ; - /// `*sp = low32(src); sp += 4` + /// `*sp = low32(src); sp = sp.checked_add(4)` xpush32 = XPush32 { src: XReg }; /// `for src in srcs { xpush32 src }` xpush32_many = XPush32Many { srcs: RegSet }; - /// `*sp = src; sp += 8` + /// `*sp = src; sp = sp.checked_add(8)` xpush64 = XPush64 { src: XReg }; /// `for src in srcs { xpush64 src }` xpush64_many = XPush64Many { srcs: RegSet }; @@ -189,6 +189,12 @@ macro_rules! for_each_op { bitcast_float_from_int_32 = BitcastFloatFromInt32 { dst: FReg, src: XReg }; /// `dst = bitcast src as f64` bitcast_float_from_int_64 = BitcastFloatFromInt64 { dst: FReg, src: XReg }; + + /// `sp = sp.checked_sub(amt)` + stack_alloc32 = StackAlloc32 { amt: u32 }; + + /// `sp = sp + amt` + stack_free32 = StackFree32 { amt: u32 }; } }; } diff --git a/tests/disas/pulley/br_table.wat b/tests/disas/pulley/br_table.wat index 63ec9cefde36..ad6c1fc2f7b5 100644 --- a/tests/disas/pulley/br_table.wat +++ b/tests/disas/pulley/br_table.wat @@ -19,30 +19,17 @@ ) ) ;; wasm[0]::function[0]: -;; xconst8 spilltmp0, -16 -;; xadd32 sp, sp, spilltmp0 -;; store64_offset8 sp, 8, lr -;; store64 sp, fp -;; xmov fp, sp +;; push_frame ;; br_table32 x2, 3 -;; 0x1d // target = 0x33 -;; 0x8 // target = 0x22 -;; 0x26 // target = 0x44 -;; 22: xconst8 x0, 1 -;; load64_offset8 lr, sp, 8 -;; load64 fp, sp -;; xconst8 spilltmp0, 16 -;; xadd32 sp, sp, spilltmp0 +;; 0x11 // target = 0x18 +;; 0x8 // target = 0x13 +;; 0xe // target = 0x1d +;; 13: xconst8 x0, 1 +;; pop_frame ;; ret -;; 33: xconst8 x0, 2 -;; 36: load64_offset8 lr, sp, 8 -;; 3a: load64 fp, sp -;; 3d: xconst8 spilltmp0, 16 -;; 40: xadd32 sp, sp, spilltmp0 -;; 43: ret -;; 44: xconst8 x0, 0 -;; 47: load64_offset8 lr, sp, 8 -;; 4b: load64 fp, sp -;; 4e: xconst8 spilltmp0, 16 -;; 51: xadd32 sp, sp, spilltmp0 -;; 54: ret +;; 18: xconst8 x0, 2 +;; 1b: pop_frame +;; 1c: ret +;; 1d: xconst8 x0, 0 +;; 20: pop_frame +;; 21: ret diff --git a/tests/disas/pulley/call.wat b/tests/disas/pulley/call.wat new file mode 100644 index 000000000000..238e2b363d2a --- /dev/null +++ b/tests/disas/pulley/call.wat @@ -0,0 +1,16 @@ +;;! target = "pulley32" +;;! test = "compile" + +(module + (import "" "" (func $x)) + (func (export "") call $x) +) +;; wasm[0]::function[1]: +;; push_frame +;; load32_u_offset8 x3, x0, 44 +;; xmov x6, x0 +;; load32_u_offset8 x0, x6, 52 +;; xmov x1, x6 +;; call_indirect x3 +;; pop_frame +;; ret diff --git a/tests/disas/pulley/i32_add/const.wat b/tests/disas/pulley/i32_add/const.wat index f0e23cd22d0f..75629758d48c 100644 --- a/tests/disas/pulley/i32_add/const.wat +++ b/tests/disas/pulley/i32_add/const.wat @@ -10,14 +10,7 @@ ) ;; wasm[0]::function[0]: -;; xconst8 spilltmp0, -16 -;; xadd32 sp, sp, spilltmp0 -;; store64_offset8 sp, 8, lr -;; store64 sp, fp -;; xmov fp, sp +;; push_frame ;; xconst8 x0, 30 -;; load64_offset8 lr, sp, 8 -;; load64 fp, sp -;; xconst8 spilltmp0, 16 -;; xadd32 sp, sp, spilltmp0 +;; pop_frame ;; ret diff --git a/tests/disas/pulley/loads.wat b/tests/disas/pulley/loads.wat index 76e2063b268b..dbf9a380ab02 100644 --- a/tests/disas/pulley/loads.wat +++ b/tests/disas/pulley/loads.wat @@ -16,37 +16,23 @@ ) ;; wasm[0]::function[0]::i32: -;; xconst8 spilltmp0, -16 -;; xadd32 sp, sp, spilltmp0 -;; store64_offset8 sp, 8, lr -;; store64 sp, fp -;; xmov fp, sp +;; push_frame ;; load32_u_offset8 x6, x0, 52 -;; br_if_xult32 x6, x2, 0x1f // target = 0x33 -;; 1b: load32_u_offset8 x7, x0, 48 +;; br_if_xult32 x6, x2, 0x13 // target = 0x18 +;; c: load32_u_offset8 x7, x0, 48 ;; xadd32 x7, x7, x2 ;; load32_u x0, x7 -;; load64_offset8 lr, sp, 8 -;; load64 fp, sp -;; xconst8 spilltmp0, 16 -;; xadd32 sp, sp, spilltmp0 +;; pop_frame ;; ret -;; 33: trap +;; 18: trap ;; ;; wasm[0]::function[1]::i64: -;; xconst8 spilltmp0, -16 -;; xadd32 sp, sp, spilltmp0 -;; store64_offset8 sp, 8, lr -;; store64 sp, fp -;; xmov fp, sp +;; push_frame ;; load32_u_offset8 x6, x0, 52 -;; br_if_xult32 x6, x2, 0x1f // target = 0x33 -;; 1b: load32_u_offset8 x7, x0, 48 +;; br_if_xult32 x6, x2, 0x13 // target = 0x18 +;; c: load32_u_offset8 x7, x0, 48 ;; xadd32 x7, x7, x2 ;; load64 x0, x7 -;; load64_offset8 lr, sp, 8 -;; load64 fp, sp -;; xconst8 spilltmp0, 16 -;; xadd32 sp, sp, spilltmp0 +;; pop_frame ;; ret -;; 33: trap +;; 18: trap From f40e53e8992db030296c820debdad8950c773eff Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Dec 2024 10:19:26 -0700 Subject: [PATCH 17/21] Add basic pulley disassembly support to `clif-util` (#9721) * Add basic pulley disassembly support to `clif-util` Helpful when running `clif-util compile -D --target pulley64` over the input. * Fix non-pulley build --- Cargo.lock | 1 + cranelift/Cargo.toml | 2 ++ cranelift/src/disasm.rs | 15 ++++++++++++++- pulley/src/disas.rs | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7372d2d717f9..3d5ed322bdc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -957,6 +957,7 @@ dependencies = [ "indicatif", "log", "pretty_env_logger", + "pulley-interpreter", "rayon", "regalloc2", "rustc-hash 2.0.0", diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index 4cca318de5a5..6a82b6c35078 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -52,6 +52,7 @@ rustc-hash = { workspace = true } # Note that this just enables `trace-log` for `clif-util` and doesn't turn it on # for all of Cranelift, which would be bad. regalloc2 = { workspace = true, features = ["trace-log"] } +pulley-interpreter = { workspace = true, optional = true } [features] default = [ @@ -64,3 +65,4 @@ disas = ["capstone"] souper-harvest = ["cranelift-codegen/souper-harvest", "rayon"] all-arch = ["cranelift-codegen/all-arch"] all-native-arch = ["cranelift-codegen/all-native-arch"] +pulley = ['cranelift-codegen/pulley', 'dep:pulley-interpreter'] diff --git a/cranelift/src/disasm.rs b/cranelift/src/disasm.rs index 6947a5b977a9..574f72ec3bf6 100644 --- a/cranelift/src/disasm.rs +++ b/cranelift/src/disasm.rs @@ -39,9 +39,22 @@ pub fn print_traps(traps: &[MachTrap]) -> String { cfg_if! { if #[cfg(feature = "disas")] { pub fn print_disassembly(func: &Function, isa: &dyn TargetIsa, mem: &[u8]) -> Result<()> { + #[cfg(feature = "pulley")] + let is_pulley = match isa.triple().architecture { + target_lexicon::Architecture::Pulley32 | target_lexicon::Architecture::Pulley64 => true, + _ => false, + }; + println!("\nDisassembly of {} bytes <{}>:", mem.len(), func.name); + + #[cfg(feature = "pulley")] + if is_pulley { + let mut disas = pulley_interpreter::disas::Disassembler::new(mem); + pulley_interpreter::decode::Decoder::decode_all(&mut disas)?; + println!("{}", disas.disas()); + return Ok(()); + } let cs = isa.to_capstone().map_err(|e| anyhow::format_err!("{}", e))?; - println!("\nDisassembly of {} bytes <{}>:", mem.len(), func.name); let insns = cs.disasm_all(&mem, 0x0).unwrap(); for i in insns.iter() { let mut line = String::new(); diff --git a/pulley/src/disas.rs b/pulley/src/disas.rs index bdedf1164f59..301bf2c345d6 100644 --- a/pulley/src/disas.rs +++ b/pulley/src/disas.rs @@ -274,7 +274,7 @@ impl<'a> OpVisitor for Disassembler<'a> { write!(&mut self.disas, "{space}{byte:02x}").unwrap(); need_space = true; } - for _ in 0..11_usize.saturating_sub(size) { + for _ in 0..12_usize.saturating_sub(size) { write!(&mut self.disas, " ").unwrap(); } } From 7ef8f2e271aa8f5bfefca16b06757808ee6e0a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Cabrera?= Date: Wed, 4 Dec 2024 14:12:09 -0500 Subject: [PATCH 18/21] winch: Improve frame handling (#9708) This commit addresses issues identified while working on issue #8091. It improves the frame handling in Winch to prevent subtle bugs and enhance the robustness of the code generation process. Previously, there was no clear mechanism to verify when the frame was fully set up and safe to access the local slots allocated for register arguments, including the special slots used for the `VMContext`. As a result, it was possible to inadvertently read from uninitialized memory if calls were made before the frame was properly set up and sealed. This commit introduces two main changes with the objective to help reduce the risk of introducing bugs related to the above: * A `CodeGenPhase` trait, used via the type state pattern to clearly gate the operations allowed during each phase of the code generation process. * Improve the semantics of locals, by clearly separating the notion of Wasm locals and special locals used by the compiler. This specialization allows a more accurate representation of the semantics of Wasm locals and their index space. --- winch/codegen/src/abi/mod.rs | 15 -- winch/codegen/src/codegen/bounds.rs | 6 +- winch/codegen/src/codegen/call.rs | 14 +- winch/codegen/src/codegen/context.rs | 132 ++++++++------ winch/codegen/src/codegen/control.rs | 63 ++++--- winch/codegen/src/codegen/mod.rs | 252 ++++++++++++++------------ winch/codegen/src/codegen/phase.rs | 24 +++ winch/codegen/src/frame/mod.rs | 162 ++++++++++------- winch/codegen/src/isa/aarch64/masm.rs | 21 ++- winch/codegen/src/isa/aarch64/mod.rs | 9 +- winch/codegen/src/isa/x64/masm.rs | 21 ++- winch/codegen/src/isa/x64/mod.rs | 10 +- winch/codegen/src/masm.rs | 16 +- winch/codegen/src/visitor.rs | 9 +- 14 files changed, 436 insertions(+), 318 deletions(-) create mode 100644 winch/codegen/src/codegen/phase.rs diff --git a/winch/codegen/src/abi/mod.rs b/winch/codegen/src/abi/mod.rs index c2fa325c1f50..c205f7ea54c4 100644 --- a/winch/codegen/src/abi/mod.rs +++ b/winch/codegen/src/abi/mod.rs @@ -212,21 +212,6 @@ impl ABIOperand { _ => unreachable!(), } } - - /// Get the register associated to this [`ABIOperand`]. - pub fn get_reg(&self) -> Option { - match *self { - ABIOperand::Reg { reg, .. } => Some(reg), - _ => None, - } - } - - /// Get the type associated to this [`ABIOperand`]. - pub fn ty(&self) -> WasmValType { - match *self { - ABIOperand::Reg { ty, .. } | ABIOperand::Stack { ty, .. } => ty, - } - } } /// Information about the [`ABIOperand`] information used in [`ABISig`]. diff --git a/winch/codegen/src/codegen/bounds.rs b/winch/codegen/src/codegen/bounds.rs index 1904c8b68128..37ebd1088327 100644 --- a/winch/codegen/src/codegen/bounds.rs +++ b/winch/codegen/src/codegen/bounds.rs @@ -4,7 +4,7 @@ use super::env::HeapData; use crate::{ abi::{scratch, vmctx}, - codegen::CodeGenContext, + codegen::{CodeGenContext, Emission}, isa::reg::{writable, Reg}, masm::{IntCmpKind, MacroAssembler, OperandSize, RegImm, TrapCode}, stack::TypedReg, @@ -82,7 +82,7 @@ impl Index { /// Loads the bounds of the dynamic heap. pub(crate) fn load_dynamic_heap_bounds( - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, heap: &HeapData, ptr_size: OperandSize, @@ -149,7 +149,7 @@ pub(crate) fn ensure_index_and_offset( /// criteria is in bounds. pub(crate) fn load_heap_addr_checked( masm: &mut M, - context: &mut CodeGenContext, + context: &mut CodeGenContext, ptr_size: OperandSize, heap: &HeapData, enable_spectre_mitigation: bool, diff --git a/winch/codegen/src/codegen/call.rs b/winch/codegen/src/codegen/call.rs index ee3b4415cd5c..2cbb06bf96b5 100644 --- a/winch/codegen/src/codegen/call.rs +++ b/winch/codegen/src/codegen/call.rs @@ -58,7 +58,7 @@ use crate::{ abi::{scratch, vmctx, ABIOperand, ABISig, RetArea}, - codegen::{BuiltinFunction, BuiltinType, Callee, CodeGenContext}, + codegen::{BuiltinFunction, BuiltinType, Callee, CodeGenContext, Emission}, masm::{ CalleeKind, ContextArgs, MacroAssembler, MemMoveDirection, OperandSize, SPOffset, VMContextLoc, @@ -85,7 +85,7 @@ impl FnCall { pub fn emit( env: &mut FuncEnv, masm: &mut M, - context: &mut CodeGenContext, + context: &mut CodeGenContext, callee: Callee, ) { let (kind, callee_context) = Self::lower(env, context.vmoffsets, &callee, context, masm); @@ -129,7 +129,7 @@ impl FnCall { env: &mut FuncEnv, vmoffsets: &VMOffsets, callee: &Callee, - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, ) -> (CalleeKind, ContextArgs) { let ptr = vmoffsets.ptr.size(); @@ -177,7 +177,7 @@ impl FnCall { fn lower_import( index: FuncIndex, sig: &ABISig, - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, vmoffsets: &VMOffsets

, ) -> (CalleeKind, ContextArgs) { @@ -204,7 +204,7 @@ impl FnCall { fn lower_funcref( sig: &ABISig, ptr: impl PtrSize, - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, ) -> (CalleeKind, ContextArgs) { // Pop the funcref pointer to a register and allocate a register to hold the @@ -275,7 +275,7 @@ impl FnCall { sig: &ABISig, callee_context: &ContextArgs, ret_area: Option<&RetArea>, - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, ) { let arg_count = sig.params.len_without_retptr(); @@ -337,7 +337,7 @@ impl FnCall { reserved_space: u32, ret_area: Option, masm: &mut M, - context: &mut CodeGenContext, + context: &mut CodeGenContext, ) { // Free any registers holding any function references. match callee_kind { diff --git a/winch/codegen/src/codegen/context.rs b/winch/codegen/src/codegen/context.rs index 8cb315e696a6..99b9dc765667 100644 --- a/winch/codegen/src/codegen/context.rs +++ b/winch/codegen/src/codegen/context.rs @@ -3,6 +3,7 @@ use wasmtime_environ::{VMOffsets, WasmHeapType, WasmValType}; use super::ControlStackFrame; use crate::{ abi::{scratch, vmctx, ABIOperand, ABIResults, RetArea}, + codegen::{CodeGenPhase, Emission, Prologue}, frame::Frame, isa::reg::RegClass, masm::{MacroAssembler, OperandSize, RegImm, SPOffset, ShiftKind, StackSlot}, @@ -26,25 +27,78 @@ use crate::{ /// generation process. The code generation context should /// be generally used as the single entry point to access /// the compound functionality provided by its elements. -pub(crate) struct CodeGenContext<'a> { +pub(crate) struct CodeGenContext<'a, P: CodeGenPhase> { /// The register allocator. pub regalloc: RegAlloc, /// The value stack. pub stack: Stack, /// The current function's frame. - pub frame: Frame, + pub frame: Frame

, /// Reachability state. pub reachable: bool, /// A reference to the VMOffsets. pub vmoffsets: &'a VMOffsets, } -impl<'a> CodeGenContext<'a> { +impl<'a> CodeGenContext<'a, Emission> { + /// Prepares arguments for emitting an i32 shift operation. + pub fn i32_shift(&mut self, masm: &mut M, kind: ShiftKind) + where + M: MacroAssembler, + { + let top = self.stack.peek().expect("value at stack top"); + + if top.is_i32_const() { + let val = self + .stack + .pop_i32_const() + .expect("i32 const value at stack top"); + let typed_reg = self.pop_to_reg(masm, None); + masm.shift_ir( + writable!(typed_reg.reg), + val as u64, + typed_reg.reg, + kind, + OperandSize::S32, + ); + self.stack.push(typed_reg.into()); + } else { + masm.shift(self, kind, OperandSize::S32); + } + } + + /// Prepares arguments for emitting an i64 binary operation. + pub fn i64_shift(&mut self, masm: &mut M, kind: ShiftKind) + where + M: MacroAssembler, + { + let top = self.stack.peek().expect("value at stack top"); + if top.is_i64_const() { + let val = self + .stack + .pop_i64_const() + .expect("i64 const value at stack top"); + let typed_reg = self.pop_to_reg(masm, None); + masm.shift_ir( + writable!(typed_reg.reg), + val as u64, + typed_reg.reg, + kind, + OperandSize::S64, + ); + self.stack.push(typed_reg.into()); + } else { + masm.shift(self, kind, OperandSize::S64); + }; + } +} + +impl<'a> CodeGenContext<'a, Prologue> { /// Create a new code generation context. pub fn new( regalloc: RegAlloc, stack: Stack, - frame: Frame, + frame: Frame, vmoffsets: &'a VMOffsets, ) -> Self { Self { @@ -56,6 +110,19 @@ impl<'a> CodeGenContext<'a> { } } + /// Prepares the frame for the [`Emission`] code generation phase. + pub fn for_emission(self) -> CodeGenContext<'a, Emission> { + CodeGenContext { + regalloc: self.regalloc, + stack: self.stack, + reachable: self.reachable, + vmoffsets: self.vmoffsets, + frame: self.frame.for_emission(), + } + } +} + +impl<'a> CodeGenContext<'a, Emission> { /// Request a specific register to the register allocator, /// spilling if not available. pub fn reg(&mut self, named: Reg, masm: &mut M) -> Reg { @@ -325,57 +392,6 @@ impl<'a> CodeGenContext<'a> { }; } - /// Prepares arguments for emitting an i32 shift operation. - pub fn i32_shift(&mut self, masm: &mut M, kind: ShiftKind) - where - M: MacroAssembler, - { - let top = self.stack.peek().expect("value at stack top"); - - if top.is_i32_const() { - let val = self - .stack - .pop_i32_const() - .expect("i32 const value at stack top"); - let typed_reg = self.pop_to_reg(masm, None); - masm.shift_ir( - writable!(typed_reg.reg), - val as u64, - typed_reg.reg, - kind, - OperandSize::S32, - ); - self.stack.push(typed_reg.into()); - } else { - masm.shift(self, kind, OperandSize::S32); - } - } - - /// Prepares arguments for emitting an i64 binary operation. - pub fn i64_shift(&mut self, masm: &mut M, kind: ShiftKind) - where - M: MacroAssembler, - { - let top = self.stack.peek().expect("value at stack top"); - if top.is_i64_const() { - let val = self - .stack - .pop_i64_const() - .expect("i64 const value at stack top"); - let typed_reg = self.pop_to_reg(masm, None); - masm.shift_ir( - writable!(typed_reg.reg), - val as u64, - typed_reg.reg, - kind, - OperandSize::S64, - ); - self.stack.push(typed_reg.into()); - } else { - masm.shift(self, kind, OperandSize::S64); - }; - } - /// Prepares arguments for emitting a convert operation. pub fn convert_op(&mut self, masm: &mut M, dst_ty: WasmValType, mut emit: F) where @@ -511,7 +527,7 @@ impl<'a> CodeGenContext<'a> { mut calculate_ret_area: F, ) where M: MacroAssembler, - F: FnMut(&ABIResults, &mut CodeGenContext, &mut M) -> Option, + F: FnMut(&ABIResults, &mut CodeGenContext, &mut M) -> Option, { let area = results .on_stack() @@ -558,7 +574,7 @@ impl<'a> CodeGenContext<'a> { where M: MacroAssembler, { - let addr = masm.local_address(&self.frame.vmctx_slot); + let addr = masm.local_address(&self.frame.vmctx_slot()); masm.load_ptr(addr, writable!(vmctx!(M))); } @@ -570,7 +586,7 @@ impl<'a> CodeGenContext<'a> { fn spill_impl( stack: &mut Stack, regalloc: &mut RegAlloc, - frame: &Frame, + frame: &Frame, masm: &mut M, ) { stack.inner_mut().iter_mut().for_each(|v| match v { diff --git a/winch/codegen/src/codegen/control.rs b/winch/codegen/src/codegen/control.rs index d9fc7fc7ee8e..d9bab98880bd 100644 --- a/winch/codegen/src/codegen/control.rs +++ b/winch/codegen/src/codegen/control.rs @@ -9,6 +9,7 @@ use super::{CodeGenContext, OperandSize, Reg, TypedReg}; use crate::{ abi::{ABIOperand, ABIResults, ABISig, RetArea, ABI}, + codegen::Emission, masm::{IntCmpKind, MacroAssembler, MemMoveDirection, RegImm, SPOffset}, reg::writable, stack::Val, @@ -248,7 +249,7 @@ impl ControlStackFrame { pub fn r#if( sig: BlockSig, masm: &mut M, - context: &mut CodeGenContext, + context: &mut CodeGenContext, ) -> Self { let mut control = Self::If { cont: masm.get_label(), @@ -266,7 +267,7 @@ impl ControlStackFrame { pub fn block( sig: BlockSig, masm: &mut M, - context: &mut CodeGenContext, + context: &mut CodeGenContext, ) -> Self { let mut control = Self::Block { sig, @@ -283,7 +284,7 @@ impl ControlStackFrame { pub fn r#loop( sig: BlockSig, masm: &mut M, - context: &mut CodeGenContext, + context: &mut CodeGenContext, ) -> Self { let mut control = Self::Loop { stack_state: Default::default(), @@ -295,7 +296,7 @@ impl ControlStackFrame { control } - fn init(&mut self, masm: &mut M, context: &mut CodeGenContext) { + fn init(&mut self, masm: &mut M, context: &mut CodeGenContext) { self.calculate_stack_state(context, masm); // If the block has stack results, immediately resolve the return area // base. @@ -336,7 +337,7 @@ impl ControlStackFrame { /// Calculates the [StackState] of the block. fn calculate_stack_state( &mut self, - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, ) { use ControlStackFrame::*; @@ -388,7 +389,7 @@ impl ControlStackFrame { pub fn ensure_stack_state( &mut self, masm: &mut M, - context: &mut CodeGenContext, + context: &mut CodeGenContext, ) { let state = self.stack_state(); // This assumes that at jump sites, the machine stack pointer will be @@ -416,7 +417,7 @@ impl ControlStackFrame { } } - fn emit(&mut self, masm: &mut M, context: &mut CodeGenContext) { + fn emit(&mut self, masm: &mut M, context: &mut CodeGenContext) { use ControlStackFrame::*; // Do not perform any emissions if we are in an unreachable state. @@ -455,7 +456,11 @@ impl ControlStackFrame { /// Handles the else branch if the current control stack frame is /// [`ControlStackFrame::If`]. - pub fn emit_else(&mut self, masm: &mut M, context: &mut CodeGenContext) { + pub fn emit_else( + &mut self, + masm: &mut M, + context: &mut CodeGenContext, + ) { debug_assert!(self.is_if()); let state = self.stack_state(); @@ -467,7 +472,11 @@ impl ControlStackFrame { /// Binds the else branch label and converts `self` to /// [`ControlStackFrame::Else`]. - pub fn bind_else(&mut self, masm: &mut M, context: &mut CodeGenContext) { + pub fn bind_else( + &mut self, + masm: &mut M, + context: &mut CodeGenContext, + ) { use ControlStackFrame::*; match self { If { @@ -510,7 +519,11 @@ impl ControlStackFrame { } /// Handles the end of a control stack frame. - pub fn emit_end(&mut self, masm: &mut M, context: &mut CodeGenContext) { + pub fn emit_end( + &mut self, + masm: &mut M, + context: &mut CodeGenContext, + ) { use ControlStackFrame::*; match self { If { stack_state, .. } | Else { stack_state, .. } | Block { stack_state, .. } => { @@ -527,7 +540,11 @@ impl ControlStackFrame { /// Binds the exit label of the current control stack frame and pushes the /// ABI results to the value stack. - pub fn bind_end(&mut self, masm: &mut M, context: &mut CodeGenContext) { + pub fn bind_end( + &mut self, + masm: &mut M, + context: &mut CodeGenContext, + ) { self.push_abi_results(context, masm); self.bind_exit_label(masm); } @@ -627,12 +644,12 @@ impl ControlStackFrame { /// updated. pub fn pop_abi_results( &mut self, - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, calculate_ret_area: F, ) where M: MacroAssembler, - F: FnMut(&ABIResults, &mut CodeGenContext, &mut M) -> Option, + F: FnMut(&ABIResults, &mut CodeGenContext, &mut M) -> Option, { Self::pop_abi_results_impl(self.results::(), context, masm, calculate_ret_area) } @@ -648,12 +665,12 @@ impl ControlStackFrame { /// results should be interpreted. pub fn pop_abi_results_impl( results: &mut ABIResults, - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, mut calculate_ret_area: F, ) where M: MacroAssembler, - F: FnMut(&ABIResults, &mut CodeGenContext, &mut M) -> Option, + F: FnMut(&ABIResults, &mut CodeGenContext, &mut M) -> Option, { let mut iter = results.operands().iter().rev().peekable(); @@ -690,7 +707,7 @@ impl ControlStackFrame { /// Convenience wrapper around [CodeGenContext::push_abi_results] using the /// results of the current frame. - fn push_abi_results(&mut self, context: &mut CodeGenContext, masm: &mut M) + fn push_abi_results(&mut self, context: &mut CodeGenContext, masm: &mut M) where M: MacroAssembler, { @@ -705,12 +722,12 @@ impl ControlStackFrame { /// taken. pub fn top_abi_results( &mut self, - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, calculate_ret_area: F, ) where M: MacroAssembler, - F: FnMut(&ABIResults, &mut CodeGenContext, &mut M) -> Option, + F: FnMut(&ABIResults, &mut CodeGenContext, &mut M) -> Option, { Self::top_abi_results_impl::(self.results::(), context, masm, calculate_ret_area) } @@ -720,12 +737,12 @@ impl ControlStackFrame { /// needed. fn top_abi_results_impl( results: &mut ABIResults, - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, mut calculate_ret_area: F, ) where M: MacroAssembler, - F: FnMut(&ABIResults, &mut CodeGenContext, &mut M) -> Option, + F: FnMut(&ABIResults, &mut CodeGenContext, &mut M) -> Option, { let mut area = None; Self::pop_abi_results_impl::(results, context, masm, |r, context, masm| { @@ -764,7 +781,7 @@ impl ControlStackFrame { fn adjust_stack_results( ret_area: RetArea, results: &ABIResults, - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, ) where M: MacroAssembler, @@ -889,7 +906,7 @@ impl ControlStackFrame { /// Ensures that there is enough space for return values on the stack. /// This function is called at the end of all blocks and when branching from /// within blocks. - fn ensure_ret_area(ret_area: &RetArea, context: &mut CodeGenContext, masm: &mut M) + fn ensure_ret_area(ret_area: &RetArea, context: &mut CodeGenContext, masm: &mut M) where M: MacroAssembler, { @@ -907,7 +924,7 @@ impl ControlStackFrame { fn maybe_load_retptr( ret_area: Option<&RetArea>, results: &ABIResults, - context: &mut CodeGenContext, + context: &mut CodeGenContext, masm: &mut M, ) -> Option where diff --git a/winch/codegen/src/codegen/mod.rs b/winch/codegen/src/codegen/mod.rs index a3721867b2c5..63f442c23444 100644 --- a/winch/codegen/src/codegen/mod.rs +++ b/winch/codegen/src/codegen/mod.rs @@ -13,6 +13,7 @@ use cranelift_codegen::{ ir::{RelSourceLoc, SourceLoc}, }; use smallvec::SmallVec; +use std::marker::PhantomData; use wasmparser::{ BinaryReader, FuncValidator, MemArg, Operator, ValidatorResources, VisitOperator, VisitSimdOperator, @@ -37,6 +38,9 @@ pub(crate) mod bounds; use bounds::{Bounds, ImmOffset, Index}; +mod phase; +pub(crate) use phase::*; + /// Holds metadata about the source code location and the machine code emission. /// The fields of this struct are opaque and are not interpreted in any way. /// They serve as a mapping between source code and machine code. @@ -50,15 +54,16 @@ pub(crate) struct SourceLocation { } /// The code generation abstraction. -pub(crate) struct CodeGen<'a, 'translation: 'a, 'data: 'translation, M> +pub(crate) struct CodeGen<'a, 'translation: 'a, 'data: 'translation, M, P> where M: MacroAssembler, + P: CodeGenPhase, { /// The ABI-specific representation of the function signature, excluding results. pub sig: ABISig, /// The code generation context. - pub context: CodeGenContext<'a>, + pub context: CodeGenContext<'a, P>, /// A reference to the function compilation environment. pub env: FuncEnv<'a, 'translation, 'data, M::Ptr>, @@ -83,19 +88,20 @@ where /// Local counter to track fuel consumption. pub fuel_consumed: i64, + phase: PhantomData

, } -impl<'a, 'translation, 'data, M> CodeGen<'a, 'translation, 'data, M> +impl<'a, 'translation, 'data, M> CodeGen<'a, 'translation, 'data, M, Prologue> where M: MacroAssembler, { pub fn new( tunables: &'a Tunables, masm: &'a mut M, - context: CodeGenContext<'a>, + context: CodeGenContext<'a, Prologue>, env: FuncEnv<'a, 'translation, 'data, M::Ptr>, sig: ABISig, - ) -> Self { + ) -> CodeGen<'a, 'translation, 'data, M, Prologue> { Self { sig, context, @@ -107,32 +113,11 @@ where found_unsupported_instruction: None, // Empty functions should consume at least 1 fuel unit. fuel_consumed: 1, + phase: PhantomData, } } - /// Emit the function body to machine code. - pub fn emit( - &mut self, - body: &mut BinaryReader<'a>, - validator: &mut FuncValidator, - ) -> Result<()> { - self.emit_start() - .and_then(|_| self.emit_body(body, validator)) - .and_then(|_| self.emit_end())?; - - Ok(()) - } - - /// Derives a [RelSourceLoc] from a [SourceLoc]. - pub fn source_loc_from(&mut self, loc: SourceLoc) -> RelSourceLoc { - if self.source_location.base.is_none() && !loc.is_default() { - self.source_location.base = Some(loc); - } - - RelSourceLoc::from_base_offset(self.source_location.base.unwrap_or_default(), loc) - } - - fn emit_start(&mut self) -> Result<()> { + pub fn emit_prologue(mut self) -> Result> { let vmctx = self .sig .params() @@ -153,32 +138,95 @@ where ); self.masm.reserve_stack(self.context.frame.locals_size); + self.spill_register_arguments(); + + let defined_locals_range = &self.context.frame.defined_locals_range; + self.masm.zero_mem_range(defined_locals_range.as_range()); + + // Save the results base parameter register into its slot. + self.sig.params.has_retptr().then(|| { + match self.sig.params.unwrap_results_area_operand() { + ABIOperand::Reg { ty, reg, .. } => { + let results_base_slot = self.context.frame.results_base_slot.as_ref().unwrap(); + debug_assert!(results_base_slot.addressed_from_sp()); + let addr = self.masm.local_address(results_base_slot); + self.masm.store((*reg).into(), addr, (*ty).into()); + } + // The result base parameter is a stack parameter, addressed + // from FP. + _ => {} + } + }); self.masm.end_source_loc(); - if self.tunables.consume_fuel { - self.emit_fuel_check(); + Ok(CodeGen { + sig: self.sig, + context: self.context.for_emission(), + masm: self.masm, + env: self.env, + tunables: self.tunables, + source_location: self.source_location, + control_frames: self.control_frames, + found_unsupported_instruction: self.found_unsupported_instruction, + fuel_consumed: self.fuel_consumed, + phase: PhantomData, + }) + } + + fn spill_register_arguments(&mut self) { + use WasmValType::*; + for (operand, slot) in self + .sig + .params_without_retptr() + .iter() + .zip(self.context.frame.locals()) + { + match (operand, slot) { + (ABIOperand::Reg { ty, reg, .. }, slot) => { + let addr = self.masm.local_address(slot); + match &ty { + I32 | I64 | F32 | F64 | V128 => { + self.masm.store((*reg).into(), addr, (*ty).into()) + } + Ref(rt) => match rt.heap_type { + WasmHeapType::Func | WasmHeapType::Extern => { + self.masm.store_ptr((*reg).into(), addr) + } + ht => unimplemented!("Support for WasmHeapType: {ht}"), + }, + } + } + // Skip non-register arguments + _ => {} + } } + } +} - // Once we have emitted the epilogue and reserved stack space for the locals, we push the - // base control flow block. - self.control_frames.push(ControlStackFrame::block( - BlockSig::from_sig(self.sig.clone()), - self.masm, - &mut self.context, - )); +impl<'a, 'translation, 'data, M> CodeGen<'a, 'translation, 'data, M, Emission> +where + M: MacroAssembler, +{ + /// Emit the function body to machine code. + pub fn emit( + &mut self, + body: &mut BinaryReader<'a>, + validator: &mut FuncValidator, + ) -> Result<()> { + self.emit_body(body, validator) + .and_then(|_| self.emit_end())?; - // Set the return area of the results *after* initializing the block. In - // the function body block case, we'll treat the results as any other - // case, addressed from the stack pointer, and when ending the function - // the return area will be set to the return pointer. - if self.sig.params.has_retptr() { - self.sig - .results - .set_ret_area(RetArea::slot(self.context.frame.results_base_slot.unwrap())); + Ok(()) + } + + /// Derives a [RelSourceLoc] from a [SourceLoc]. + pub fn source_loc_from(&mut self, loc: SourceLoc) -> RelSourceLoc { + if self.source_location.base.is_none() && !loc.is_default() { + self.source_location.base = Some(loc); } - Ok(()) + RelSourceLoc::from_base_offset(self.source_location.base.unwrap_or_default(), loc) } /// The following two helpers, handle else or end instructions when the @@ -224,24 +272,27 @@ where body: &mut BinaryReader<'a>, validator: &mut FuncValidator, ) -> Result<()> { - self.spill_register_arguments(); - let defined_locals_range = &self.context.frame.defined_locals_range; - self.masm.zero_mem_range(defined_locals_range.as_range()); + if self.tunables.consume_fuel { + self.emit_fuel_check(); + } - // Save the results base parameter register into its slot. - self.sig.params.has_retptr().then(|| { - match self.sig.params.unwrap_results_area_operand() { - ABIOperand::Reg { ty, reg, .. } => { - let results_base_slot = self.context.frame.results_base_slot.as_ref().unwrap(); - debug_assert!(results_base_slot.addressed_from_sp()); - let addr = self.masm.local_address(results_base_slot); - self.masm.store((*reg).into(), addr, (*ty).into()); - } - // The result base parameter is a stack parameter, addressed - // from FP. - _ => {} - } - }); + // Once we have emitted the epilogue and reserved stack space for the locals, we push the + // base control flow block. + self.control_frames.push(ControlStackFrame::block( + BlockSig::from_sig(self.sig.clone()), + self.masm, + &mut self.context, + )); + + // Set the return area of the results *after* initializing the block. In + // the function body block case, we'll treat the results as any other + // case, addressed from the stack pointer, and when ending the function + // the return area will be set to the return pointer. + if self.sig.params.has_retptr() { + self.sig + .results + .set_ret_area(RetArea::slot(self.context.frame.results_base_slot.unwrap())); + } while !body.eof() { let offset = body.original_position(); @@ -307,7 +358,7 @@ where } impl<'a, 'translation, 'data, M: MacroAssembler> VisitorHooks - for CodeGen<'a, 'translation, 'data, M> + for CodeGen<'a, 'translation, 'data, M, Emission> { fn visit(&self, op: &Operator) -> bool { self.context.reachable || visit_op_when_unreachable(op) @@ -431,35 +482,6 @@ where Ok(()) } - fn spill_register_arguments(&mut self) { - use WasmValType::*; - self.sig - // Skip the results base param if any; [Self::emit_body], - // will handle spilling the results base param if it's in a register. - .params_without_retptr() - .iter() - .enumerate() - .filter(|(_, a)| a.is_reg()) - .for_each(|(index, arg)| { - let ty = arg.ty(); - let local = self.context.frame.get_frame_local(index); - let addr = self.masm.local_address(local); - let src = arg - .get_reg() - .expect("arg should be associated to a register"); - - match &ty { - I32 | I64 | F32 | F64 | V128 => self.masm.store(src.into(), addr, ty.into()), - Ref(rt) => match rt.heap_type { - WasmHeapType::Func | WasmHeapType::Extern => { - self.masm.store_ptr(src.into(), addr) - } - ht => unimplemented!("Support for WasmHeapType: {ht}"), - }, - } - }); - } - /// Pops the value at the stack top and assigns it to the local at /// the given index, returning the typed register holding the /// source value. @@ -633,8 +655,12 @@ where // * index + offset + access_size overflows // OR // * index + offset + access_size > bound - let bounds = - bounds::load_dynamic_heap_bounds(&mut self.context, self.masm, &heap, ptr_size); + let bounds = bounds::load_dynamic_heap_bounds::<_>( + &mut self.context, + self.masm, + &heap, + ptr_size, + ); let index_reg = index.as_typed_reg().reg; // Allocate a temporary register to hold @@ -978,6 +1004,24 @@ where self.context.free_reg(fuel_var); } + /// Emits a series of instructions that load the `fuel_consumed` field from + /// `VMRuntimeLimits`. + fn emit_load_fuel_consumed(&mut self, fuel_var: Reg) { + let limits_offset = self.env.vmoffsets.ptr.vmctx_runtime_limits(); + let fuel_offset = self.env.vmoffsets.ptr.vmruntime_limits_fuel_consumed(); + self.masm.load_ptr( + self.masm.address_at_vmctx(u32::from(limits_offset)), + writable!(fuel_var), + ); + + self.masm.load( + self.masm.address_at_reg(fuel_var, u32::from(fuel_offset)), + writable!(fuel_var), + // Fuel is an i64. + OperandSize::S64, + ); + } + /// Increments the fuel consumed in `VMRuntimeLimits` by flushing /// `self.fuel_consumed` to memory. fn emit_fuel_increment(&mut self) { @@ -1022,24 +1066,6 @@ where self.context.free_reg(limits_var); } - /// Emits a series of instructions that load the `fuel_consumed` field from - /// `VMRuntimeLimits`. - fn emit_load_fuel_consumed(&mut self, fuel_var: Reg) { - let limits_offset = self.env.vmoffsets.ptr.vmctx_runtime_limits(); - let fuel_offset = self.env.vmoffsets.ptr.vmruntime_limits_fuel_consumed(); - self.masm.load_ptr( - self.masm.address_at_vmctx(u32::from(limits_offset)), - writable!(fuel_var), - ); - - self.masm.load( - self.masm.address_at_reg(fuel_var, u32::from(fuel_offset)), - writable!(fuel_var), - // Fuel is an i64. - OperandSize::S64, - ); - } - /// Hook to handle fuel before visiting an operator. fn fuel_before_visit_op(&mut self, op: &Operator) { if !self.context.reachable { diff --git a/winch/codegen/src/codegen/phase.rs b/winch/codegen/src/codegen/phase.rs new file mode 100644 index 000000000000..de2d2e0206fa --- /dev/null +++ b/winch/codegen/src/codegen/phase.rs @@ -0,0 +1,24 @@ +//! Type-based states to represent code generation phases. +//! These states help enforce code generation invariants at compile time. +//! +//! Currently two phases are defined for code generation: +//! +//! * Prologue: responsible of setting up the function's frame. +//! * Emission: emission of Wasm code to machine code. + +/// A code generation phase. +pub trait CodeGenPhase {} + +/// The prologue phase. +/// +/// Its main responsibility is to setup the function's frame, by creating the +/// well known local slots. In this phase, writes to such slots is allowed. +/// After this phase, the frame is considered immutable. +pub struct Prologue; +/// The code emission phase. +/// +/// Its main responsibility is to emit Wasm code to machine code. +pub struct Emission; + +impl CodeGenPhase for Prologue {} +impl CodeGenPhase for Emission {} diff --git a/winch/codegen/src/frame/mod.rs b/winch/codegen/src/frame/mod.rs index 1ebdace8daf3..c813141d7184 100644 --- a/winch/codegen/src/frame/mod.rs +++ b/winch/codegen/src/frame/mod.rs @@ -1,18 +1,27 @@ use crate::{ abi::{align_to, ABIOperand, ABISig, LocalSlot, ABI}, + codegen::{CodeGenPhase, Emission, Prologue}, masm::MacroAssembler, }; use anyhow::Result; use smallvec::SmallVec; +use std::marker::PhantomData; use std::ops::Range; use wasmparser::{BinaryReader, FuncValidator, ValidatorResources}; use wasmtime_environ::{TypeConvert, WasmValType}; +/// WebAssembly locals. // TODO: // SpiderMonkey's implementation uses 16; // (ref: https://searchfox.org/mozilla-central/source/js/src/wasm/WasmBCFrame.h#585) // during instrumentation we should measure to verify if this is a good default. -pub(crate) type Locals = SmallVec<[LocalSlot; 16]>; +pub(crate) type WasmLocals = SmallVec<[LocalSlot; 16]>; +/// Special local slots used by the compiler. +// Winch's ABI uses two extra parameters to store the callee and caller +// VMContext pointers. +// These arguments are spilled and treated as frame locals, but not +// WebAssembly locals. +pub(crate) type SpecialLocals = [LocalSlot; 2]; /// Function defined locals start and end in the frame. pub(crate) struct DefinedLocalsRange(Range); @@ -28,7 +37,7 @@ impl DefinedLocalsRange { #[derive(Default)] pub(crate) struct DefinedLocals { /// The defined locals for a function. - pub defined_locals: Locals, + pub defined_locals: WasmLocals, /// The size of the defined locals. pub stack_size: u32, } @@ -43,7 +52,7 @@ impl DefinedLocals { let mut next_stack: u32 = 0; // The first 32 bits of a Wasm binary function describe the number of locals. let local_count = reader.read_var_u32()?; - let mut slots: Locals = Default::default(); + let mut slots: WasmLocals = Default::default(); for _ in 0..local_count { let position = reader.original_position(); @@ -67,7 +76,7 @@ impl DefinedLocals { } /// Frame handler abstraction. -pub(crate) struct Frame { +pub(crate) struct Frame { /// The size of the entire local area; the arguments plus the function defined locals. pub locals_size: u32, @@ -78,23 +87,24 @@ pub(crate) struct Frame { /// /// Locals get calculated when allocating a frame and are readonly /// through the function compilation lifetime. - locals: Locals, - - /// The offset to the slot containing the `VMContext`. - pub vmctx_slot: LocalSlot, + wasm_locals: WasmLocals, + /// Special locals used by the internal ABI. See [`SpecialLocals`]. + special_locals: SpecialLocals, /// The slot holding the address of the results area. pub results_base_slot: Option, + marker: PhantomData

, } -impl Frame { +impl Frame { /// Allocate a new [`Frame`]. - pub fn new(sig: &ABISig, defined_locals: &DefinedLocals) -> Result { - let (mut locals, defined_locals_start) = Self::compute_arg_slots::(sig)?; + pub fn new(sig: &ABISig, defined_locals: &DefinedLocals) -> Result> { + let (special_locals, mut wasm_locals, defined_locals_start) = + Self::compute_arg_slots::(sig)?; // The defined locals have a zero-based offset by default // so we need to add the defined locals start to the offset. - locals.extend( + wasm_locals.extend( defined_locals .defined_locals .iter() @@ -138,66 +148,37 @@ impl Frame { (None, defined_locals_end) }; - let vmctx_slot = *locals.get(0).expect("LocalSlot for VMContext"); Ok(Self { - locals, + wasm_locals, + special_locals, locals_size, - vmctx_slot, defined_locals_range: DefinedLocalsRange( defined_locals_start..(defined_locals_start + defined_locals.stack_size), ), results_base_slot, + marker: PhantomData, }) } - // Winch's ABI uses two extra parameters to store the callee and caller - // VMContext pointers. - // These arguments are spilled and treated as frame locals, but not - // WebAssembly locals. - const WASM_LOCALS_OFFSET: usize = 2; - - /// Get the [LocalSlot] for a WebAssembly local. - /// This method assumes that the index is bound to u32::MAX, representing - /// the index space for WebAssembly locals. - /// - /// # Panics - /// This method panics if the index is not associated to a valid WebAssembly - /// local. - pub fn get_wasm_local(&self, index: u32) -> &LocalSlot { - let local_index = Self::WASM_LOCALS_OFFSET + index as usize; - self.locals - .get(local_index) - .unwrap_or_else(|| panic!(" Expected WebAssembly local at slot: {index}")) - } - - /// Get the [LocalSlot] for a frame local. - /// This method doesn't make any asumptions about the local index passed in, - /// and simply delegates the [LocalSlot] retrieval to the underlying locals - /// vector. - /// - /// # Panics - /// This method panics if the index is not associated to a valid WebAssembly - /// local. - pub fn get_frame_local(&self, index: usize) -> &LocalSlot { - self.locals - .get(index) - .unwrap_or_else(|| panic!(" Expected Frame local at slot: {index}")) + /// Returns an iterator over all the [`LocalSlot`]s in the frame, including + /// the [`SpecialLocals`]. + pub fn locals(&self) -> impl Iterator { + self.special_locals.iter().chain(self.wasm_locals.iter()) } - /// Returns the address of the local at the given index. - /// - /// # Panics - /// This function panics if the index is not associated to a local. - pub fn get_local_address( - &self, - index: u32, - masm: &mut M, - ) -> (WasmValType, M::Address) { - let slot = self.get_wasm_local(index); - (slot.ty, masm.local_address(&slot)) + /// Prepares the frame for the [`Emission`] code generation phase. + pub fn for_emission(self) -> Frame { + Frame { + wasm_locals: self.wasm_locals, + special_locals: self.special_locals, + locals_size: self.locals_size, + defined_locals_range: self.defined_locals_range, + results_base_slot: self.results_base_slot, + marker: PhantomData, + } } - fn compute_arg_slots(sig: &ABISig) -> Result<(Locals, u32)> { + fn compute_arg_slots(sig: &ABISig) -> Result<(SpecialLocals, WasmLocals, u32)> { // Go over the function ABI-signature and // calculate the stack slots. // @@ -231,13 +212,24 @@ impl Frame { // Skip the results base param; if present, the [Frame] will create // a dedicated slot for it. - let slots: Locals = sig - .params_without_retptr() - .into_iter() + let mut params_iter = sig.params_without_retptr().into_iter(); + + // Handle special local slots. + let callee_vmctx = params_iter + .next() + .map(|arg| Self::abi_arg_slot(&arg, &mut next_stack, arg_base_offset)) + .expect("Slot for VMContext"); + + let caller_vmctx = params_iter + .next() + .map(|arg| Self::abi_arg_slot(&arg, &mut next_stack, arg_base_offset)) + .expect("Slot for VMContext"); + + let slots: WasmLocals = params_iter .map(|arg| Self::abi_arg_slot(&arg, &mut next_stack, arg_base_offset)) .collect(); - Ok((slots, next_stack)) + Ok(([callee_vmctx, caller_vmctx], slots, next_stack)) } fn abi_arg_slot(arg: &ABIOperand, next_stack: &mut u32, arg_base_offset: u32) -> LocalSlot { @@ -256,3 +248,47 @@ impl Frame { } } } + +impl Frame { + /// Get the [`LocalSlot`] for a WebAssembly local. + /// This method assumes that the index is bound to u32::MAX, representing + /// the index space for WebAssembly locals. + /// + /// # Panics + /// This method panics if the index is not associated to a valid WebAssembly + /// local. + pub fn get_wasm_local(&self, index: u32) -> &LocalSlot { + self.wasm_locals + .get(index as usize) + .unwrap_or_else(|| panic!(" Expected WebAssembly local at slot: {index}")) + } + + /// Get the [`LocalSlot`] for a special local. + /// + /// # Panics + /// This method panics if the index is not associated to a valid special + /// local. + pub fn get_special_local(&self, index: usize) -> &LocalSlot { + self.special_locals + .get(index) + .unwrap_or_else(|| panic!(" Expected special local at slot: {index}")) + } + + /// Get the special [`LocalSlot`] for the `VMContext`. + pub fn vmctx_slot(&self) -> &LocalSlot { + self.get_special_local(0) + } + + /// Returns the address of the local at the given index. + /// + /// # Panics + /// This function panics if the index is not associated to a local. + pub fn get_local_address( + &self, + index: u32, + masm: &mut M, + ) -> (WasmValType, M::Address) { + let slot = self.get_wasm_local(index); + (slot.ty, masm.local_address(&slot)) + } +} diff --git a/winch/codegen/src/isa/aarch64/masm.rs b/winch/codegen/src/isa/aarch64/masm.rs index 02226387baa3..9be8a60f772a 100644 --- a/winch/codegen/src/isa/aarch64/masm.rs +++ b/winch/codegen/src/isa/aarch64/masm.rs @@ -1,7 +1,7 @@ use super::{abi::Aarch64ABI, address::Address, asm::Assembler, regs}; use crate::{ abi::local::LocalSlot, - codegen::{ptr_type_from_ptr_size, CodeGenContext, FuncEnv}, + codegen::{ptr_type_from_ptr_size, CodeGenContext, Emission, FuncEnv}, isa::reg::{writable, Reg, WritableReg}, masm::{ CalleeKind, DivKind, ExtendKind, FloatCmpKind, Imm as I, IntCmpKind, @@ -350,11 +350,11 @@ impl Masm for MacroAssembler { self.asm.fabs_rr(dst.to_reg(), dst, size); } - fn float_round, &mut CodeGenContext, &mut Self)>( + fn float_round, &mut CodeGenContext, &mut Self)>( &mut self, mode: RoundingMode, _env: &mut FuncEnv, - context: &mut CodeGenContext, + context: &mut CodeGenContext, size: OperandSize, _fallback: F, ) { @@ -433,7 +433,12 @@ impl Masm for MacroAssembler { self.asm.shift_ir(imm, lhs, dst, kind, size) } - fn shift(&mut self, context: &mut CodeGenContext, kind: ShiftKind, size: OperandSize) { + fn shift( + &mut self, + context: &mut CodeGenContext, + kind: ShiftKind, + size: OperandSize, + ) { let src = context.pop_to_reg(self, None); let dst = context.pop_to_reg(self, None); @@ -444,11 +449,11 @@ impl Masm for MacroAssembler { context.stack.push(dst.into()); } - fn div(&mut self, _context: &mut CodeGenContext, _kind: DivKind, _size: OperandSize) { + fn div(&mut self, _context: &mut CodeGenContext, _kind: DivKind, _size: OperandSize) { todo!() } - fn rem(&mut self, _context: &mut CodeGenContext, _kind: RemKind, _size: OperandSize) { + fn rem(&mut self, _context: &mut CodeGenContext, _kind: RemKind, _size: OperandSize) { todo!() } @@ -456,7 +461,7 @@ impl Masm for MacroAssembler { self.asm.load_constant(0, reg); } - fn popcnt(&mut self, context: &mut CodeGenContext, size: OperandSize) { + fn popcnt(&mut self, context: &mut CodeGenContext, size: OperandSize) { let src = context.pop_to_reg(self, None); let tmp = regs::float_scratch(); self.asm.mov_to_fpu(src.into(), writable!(tmp), size); @@ -700,7 +705,7 @@ impl Masm for MacroAssembler { todo!() } - fn mul_wide(&mut self, context: &mut CodeGenContext, kind: MulWideKind) { + fn mul_wide(&mut self, context: &mut CodeGenContext, kind: MulWideKind) { let _ = (context, kind); todo!() } diff --git a/winch/codegen/src/isa/aarch64/mod.rs b/winch/codegen/src/isa/aarch64/mod.rs index 17c49577a6fb..e54ffa0c9d4e 100644 --- a/winch/codegen/src/isa/aarch64/mod.rs +++ b/winch/codegen/src/isa/aarch64/mod.rs @@ -123,11 +123,12 @@ impl TargetIsa for Aarch64 { ); let regalloc = RegAlloc::from(gpr, fpr); let codegen_context = CodeGenContext::new(regalloc, stack, frame, &vmoffsets); - let mut codegen = CodeGen::new(tunables, &mut masm, codegen_context, env, abi_sig); + let codegen = CodeGen::new(tunables, &mut masm, codegen_context, env, abi_sig); - codegen.emit(&mut body, validator)?; - let names = codegen.env.take_name_map(); - let base = codegen.source_location.base; + let mut body_codegen = codegen.emit_prologue()?; + body_codegen.emit(&mut body, validator)?; + let names = body_codegen.env.take_name_map(); + let base = body_codegen.source_location.base; Ok(CompiledFunction::new( masm.finalize(base), names, diff --git a/winch/codegen/src/isa/x64/masm.rs b/winch/codegen/src/isa/x64/masm.rs index 4d72b79e6965..9937d165e9b9 100644 --- a/winch/codegen/src/isa/x64/masm.rs +++ b/winch/codegen/src/isa/x64/masm.rs @@ -12,7 +12,7 @@ use crate::masm::{ }; use crate::{ abi::{self, align_to, calculate_frame_adjustment, LocalSlot}, - codegen::{ptr_type_from_ptr_size, CodeGenContext, FuncEnv}, + codegen::{ptr_type_from_ptr_size, CodeGenContext, Emission, FuncEnv}, stack::{TypedReg, Val}, }; use crate::{ @@ -474,11 +474,11 @@ impl Masm for MacroAssembler { self.asm.xmm_and_rr(scratch_xmm, dst, size); } - fn float_round, &mut CodeGenContext, &mut Self)>( + fn float_round, &mut CodeGenContext, &mut Self)>( &mut self, mode: RoundingMode, env: &mut FuncEnv, - context: &mut CodeGenContext, + context: &mut CodeGenContext, size: OperandSize, mut fallback: F, ) { @@ -565,7 +565,12 @@ impl Masm for MacroAssembler { self.asm.shift_ir(imm as u8, dst, kind, size) } - fn shift(&mut self, context: &mut CodeGenContext, kind: ShiftKind, size: OperandSize) { + fn shift( + &mut self, + context: &mut CodeGenContext, + kind: ShiftKind, + size: OperandSize, + ) { // Number of bits to shift must be in the CL register. let src = context.pop_to_reg(self, Some(regs::rcx())); let dst = context.pop_to_reg(self, None); @@ -577,7 +582,7 @@ impl Masm for MacroAssembler { context.stack.push(dst.into()); } - fn div(&mut self, context: &mut CodeGenContext, kind: DivKind, size: OperandSize) { + fn div(&mut self, context: &mut CodeGenContext, kind: DivKind, size: OperandSize) { // Allocate rdx:rax. let rdx = context.reg(regs::rdx(), self); let rax = context.reg(regs::rax(), self); @@ -599,7 +604,7 @@ impl Masm for MacroAssembler { context.stack.push(rax.into()); } - fn rem(&mut self, context: &mut CodeGenContext, kind: RemKind, size: OperandSize) { + fn rem(&mut self, context: &mut CodeGenContext, kind: RemKind, size: OperandSize) { // Allocate rdx:rax. let rdx = context.reg(regs::rdx(), self); let rax = context.reg(regs::rax(), self); @@ -787,7 +792,7 @@ impl Masm for MacroAssembler { self.asm.jmp(target); } - fn popcnt(&mut self, context: &mut CodeGenContext, size: OperandSize) { + fn popcnt(&mut self, context: &mut CodeGenContext, size: OperandSize) { let src = context.pop_to_reg(self, None); if self.flags.has_popcnt() && self.flags.has_sse42() { self.asm.popcnt(src.into(), size); @@ -1028,7 +1033,7 @@ impl Masm for MacroAssembler { self.asm.sbb_rr(rhs_hi, dst_hi, OperandSize::S64); } - fn mul_wide(&mut self, context: &mut CodeGenContext, kind: MulWideKind) { + fn mul_wide(&mut self, context: &mut CodeGenContext, kind: MulWideKind) { // Reserve rax/rdx since they're required by the `mul_wide` instruction // being used here. let rax = context.reg(regs::rax(), self); diff --git a/winch/codegen/src/isa/x64/mod.rs b/winch/codegen/src/isa/x64/mod.rs index ae038f6d7776..de0029d08d00 100644 --- a/winch/codegen/src/isa/x64/mod.rs +++ b/winch/codegen/src/isa/x64/mod.rs @@ -134,12 +134,14 @@ impl TargetIsa for X64 { let regalloc = RegAlloc::from(gpr, fpr); let codegen_context = CodeGenContext::new(regalloc, stack, frame, &vmoffsets); - let mut codegen = CodeGen::new(tunables, &mut masm, codegen_context, env, abi_sig); + let codegen = CodeGen::new(tunables, &mut masm, codegen_context, env, abi_sig); - codegen.emit(&mut body, validator)?; - let base = codegen.source_location.base; + let mut body_codegen = codegen.emit_prologue()?; - let names = codegen.env.take_name_map(); + body_codegen.emit(&mut body, validator)?; + let base = body_codegen.source_location.base; + + let names = body_codegen.env.take_name_map(); Ok(CompiledFunction::new( masm.finalize(base), names, diff --git a/winch/codegen/src/masm.rs b/winch/codegen/src/masm.rs index 95de6e789225..1bd5a7a59b4e 100644 --- a/winch/codegen/src/masm.rs +++ b/winch/codegen/src/masm.rs @@ -1,5 +1,5 @@ use crate::abi::{self, align_to, scratch, LocalSlot}; -use crate::codegen::{CodeGenContext, FuncEnv}; +use crate::codegen::{CodeGenContext, Emission, FuncEnv}; use crate::isa::reg::{writable, Reg, WritableReg}; use cranelift_codegen::{ binemit::CodeOffset, @@ -744,11 +744,11 @@ pub(crate) trait MacroAssembler { fn float_neg(&mut self, dst: WritableReg, size: OperandSize); /// Perform a floating point floor operation. - fn float_round, &mut CodeGenContext, &mut Self)>( + fn float_round, &mut CodeGenContext, &mut Self)>( &mut self, mode: RoundingMode, env: &mut FuncEnv, - context: &mut CodeGenContext, + context: &mut CodeGenContext, size: OperandSize, fallback: F, ); @@ -781,7 +781,7 @@ pub(crate) trait MacroAssembler { /// caller from having to deal with the architecture specific constraints /// we give this function access to the code generation context, allowing /// each implementation to decide the lowering path. - fn shift(&mut self, context: &mut CodeGenContext, kind: ShiftKind, size: OperandSize); + fn shift(&mut self, context: &mut CodeGenContext, kind: ShiftKind, size: OperandSize); /// Perform division operation. /// Division is special in that some architectures have specific @@ -794,10 +794,10 @@ pub(crate) trait MacroAssembler { /// unconstrained binary operation, the caller can decide to use /// the `CodeGenContext::i32_binop` or `CodeGenContext::i64_binop` /// functions. - fn div(&mut self, context: &mut CodeGenContext, kind: DivKind, size: OperandSize); + fn div(&mut self, context: &mut CodeGenContext, kind: DivKind, size: OperandSize); /// Calculate remainder. - fn rem(&mut self, context: &mut CodeGenContext, kind: RemKind, size: OperandSize); + fn rem(&mut self, context: &mut CodeGenContext, kind: RemKind, size: OperandSize); /// Compares `src1` against `src2` for the side effect of setting processor /// flags. @@ -852,7 +852,7 @@ pub(crate) trait MacroAssembler { /// Count the number of 1 bits in src and put the result in dst. In x64, /// this will emit multiple instructions if the `has_popcnt` flag is false. - fn popcnt(&mut self, context: &mut CodeGenContext, size: OperandSize); + fn popcnt(&mut self, context: &mut CodeGenContext, size: OperandSize); /// Converts an i64 to an i32 by discarding the high 32 bits. fn wrap(&mut self, dst: WritableReg, src: Reg); @@ -1053,5 +1053,5 @@ pub(crate) trait MacroAssembler { /// /// Note that some platforms require special handling of registers in this /// instruction (e.g. x64) so full access to `CodeGenContext` is provided. - fn mul_wide(&mut self, context: &mut CodeGenContext, kind: MulWideKind); + fn mul_wide(&mut self, context: &mut CodeGenContext, kind: MulWideKind); } diff --git a/winch/codegen/src/visitor.rs b/winch/codegen/src/visitor.rs index c38cd41ac1ed..1fae5644330e 100644 --- a/winch/codegen/src/visitor.rs +++ b/winch/codegen/src/visitor.rs @@ -5,7 +5,7 @@ //! machine code emitter. use crate::abi::RetArea; -use crate::codegen::{control_index, Callee, CodeGen, ControlStackFrame, FnCall}; +use crate::codegen::{control_index, Callee, CodeGen, ControlStackFrame, Emission, FnCall}; use crate::masm::{ DivKind, ExtendKind, FloatCmpKind, IntCmpKind, MacroAssembler, MemMoveDirection, MulWideKind, OperandSize, RegImm, RemKind, RoundingMode, SPOffset, ShiftKind, TruncKind, @@ -253,7 +253,7 @@ macro_rules! def_unsupported { (emit $unsupported:tt $($rest:tt)*) => {$($rest)*}; } -impl<'a, 'translation, 'data, M> VisitOperator<'a> for CodeGen<'a, 'translation, 'data, M> +impl<'a, 'translation, 'data, M> VisitOperator<'a> for CodeGen<'a, 'translation, 'data, M, Emission> where M: MacroAssembler, { @@ -2212,7 +2212,8 @@ where wasmparser::for_each_visit_operator!(def_unsupported); } -impl<'a, 'translation, 'data, M> VisitSimdOperator<'a> for CodeGen<'a, 'translation, 'data, M> +impl<'a, 'translation, 'data, M> VisitSimdOperator<'a> + for CodeGen<'a, 'translation, 'data, M, Emission> where M: MacroAssembler, { @@ -2231,7 +2232,7 @@ where wasmparser::for_each_visit_simd_operator!(def_unsupported); } -impl<'a, 'translation, 'data, M> CodeGen<'a, 'translation, 'data, M> +impl<'a, 'translation, 'data, M> CodeGen<'a, 'translation, 'data, M, Emission> where M: MacroAssembler, { From abcd6accd4a990c8efa9faff8f2715812ebd6d7a Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Wed, 4 Dec 2024 11:31:21 -0800 Subject: [PATCH 19/21] Port wasmtime-fiber to `no_std` and allow `async` feature in `no_std` Wasmtime. (#9689) This PR allows a `no_std` Wasmtime build to be configured with the `async` feature. (Previously, a minimal `no_std` configuration could only run with sync entry points, without suspending of stacks.) The main hurdle to this support was the `wasmtime-fiber` crate. Fortunately, the "unix" variant of fibers was almost entirely portable to a `no_std` environment, owing to the fact that it implements stack-switching manually in assembly itself. I moved the per-ISA implementations to a shared submodule and built the nostd platform backend for `wasmtime-fiber` with a stripped-down version of the unix backend. The nostd backend does not support mmap'd stacks, does not support custom stack allocators, and does not propagate panics. prtest:full --- .github/workflows/main.yml | 22 ++- crates/asm-macros/src/lib.rs | 6 +- crates/fiber/Cargo.toml | 8 +- crates/fiber/build.rs | 4 +- crates/fiber/src/lib.rs | 82 +++++--- crates/fiber/src/nostd.rs | 178 ++++++++++++++++++ crates/fiber/src/stackswitch.rs | 38 ++++ .../src/{unix => stackswitch}/aarch64.rs | 0 crates/fiber/src/{unix => stackswitch}/arm.rs | 0 .../src/{unix => stackswitch}/riscv64.rs | 0 .../fiber/src/{unix => stackswitch}/s390x.S | 0 crates/fiber/src/{unix => stackswitch}/x86.rs | 0 .../fiber/src/{unix => stackswitch}/x86_64.rs | 0 crates/fiber/src/unix.rs | 40 +--- crates/fiber/src/windows.rs | 3 + crates/wasmtime/Cargo.toml | 2 +- crates/wasmtime/src/runtime/stack.rs | 3 +- 17 files changed, 320 insertions(+), 66 deletions(-) create mode 100644 crates/fiber/src/nostd.rs create mode 100644 crates/fiber/src/stackswitch.rs rename crates/fiber/src/{unix => stackswitch}/aarch64.rs (100%) rename crates/fiber/src/{unix => stackswitch}/arm.rs (100%) rename crates/fiber/src/{unix => stackswitch}/riscv64.rs (100%) rename crates/fiber/src/{unix => stackswitch}/s390x.S (100%) rename crates/fiber/src/{unix => stackswitch}/x86.rs (100%) rename crates/fiber/src/{unix => stackswitch}/x86_64.rs (100%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index baa49cf169bf..62c228fea5c3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -356,11 +356,12 @@ jobs: -p wasmtime --no-default-features --features profiling -p wasmtime --no-default-features --features cache -p wasmtime --no-default-features --features async + -p wasmtime --no-default-features --features std -p wasmtime --no-default-features --features pooling-allocator -p wasmtime --no-default-features --features cranelift -p wasmtime --no-default-features --features component-model -p wasmtime --no-default-features --features runtime,component-model - -p wasmtime --no-default-features --features cranelift,wat,async,cache + -p wasmtime --no-default-features --features cranelift,wat,async,std,cache -p wasmtime --no-default-features --features winch -p wasmtime --no-default-features --features wmemcheck -p wasmtime --no-default-features --features wmemcheck,cranelift,runtime @@ -384,6 +385,12 @@ jobs: -p wasmtime --features incremental-cache -p wasmtime --all-features + - name: wasmtime-fiber + checks: | + -p wasmtime-fiber --no-default-features + -p wasmtime-fiber --no-default-features --features std + -p wasmtime-fiber --all-features + - name: wasmtime-cli checks: | -p wasmtime-cli --no-default-features @@ -432,6 +439,18 @@ jobs: env: GH_TOKEN: ${{ github.token }} + fiber_tests: + name: wasmtime-fiber tests + runs-on: ubuntu-latest + env: + CARGO_NDK_VERSION: 2.12.2 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/actions/install-rust + - run: cargo test -p wasmtime-fiber --no-default-features + # Checks for no_std support, ensure that crates can build on a no_std target no_std_checks: name: no_std checks @@ -1192,6 +1211,7 @@ jobs: - cargo_vet - doc - micro_checks + - fiber_tests - no_std_checks - clippy - monolith_checks diff --git a/crates/asm-macros/src/lib.rs b/crates/asm-macros/src/lib.rs index 0fd62e8b382f..92b04380b489 100644 --- a/crates/asm-macros/src/lib.rs +++ b/crates/asm-macros/src/lib.rs @@ -13,7 +13,7 @@ cfg_if::cfg_if! { #[macro_export] macro_rules! asm_func { ($name:expr, $body:expr $(, $($args:tt)*)?) => { - std::arch::global_asm!( + core::arch::global_asm!( concat!( ".p2align 4\n", ".private_extern _", $name, "\n", @@ -29,7 +29,7 @@ cfg_if::cfg_if! { #[macro_export] macro_rules! asm_func { ($name:expr, $body:expr $(, $($args:tt)*)?) => { - std::arch::global_asm!( + core::arch::global_asm!( concat!( ".def ", $name, "\n", ".scl 2\n", @@ -65,7 +65,7 @@ cfg_if::cfg_if! { #[macro_export] macro_rules! asm_func { ($name:expr, $body:expr $(, $($args:tt)*)?) => { - std::arch::global_asm!( + core::arch::global_asm!( concat!( ".p2align 4\n", ".hidden ", $name, "\n", diff --git a/crates/fiber/Cargo.toml b/crates/fiber/Cargo.toml index 8d83fd03553f..55f0087767ea 100644 --- a/crates/fiber/Cargo.toml +++ b/crates/fiber/Cargo.toml @@ -15,10 +15,10 @@ workspace = true anyhow = { workspace = true } cfg-if = { workspace = true } wasmtime-versioned-export-macros = { workspace = true } +wasmtime-asm-macros = { workspace = true } [target.'cfg(unix)'.dependencies] rustix = { workspace = true, features = ["mm", "param"] } -wasmtime-asm-macros = { workspace = true } [target.'cfg(windows)'.dependencies.windows-sys] workspace = true @@ -33,3 +33,9 @@ wasmtime-versioned-export-macros = { workspace = true } [dev-dependencies] backtrace = "0.3.68" + +[features] + +# Assume presence of the standard library. Allows propagating +# panic-unwinds across fiber invocations. +std = [] diff --git a/crates/fiber/build.rs b/crates/fiber/build.rs index 19e7a516259c..d14343fc0893 100644 --- a/crates/fiber/build.rs +++ b/crates/fiber/build.rs @@ -23,8 +23,8 @@ fn main() { build.file("src/windows.c"); build.define("VERSIONED_SUFFIX", Some(versioned_suffix!())); } else if arch == "s390x" { - println!("cargo:rerun-if-changed=src/unix/s390x.S"); - build.file("src/unix/s390x.S"); + println!("cargo:rerun-if-changed=src/stackswitch/s390x.S"); + build.file("src/stackswitch/s390x.S"); build.define("VERSIONED_SUFFIX", Some(versioned_suffix!())); } else { // assume that this is included via inline assembly in the crate itself, diff --git a/crates/fiber/src/lib.rs b/crates/fiber/src/lib.rs index 06a188a62330..11cbe912f11b 100644 --- a/crates/fiber/src/lib.rs +++ b/crates/fiber/src/lib.rs @@ -1,15 +1,22 @@ #![expect(clippy::allow_attributes, reason = "crate not migrated yet")] +#![no_std] +#[cfg(any(feature = "std", unix, windows))] +#[macro_use] +extern crate std; +extern crate alloc; + +use alloc::boxed::Box; use anyhow::Error; -use std::any::Any; -use std::cell::Cell; -use std::io; -use std::marker::PhantomData; -use std::ops::Range; -use std::panic::{self, AssertUnwindSafe}; +use core::cell::Cell; +use core::marker::PhantomData; +use core::ops::Range; cfg_if::cfg_if! { - if #[cfg(windows)] { + if #[cfg(not(feature = "std"))] { + mod nostd; + use nostd as imp; + } else if #[cfg(windows)] { mod windows; use windows as imp; } else if #[cfg(unix)] { @@ -20,6 +27,11 @@ cfg_if::cfg_if! { } } +// Our own stack switcher routines are used on Unix and no_std +// platforms, but not on Windows (it has its own fiber API). +#[cfg(any(unix, not(feature = "std")))] +pub(crate) mod stackswitch; + /// Represents an execution stack to use for a fiber. pub struct FiberStack(imp::FiberStack); @@ -31,14 +43,16 @@ fn _assert_send_sync() { _assert_sync::(); } +pub type Result = core::result::Result; + impl FiberStack { /// Creates a new fiber stack of the given size. - pub fn new(size: usize) -> io::Result { + pub fn new(size: usize) -> Result { Ok(Self(imp::FiberStack::new(size)?)) } /// Creates a new fiber stack of the given size. - pub fn from_custom(custom: Box) -> io::Result { + pub fn from_custom(custom: Box) -> Result { Ok(Self(imp::FiberStack::from_custom(custom)?)) } @@ -55,11 +69,7 @@ impl FiberStack { /// /// The caller must properly allocate the stack space with a guard page and /// make the pages accessible for correct behavior. - pub unsafe fn from_raw_parts( - bottom: *mut u8, - guard_size: usize, - len: usize, - ) -> io::Result { + pub unsafe fn from_raw_parts(bottom: *mut u8, guard_size: usize, len: usize) -> Result { Ok(Self(imp::FiberStack::from_raw_parts( bottom, guard_size, len, )?)) @@ -128,7 +138,8 @@ enum RunResult { Resuming(Resume), Yield(Yield), Returned(Return), - Panicked(Box), + #[cfg(feature = "std")] + Panicked(Box), } impl<'a, Resume, Yield, Return> Fiber<'a, Resume, Yield, Return> { @@ -140,7 +151,7 @@ impl<'a, Resume, Yield, Return> Fiber<'a, Resume, Yield, Return> { pub fn new( stack: FiberStack, func: impl FnOnce(Resume, &mut Suspend) -> Return + 'a, - ) -> io::Result { + ) -> Result { let inner = imp::Fiber::new(&stack.0, func)?; Ok(Self { @@ -177,7 +188,11 @@ impl<'a, Resume, Yield, Return> Fiber<'a, Resume, Yield, Return> { Err(y) } RunResult::Returned(r) => Ok(r), - RunResult::Panicked(payload) => std::panic::resume_unwind(payload), + #[cfg(feature = "std")] + RunResult::Panicked(_payload) => { + use std::panic; + panic::resume_unwind(_payload); + } } } @@ -222,11 +237,27 @@ impl Suspend { inner, _phantom: PhantomData, }; - let result = panic::catch_unwind(AssertUnwindSafe(|| (func)(initial, &mut suspend))); - suspend.inner.switch::(match result { - Ok(result) => RunResult::Returned(result), - Err(panic) => RunResult::Panicked(panic), - }); + + #[cfg(feature = "std")] + { + use std::panic::{self, AssertUnwindSafe}; + let result = panic::catch_unwind(AssertUnwindSafe(|| (func)(initial, &mut suspend))); + suspend.inner.switch::(match result { + Ok(result) => RunResult::Returned(result), + Err(panic) => RunResult::Panicked(panic), + }); + } + // Note that it is sound to omit the `catch_unwind` here: it + // will not result in unwinding going off the top of the fiber + // stack, because the code on the fiber stack is invoked via + // an extern "C" boundary which will panic on unwinds. + #[cfg(not(feature = "std"))] + { + let result = (func)(initial, &mut suspend); + suspend + .inner + .switch::(RunResult::Returned(result)); + } } } @@ -236,11 +267,11 @@ impl Drop for Fiber<'_, A, B, C> { } } -#[cfg(test)] +#[cfg(all(test))] mod tests { use super::{Fiber, FiberStack}; + use alloc::string::ToString; use std::cell::Cell; - use std::panic::{self, AssertUnwindSafe}; use std::rc::Rc; #[test] @@ -332,7 +363,10 @@ mod tests { } #[test] + #[cfg(feature = "std")] fn panics_propagated() { + use std::panic::{self, AssertUnwindSafe}; + let a = Rc::new(Cell::new(false)); let b = SetOnDrop(a.clone()); let fiber = diff --git a/crates/fiber/src/nostd.rs b/crates/fiber/src/nostd.rs new file mode 100644 index 000000000000..48bf3b6eae69 --- /dev/null +++ b/crates/fiber/src/nostd.rs @@ -0,0 +1,178 @@ +//! no_std implementation of fibers. +//! +//! This is a very stripped-down version of the Unix platform support, +//! but without mmap or guard pages, because on no_std systems we do +//! not assume that virtual memory exists. +//! +//! The stack layout is nevertheless the same (modulo the guard page) +//! as on Unix because we share its low-level implementations: +//! +//! ```text +//! 0xB000 +-----------------------+ <- top of stack +//! | &Cell | <- where to store results +//! 0xAff8 +-----------------------+ +//! | *const u8 | <- last sp to resume from +//! 0xAff0 +-----------------------+ <- 16-byte aligned +//! | | +//! ~ ... ~ <- actual native stack space to use +//! | | +//! 0x0000 +-----------------------+ +//! ``` +//! +//! Here `0xAff8` is filled in temporarily while `resume` is running. The fiber +//! started with 0xB000 as a parameter so it knows how to find this. +//! Additionally `resumes` stores state at 0xAff0 to restart execution, and +//! `suspend`, which has 0xB000 so it can find this, will read that and write +//! its own resumption information into this slot as well. + +use crate::stackswitch::*; +use crate::{Result, RunResult, RuntimeFiberStack}; +use alloc::boxed::Box; +use alloc::{vec, vec::Vec}; +use core::cell::Cell; +use core::ops::Range; + +// The no_std implementation is infallible in practice, but we use +// `anyhow::Error` here absent any better alternative. +pub type Error = anyhow::Error; + +pub struct FiberStack { + base: BasePtr, + len: usize, + /// Backing storage, if owned. Allocated once at startup and then + /// not reallocated afterward. + storage: Vec, +} + +struct BasePtr(*mut u8); + +unsafe impl Send for BasePtr {} +unsafe impl Sync for BasePtr {} + +const STACK_ALIGN: usize = 16; + +/// Align a pointer by incrementing it up to `align - 1` +/// bytes. `align` must be a power of two. Also updates the length as +/// appropriate so that `ptr + len` points to the same endpoint. +fn align_ptr(ptr: *mut u8, len: usize, align: usize) -> (*mut u8, usize) { + let ptr = ptr as usize; + let aligned = (ptr + align - 1) & !(align - 1); + let new_len = len - (aligned - ptr); + (aligned as *mut u8, new_len) +} + +impl FiberStack { + pub fn new(size: usize) -> Result { + // Round up the size to at least one page. + let size = core::cmp::max(4096, size); + let mut storage = vec![0; size]; + let (base, len) = align_ptr(storage.as_mut_ptr(), size, STACK_ALIGN); + Ok(FiberStack { + storage, + base: BasePtr(base), + len, + }) + } + + pub unsafe fn from_raw_parts(base: *mut u8, guard_size: usize, len: usize) -> Result { + Ok(FiberStack { + storage: vec![], + base: BasePtr(base.offset(isize::try_from(guard_size).unwrap())), + len, + }) + } + + pub fn is_from_raw_parts(&self) -> bool { + self.storage.is_empty() + } + + pub fn from_custom(_custom: Box) -> Result { + unimplemented!("Custom fiber stacks not supported in no_std fiber library") + } + + pub fn top(&self) -> Option<*mut u8> { + Some(self.base.0.wrapping_byte_add(self.len)) + } + + pub fn range(&self) -> Option> { + let base = self.base.0 as usize; + Some(base..base + self.len) + } + + pub fn guard_range(&self) -> Option> { + None + } +} + +pub struct Fiber; + +pub struct Suspend { + top_of_stack: *mut u8, +} + +extern "C" fn fiber_start(arg0: *mut u8, top_of_stack: *mut u8) +where + F: FnOnce(A, &mut super::Suspend) -> C, +{ + unsafe { + let inner = Suspend { top_of_stack }; + let initial = inner.take_resume::(); + super::Suspend::::execute(inner, initial, Box::from_raw(arg0.cast::())) + } +} + +impl Fiber { + pub fn new(stack: &FiberStack, func: F) -> Result + where + F: FnOnce(A, &mut super::Suspend) -> C, + { + unsafe { + let data = Box::into_raw(Box::new(func)).cast(); + wasmtime_fiber_init(stack.top().unwrap(), fiber_start::, data); + } + + Ok(Self) + } + + pub(crate) fn resume(&self, stack: &FiberStack, result: &Cell>) { + unsafe { + // Store where our result is going at the very tip-top of the + // stack, otherwise known as our reserved slot for this information. + // + // In the diagram above this is updating address 0xAff8 + let addr = stack.top().unwrap().cast::().offset(-1); + addr.write(result as *const _ as usize); + + wasmtime_fiber_switch(stack.top().unwrap()); + + // null this out to help catch use-after-free + addr.write(0); + } + } +} + +impl Suspend { + pub(crate) fn switch(&mut self, result: RunResult) -> A { + unsafe { + // Calculate 0xAff8 and then write to it + (*self.result_location::()).set(result); + + wasmtime_fiber_switch(self.top_of_stack); + + self.take_resume::() + } + } + + unsafe fn take_resume(&self) -> A { + match (*self.result_location::()).replace(RunResult::Executing) { + RunResult::Resuming(val) => val, + _ => panic!("not in resuming state"), + } + } + + unsafe fn result_location(&self) -> *const Cell> { + let ret = self.top_of_stack.cast::<*const u8>().offset(-1).read(); + assert!(!ret.is_null()); + ret.cast() + } +} diff --git a/crates/fiber/src/stackswitch.rs b/crates/fiber/src/stackswitch.rs new file mode 100644 index 000000000000..5e32bb989fb8 --- /dev/null +++ b/crates/fiber/src/stackswitch.rs @@ -0,0 +1,38 @@ +//! ISA-specific stack-switching routines. + +// The bodies are defined in inline assembly in the conditionally +// included modules below; their symbols are visible in the binary and +// accessed via the `extern "C"` declarations below that. + +cfg_if::cfg_if! { + if #[cfg(target_arch = "aarch64")] { + mod aarch64; + } else if #[cfg(target_arch = "x86_64")] { + mod x86_64; + } else if #[cfg(target_arch = "x86")] { + mod x86; + } else if #[cfg(target_arch = "arm")] { + mod arm; + } else if #[cfg(target_arch = "s390x")] { + // currently `global_asm!` isn't stable on s390x so this is an external + // assembler file built with the `build.rs`. + } else if #[cfg(target_arch = "riscv64")] { + mod riscv64; + } else { + compile_error!("fibers are not supported on this CPU architecture"); + } +} + +extern "C" { + #[wasmtime_versioned_export_macros::versioned_link] + pub(crate) fn wasmtime_fiber_init( + top_of_stack: *mut u8, + entry: extern "C" fn(*mut u8, *mut u8), + entry_arg0: *mut u8, + ); + #[wasmtime_versioned_export_macros::versioned_link] + pub(crate) fn wasmtime_fiber_switch(top_of_stack: *mut u8); + #[allow(dead_code, reason = "only used on some platforms for inline asm")] + #[wasmtime_versioned_export_macros::versioned_link] + pub(crate) fn wasmtime_fiber_start(); +} diff --git a/crates/fiber/src/unix/aarch64.rs b/crates/fiber/src/stackswitch/aarch64.rs similarity index 100% rename from crates/fiber/src/unix/aarch64.rs rename to crates/fiber/src/stackswitch/aarch64.rs diff --git a/crates/fiber/src/unix/arm.rs b/crates/fiber/src/stackswitch/arm.rs similarity index 100% rename from crates/fiber/src/unix/arm.rs rename to crates/fiber/src/stackswitch/arm.rs diff --git a/crates/fiber/src/unix/riscv64.rs b/crates/fiber/src/stackswitch/riscv64.rs similarity index 100% rename from crates/fiber/src/unix/riscv64.rs rename to crates/fiber/src/stackswitch/riscv64.rs diff --git a/crates/fiber/src/unix/s390x.S b/crates/fiber/src/stackswitch/s390x.S similarity index 100% rename from crates/fiber/src/unix/s390x.S rename to crates/fiber/src/stackswitch/s390x.S diff --git a/crates/fiber/src/unix/x86.rs b/crates/fiber/src/stackswitch/x86.rs similarity index 100% rename from crates/fiber/src/unix/x86.rs rename to crates/fiber/src/stackswitch/x86.rs diff --git a/crates/fiber/src/unix/x86_64.rs b/crates/fiber/src/stackswitch/x86_64.rs similarity index 100% rename from crates/fiber/src/unix/x86_64.rs rename to crates/fiber/src/stackswitch/x86_64.rs diff --git a/crates/fiber/src/unix.rs b/crates/fiber/src/unix.rs index 65d6c78d5cff..a3e8dd6b7f6a 100644 --- a/crates/fiber/src/unix.rs +++ b/crates/fiber/src/unix.rs @@ -29,12 +29,16 @@ //! `suspend`, which has 0xB000 so it can find this, will read that and write //! its own resumption information into this slot as well. +use crate::stackswitch::*; use crate::{RunResult, RuntimeFiberStack}; +use std::boxed::Box; use std::cell::Cell; use std::io; use std::ops::Range; use std::ptr; +pub type Error = io::Error; + pub struct FiberStack { base: BasePtr, len: usize, @@ -192,20 +196,6 @@ pub struct Suspend { previous: asan::PreviousStack, } -extern "C" { - #[wasmtime_versioned_export_macros::versioned_link] - fn wasmtime_fiber_init( - top_of_stack: *mut u8, - entry: extern "C" fn(*mut u8, *mut u8), - entry_arg0: *mut u8, - ); - #[wasmtime_versioned_export_macros::versioned_link] - fn wasmtime_fiber_switch(top_of_stack: *mut u8); - #[allow(dead_code, reason = "only used on some platforms for inline asm")] - #[wasmtime_versioned_export_macros::versioned_link] - fn wasmtime_fiber_start(); -} - extern "C" fn fiber_start(arg0: *mut u8, top_of_stack: *mut u8) where F: FnOnce(A, &mut super::Suspend) -> C, @@ -288,25 +278,6 @@ impl Suspend { } } -cfg_if::cfg_if! { - if #[cfg(target_arch = "aarch64")] { - mod aarch64; - } else if #[cfg(target_arch = "x86_64")] { - mod x86_64; - } else if #[cfg(target_arch = "x86")] { - mod x86; - } else if #[cfg(target_arch = "arm")] { - mod arm; - } else if #[cfg(target_arch = "s390x")] { - // currently `global_asm!` isn't stable on s390x so this is an external - // assembler file built with the `build.rs`. - } else if #[cfg(target_arch = "riscv64")] { - mod riscv64; - } else { - compile_error!("fibers are not supported on this CPU architecture"); - } -} - /// Support for AddressSanitizer to support stack manipulations we do in this /// fiber implementation. /// @@ -320,6 +291,8 @@ cfg_if::cfg_if! { #[cfg(asan)] mod asan { use super::{FiberStack, MmapFiberStack, RuntimeFiberStack}; + use alloc::boxed::Box; + use alloc::vec::Vec; use rustix::param::page_size; use std::mem::ManuallyDrop; use std::ops::Range; @@ -481,6 +454,7 @@ mod asan { #[cfg(not(asan))] mod asan_disabled { use super::{FiberStack, RuntimeFiberStack}; + use std::boxed::Box; #[derive(Default)] pub struct PreviousStack; diff --git a/crates/fiber/src/windows.rs b/crates/fiber/src/windows.rs index 16203bd5c926..2ce5f8464cc0 100644 --- a/crates/fiber/src/windows.rs +++ b/crates/fiber/src/windows.rs @@ -1,4 +1,5 @@ use crate::{RunResult, RuntimeFiberStack}; +use alloc::boxed::Box; use std::cell::Cell; use std::ffi::c_void; use std::io; @@ -7,6 +8,8 @@ use std::ptr; use windows_sys::Win32::Foundation::*; use windows_sys::Win32::System::Threading::*; +pub type Error = io::Error; + #[derive(Debug)] pub struct FiberStack(usize); diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml index 63c1eafbb20c..53497575eac2 100644 --- a/crates/wasmtime/Cargo.toml +++ b/crates/wasmtime/Cargo.toml @@ -185,7 +185,6 @@ async = [ "dep:async-trait", "wasmtime-component-macro?/async", "runtime", - "std", ] # Enables support for the pooling instance allocation strategy @@ -315,6 +314,7 @@ std = [ 'wasmtime-environ/std', 'object/std', 'once_cell', + 'wasmtime-fiber?/std', # technically this isn't necessary but once you have the standard library you # probably want things to go fast in which case you've probably got signal # handlers and such so implicitly enable this. This also helps reduce the diff --git a/crates/wasmtime/src/runtime/stack.rs b/crates/wasmtime/src/runtime/stack.rs index 94f5732ec40f..458558525c73 100644 --- a/crates/wasmtime/src/runtime/stack.rs +++ b/crates/wasmtime/src/runtime/stack.rs @@ -1,5 +1,6 @@ use crate::prelude::*; -use std::{ops::Range, sync::Arc}; +use alloc::sync::Arc; +use core::ops::Range; use wasmtime_fiber::{RuntimeFiberStack, RuntimeFiberStackCreator}; /// A stack creator. Can be used to provide a stack creator to wasmtime From d1ff945e947288fd38a162a6dc2a184d7abe87e5 Mon Sep 17 00:00:00 2001 From: Xinzhao Xu Date: Thu, 5 Dec 2024 05:37:10 +0800 Subject: [PATCH 20/21] wasi-http: make the buffer and budget capacity of the OutgoingBody writer configurable (#9670) --- .../bin/http_outbound_request_large_post.rs | 11 ++++-- crates/test-programs/src/http.rs | 29 +++++++-------- crates/wasi-http/src/body.rs | 16 +++++--- crates/wasi-http/src/types.rs | 37 +++++++++++++++++++ crates/wasi-http/src/types_impl.rs | 10 ++++- 5 files changed, 77 insertions(+), 26 deletions(-) diff --git a/crates/test-programs/src/bin/http_outbound_request_large_post.rs b/crates/test-programs/src/bin/http_outbound_request_large_post.rs index 4e07493694a6..2f66daae7710 100644 --- a/crates/test-programs/src/bin/http_outbound_request_large_post.rs +++ b/crates/test-programs/src/bin/http_outbound_request_large_post.rs @@ -3,8 +3,11 @@ use std::io::{self, Read}; use test_programs::wasi::http::types::{Method, Scheme}; fn main() { - // TODO: ensure more than 700 bytes is allowed without error - const LEN: usize = 700; + // Make sure the final body is larger than 1024*1024, but we cannot allocate + // so much memory directly in the wasm program, so we use the `repeat` + // method to increase the body size. + const LEN: usize = 1024; + const REPEAT: usize = 1025; let mut buffer = [0; LEN]; let addr = std::env::var("HTTP_SERVER").unwrap(); io::repeat(0b001).read_exact(&mut buffer).unwrap(); @@ -13,7 +16,7 @@ fn main() { Scheme::Http, &addr, "/post", - Some(&buffer), + Some(&buffer.repeat(REPEAT)), None, None, None, @@ -26,5 +29,5 @@ fn main() { assert_eq!(res.status, 200); let method = res.header("x-wasmtime-test-method").unwrap(); assert_eq!(std::str::from_utf8(method).unwrap(), "POST"); - assert_eq!(res.body.len(), LEN); + assert_eq!(res.body.len(), LEN * REPEAT); } diff --git a/crates/test-programs/src/http.rs b/crates/test-programs/src/http.rs index cde88cb621d6..b2272699f6f2 100644 --- a/crates/test-programs/src/http.rs +++ b/crates/test-programs/src/http.rs @@ -74,6 +74,20 @@ pub fn request( .body() .map_err(|_| anyhow!("outgoing request write failed"))?; + let options = http_types::RequestOptions::new(); + options + .set_connect_timeout(connect_timeout) + .map_err(|()| anyhow!("failed to set connect_timeout"))?; + options + .set_first_byte_timeout(first_by_timeout) + .map_err(|()| anyhow!("failed to set first_byte_timeout"))?; + options + .set_between_bytes_timeout(between_bytes_timeout) + .map_err(|()| anyhow!("failed to set between_bytes_timeout"))?; + let options = Some(options); + + let future_response = outgoing_handler::handle(request, options)?; + if let Some(mut buf) = body { let request_body = outgoing_body .write() @@ -110,21 +124,6 @@ pub fn request( Err(_) => anyhow::bail!("output stream error"), }; } - - let options = http_types::RequestOptions::new(); - options - .set_connect_timeout(connect_timeout) - .map_err(|()| anyhow!("failed to set connect_timeout"))?; - options - .set_first_byte_timeout(first_by_timeout) - .map_err(|()| anyhow!("failed to set first_byte_timeout"))?; - options - .set_between_bytes_timeout(between_bytes_timeout) - .map_err(|()| anyhow!("failed to set between_bytes_timeout"))?; - let options = Some(options); - - let future_response = outgoing_handler::handle(request, options)?; - http_types::OutgoingBody::finish(outgoing_body, None)?; let incoming_response = match future_response.get() { diff --git a/crates/wasi-http/src/body.rs b/crates/wasi-http/src/body.rs index 5913a4922df9..96c783964746 100644 --- a/crates/wasi-http/src/body.rs +++ b/crates/wasi-http/src/body.rs @@ -423,7 +423,14 @@ pub struct HostOutgoingBody { impl HostOutgoingBody { /// Create a new `HostOutgoingBody` - pub fn new(context: StreamContext, size: Option) -> (Self, HyperOutgoingBody) { + pub fn new( + context: StreamContext, + size: Option, + buffer_chunks: usize, + chunk_size: usize, + ) -> (Self, HyperOutgoingBody) { + assert!(buffer_chunks >= 1); + let written = size.map(WrittenState::new); use tokio::sync::oneshot::error::RecvError; @@ -469,7 +476,8 @@ impl HostOutgoingBody { } } - let (body_sender, body_receiver) = mpsc::channel(2); + // always add 1 buffer here because one empty slot is required + let (body_sender, body_receiver) = mpsc::channel(buffer_chunks + 1); let (finish_sender, finish_receiver) = oneshot::channel(); let body_impl = BodyImpl { body_receiver, @@ -477,9 +485,7 @@ impl HostOutgoingBody { } .boxed(); - // TODO: this capacity constant is arbitrary, and should be configurable - let output_stream = - BodyWriteStream::new(context, 1024 * 1024, body_sender, written.clone()); + let output_stream = BodyWriteStream::new(context, chunk_size, body_sender, written.clone()); ( Self { diff --git a/crates/wasi-http/src/types.rs b/crates/wasi-http/src/types.rs index 4821e65c2ee7..912c72513b0e 100644 --- a/crates/wasi-http/src/types.rs +++ b/crates/wasi-http/src/types.rs @@ -125,6 +125,19 @@ pub trait WasiHttpView: Send { fn is_forbidden_header(&mut self, _name: &HeaderName) -> bool { false } + + /// Number of distinct write calls to the outgoing body's output-stream + /// that the implementation will buffer. + /// Default: 1. + fn outgoing_body_buffer_chunks(&mut self) -> usize { + 1 + } + + /// Maximum size allowed in a write call to the outgoing body's output-stream. + /// Default: 1024 * 1024. + fn outgoing_body_chunk_size(&mut self) -> usize { + 1024 * 1024 + } } impl WasiHttpView for &mut T { @@ -156,6 +169,14 @@ impl WasiHttpView for &mut T { fn is_forbidden_header(&mut self, name: &HeaderName) -> bool { T::is_forbidden_header(self, name) } + + fn outgoing_body_buffer_chunks(&mut self) -> usize { + T::outgoing_body_buffer_chunks(self) + } + + fn outgoing_body_chunk_size(&mut self) -> usize { + T::outgoing_body_chunk_size(self) + } } impl WasiHttpView for Box { @@ -187,6 +208,14 @@ impl WasiHttpView for Box { fn is_forbidden_header(&mut self, name: &HeaderName) -> bool { T::is_forbidden_header(self, name) } + + fn outgoing_body_buffer_chunks(&mut self) -> usize { + T::outgoing_body_buffer_chunks(self) + } + + fn outgoing_body_chunk_size(&mut self) -> usize { + T::outgoing_body_chunk_size(self) + } } /// A concrete structure that all generated `Host` traits are implemented for. @@ -233,6 +262,14 @@ impl WasiHttpView for WasiHttpImpl { fn is_forbidden_header(&mut self, name: &HeaderName) -> bool { self.0.is_forbidden_header(name) } + + fn outgoing_body_buffer_chunks(&mut self) -> usize { + self.0.outgoing_body_buffer_chunks() + } + + fn outgoing_body_chunk_size(&mut self) -> usize { + self.0.outgoing_body_chunk_size() + } } /// Returns `true` when the header is forbidden according to this [`WasiHttpView`] implementation. diff --git a/crates/wasi-http/src/types_impl.rs b/crates/wasi-http/src/types_impl.rs index 2b6b5c15b04e..337c1a3c76f7 100644 --- a/crates/wasi-http/src/types_impl.rs +++ b/crates/wasi-http/src/types_impl.rs @@ -391,6 +391,8 @@ where &mut self, request: Resource, ) -> wasmtime::Result, ()>> { + let buffer_chunks = self.outgoing_body_buffer_chunks(); + let chunk_size = self.outgoing_body_chunk_size(); let req = self .table() .get_mut(&request) @@ -405,7 +407,8 @@ where Err(e) => return Ok(Err(e)), }; - let (host_body, hyper_body) = HostOutgoingBody::new(StreamContext::Request, size); + let (host_body, hyper_body) = + HostOutgoingBody::new(StreamContext::Request, size, buffer_chunks, chunk_size); req.body = Some(hyper_body); @@ -751,6 +754,8 @@ where &mut self, id: Resource, ) -> wasmtime::Result, ()>> { + let buffer_chunks = self.outgoing_body_buffer_chunks(); + let chunk_size = self.outgoing_body_chunk_size(); let resp = self.table().get_mut(&id)?; if resp.body.is_some() { @@ -762,7 +767,8 @@ where Err(e) => return Ok(Err(e)), }; - let (host, body) = HostOutgoingBody::new(StreamContext::Response, size); + let (host, body) = + HostOutgoingBody::new(StreamContext::Response, size, buffer_chunks, chunk_size); resp.body.replace(body); From d2d3872725b223236bbf9294a54904fe99ee9bae Mon Sep 17 00:00:00 2001 From: wasmtime-publish <59749941+wasmtime-publish@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:49:06 -0600 Subject: [PATCH 21/21] Bump Wasmtime to 29.0.0 (#9738) Co-authored-by: Wasmtime Publish --- Cargo.lock | 116 ++++----- Cargo.toml | 90 +++---- RELEASES.md | 3 +- cranelift/bforest/Cargo.toml | 2 +- cranelift/bitset/Cargo.toml | 2 +- cranelift/codegen/Cargo.toml | 8 +- cranelift/codegen/meta/Cargo.toml | 4 +- cranelift/codegen/shared/Cargo.toml | 2 +- cranelift/control/Cargo.toml | 2 +- cranelift/entity/Cargo.toml | 2 +- cranelift/frontend/Cargo.toml | 2 +- cranelift/interpreter/Cargo.toml | 2 +- cranelift/isle/isle/Cargo.toml | 2 +- cranelift/jit/Cargo.toml | 2 +- cranelift/module/Cargo.toml | 2 +- cranelift/native/Cargo.toml | 2 +- cranelift/object/Cargo.toml | 2 +- cranelift/reader/Cargo.toml | 2 +- cranelift/serde/Cargo.toml | 2 +- cranelift/umbrella/Cargo.toml | 2 +- crates/c-api/include/wasmtime.h | 4 +- supply-chain/imports.lock | 372 +++++++++++++++++++++------- 22 files changed, 408 insertions(+), 219 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d5ed322bdc3..6ac3d4a602e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -289,7 +289,7 @@ dependencies = [ [[package]] name = "byte-array-literals" -version = "28.0.0" +version = "29.0.0" [[package]] name = "byteorder" @@ -694,7 +694,7 @@ dependencies = [ [[package]] name = "cranelift" -version = "0.115.0" +version = "0.116.0" dependencies = [ "cranelift-codegen", "cranelift-frontend", @@ -707,14 +707,14 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.115.0" +version = "0.116.0" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.115.0" +version = "0.116.0" dependencies = [ "arbitrary", "serde", @@ -723,7 +723,7 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.115.0" +version = "0.116.0" dependencies = [ "anyhow", "bumpalo", @@ -755,25 +755,25 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.115.0" +version = "0.116.0" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.115.0" +version = "0.116.0" [[package]] name = "cranelift-control" -version = "0.115.0" +version = "0.116.0" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.115.0" +version = "0.116.0" dependencies = [ "cranelift-bitset", "serde", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.115.0" +version = "0.116.0" dependencies = [ "cranelift-codegen", "env_logger 0.11.5", @@ -836,7 +836,7 @@ dependencies = [ [[package]] name = "cranelift-interpreter" -version = "0.115.0" +version = "0.116.0" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -850,7 +850,7 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.115.0" +version = "0.116.0" dependencies = [ "codespan-reporting", "log", @@ -859,7 +859,7 @@ dependencies = [ [[package]] name = "cranelift-jit" -version = "0.115.0" +version = "0.116.0" dependencies = [ "anyhow", "cranelift", @@ -880,7 +880,7 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.115.0" +version = "0.116.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -892,7 +892,7 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.115.0" +version = "0.116.0" dependencies = [ "cranelift-codegen", "libc", @@ -901,7 +901,7 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.115.0" +version = "0.116.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "cranelift-reader" -version = "0.115.0" +version = "0.116.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -926,7 +926,7 @@ dependencies = [ [[package]] name = "cranelift-serde" -version = "0.115.0" +version = "0.116.0" dependencies = [ "clap", "cranelift-codegen", @@ -1185,7 +1185,7 @@ checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" [[package]] name = "embedding" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "dlmalloc", @@ -2092,7 +2092,7 @@ dependencies = [ [[package]] name = "min-platform-host" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "libloading", @@ -2475,7 +2475,7 @@ dependencies = [ [[package]] name = "pulley-interpreter" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "arbitrary", @@ -3598,7 +3598,7 @@ version = "0.1.0" [[package]] name = "verify-component-adapter" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "wasmparser 0.221.2", @@ -3648,7 +3648,7 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi-common" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "bitflags 2.6.0", @@ -3687,7 +3687,7 @@ dependencies = [ [[package]] name = "wasi-preview1-component-adapter" -version = "28.0.0" +version = "29.0.0" dependencies = [ "bitflags 2.6.0", "byte-array-literals", @@ -3943,7 +3943,7 @@ dependencies = [ [[package]] name = "wasmtime" -version = "28.0.0" +version = "29.0.0" dependencies = [ "addr2line", "anyhow", @@ -4005,14 +4005,14 @@ dependencies = [ [[package]] name = "wasmtime-asm-macros" -version = "28.0.0" +version = "29.0.0" dependencies = [ "cfg-if", ] [[package]] name = "wasmtime-bench-api" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "cap-std", @@ -4028,14 +4028,14 @@ dependencies = [ [[package]] name = "wasmtime-c-api" -version = "28.0.0" +version = "29.0.0" dependencies = [ "wasmtime-c-api-impl", ] [[package]] name = "wasmtime-c-api-impl" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "cap-std", @@ -4052,7 +4052,7 @@ dependencies = [ [[package]] name = "wasmtime-c-api-macros" -version = "28.0.0" +version = "29.0.0" dependencies = [ "proc-macro2", "quote", @@ -4060,7 +4060,7 @@ dependencies = [ [[package]] name = "wasmtime-cache" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "base64 0.21.0", @@ -4081,7 +4081,7 @@ dependencies = [ [[package]] name = "wasmtime-cli" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "async-trait", @@ -4152,7 +4152,7 @@ dependencies = [ [[package]] name = "wasmtime-cli-flags" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "clap", @@ -4165,7 +4165,7 @@ dependencies = [ [[package]] name = "wasmtime-component-macro" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "component-macro-test-helpers", @@ -4185,11 +4185,11 @@ dependencies = [ [[package]] name = "wasmtime-component-util" -version = "28.0.0" +version = "29.0.0" [[package]] name = "wasmtime-cranelift" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "cfg-if", @@ -4213,7 +4213,7 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "clap", @@ -4255,7 +4255,7 @@ dependencies = [ [[package]] name = "wasmtime-explorer" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "capstone", @@ -4270,7 +4270,7 @@ dependencies = [ [[package]] name = "wasmtime-fiber" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "backtrace", @@ -4342,7 +4342,7 @@ dependencies = [ [[package]] name = "wasmtime-jit-debug" -version = "28.0.0" +version = "29.0.0" dependencies = [ "object", "rustix", @@ -4351,7 +4351,7 @@ dependencies = [ [[package]] name = "wasmtime-jit-icache-coherence" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "cfg-if", @@ -4361,7 +4361,7 @@ dependencies = [ [[package]] name = "wasmtime-slab" -version = "28.0.0" +version = "29.0.0" [[package]] name = "wasmtime-test-macros" @@ -4376,7 +4376,7 @@ dependencies = [ [[package]] name = "wasmtime-versioned-export-macros" -version = "28.0.0" +version = "29.0.0" dependencies = [ "proc-macro2", "quote", @@ -4385,7 +4385,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "async-trait", @@ -4417,7 +4417,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-config" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "test-programs-artifacts", @@ -4428,7 +4428,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-http" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "async-trait", @@ -4454,7 +4454,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-keyvalue" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "test-programs-artifacts", @@ -4465,7 +4465,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-nn" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "cap-std", @@ -4486,7 +4486,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-threads" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "log", @@ -4498,7 +4498,7 @@ dependencies = [ [[package]] name = "wasmtime-wast" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "log", @@ -4508,7 +4508,7 @@ dependencies = [ [[package]] name = "wasmtime-wast-util" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "serde", @@ -4518,7 +4518,7 @@ dependencies = [ [[package]] name = "wasmtime-winch" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -4533,7 +4533,7 @@ dependencies = [ [[package]] name = "wasmtime-wit-bindgen" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "heck 0.5.0", @@ -4543,7 +4543,7 @@ dependencies = [ [[package]] name = "wasmtime-wmemcheck" -version = "28.0.0" +version = "29.0.0" [[package]] name = "wast" @@ -4621,7 +4621,7 @@ dependencies = [ [[package]] name = "wiggle" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "async-trait", @@ -4638,7 +4638,7 @@ dependencies = [ [[package]] name = "wiggle-generate" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "heck 0.5.0", @@ -4651,7 +4651,7 @@ dependencies = [ [[package]] name = "wiggle-macro" -version = "28.0.0" +version = "29.0.0" dependencies = [ "proc-macro2", "quote", @@ -4706,7 +4706,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winch-codegen" -version = "28.0.0" +version = "29.0.0" dependencies = [ "anyhow", "cranelift-codegen", diff --git a/Cargo.toml b/Cargo.toml index 2ec821c79311..53020a85ce88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -161,7 +161,7 @@ exclude = [ ] [workspace.package] -version = "28.0.0" +version = "29.0.0" authors = ["The Wasmtime Project Developers"] edition = "2021" # Wasmtime's current policy is that this number can be no larger than the @@ -197,60 +197,60 @@ allow_attributes_without_reason = 'warn' [workspace.dependencies] arbitrary = { version = "1.3.1" } -wasmtime-wmemcheck = { path = "crates/wmemcheck", version = "=28.0.0" } -wasmtime = { path = "crates/wasmtime", version = "28.0.0", default-features = false } -wasmtime-c-api-macros = { path = "crates/c-api-macros", version = "=28.0.0" } -wasmtime-cache = { path = "crates/cache", version = "=28.0.0" } -wasmtime-cli-flags = { path = "crates/cli-flags", version = "=28.0.0" } -wasmtime-cranelift = { path = "crates/cranelift", version = "=28.0.0" } -wasmtime-winch = { path = "crates/winch", version = "=28.0.0" } -wasmtime-environ = { path = "crates/environ", version = "=28.0.0" } -wasmtime-explorer = { path = "crates/explorer", version = "=28.0.0" } -wasmtime-fiber = { path = "crates/fiber", version = "=28.0.0" } -wasmtime-jit-debug = { path = "crates/jit-debug", version = "=28.0.0" } -wasmtime-wast = { path = "crates/wast", version = "=28.0.0" } -wasmtime-wasi = { path = "crates/wasi", version = "28.0.0", default-features = false } -wasmtime-wasi-http = { path = "crates/wasi-http", version = "=28.0.0", default-features = false } -wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "28.0.0" } -wasmtime-wasi-config = { path = "crates/wasi-config", version = "28.0.0" } -wasmtime-wasi-keyvalue = { path = "crates/wasi-keyvalue", version = "28.0.0" } -wasmtime-wasi-threads = { path = "crates/wasi-threads", version = "28.0.0" } -wasmtime-component-util = { path = "crates/component-util", version = "=28.0.0" } -wasmtime-component-macro = { path = "crates/component-macro", version = "=28.0.0" } -wasmtime-asm-macros = { path = "crates/asm-macros", version = "=28.0.0" } -wasmtime-versioned-export-macros = { path = "crates/versioned-export-macros", version = "=28.0.0" } -wasmtime-slab = { path = "crates/slab", version = "=28.0.0" } +wasmtime-wmemcheck = { path = "crates/wmemcheck", version = "=29.0.0" } +wasmtime = { path = "crates/wasmtime", version = "29.0.0", default-features = false } +wasmtime-c-api-macros = { path = "crates/c-api-macros", version = "=29.0.0" } +wasmtime-cache = { path = "crates/cache", version = "=29.0.0" } +wasmtime-cli-flags = { path = "crates/cli-flags", version = "=29.0.0" } +wasmtime-cranelift = { path = "crates/cranelift", version = "=29.0.0" } +wasmtime-winch = { path = "crates/winch", version = "=29.0.0" } +wasmtime-environ = { path = "crates/environ", version = "=29.0.0" } +wasmtime-explorer = { path = "crates/explorer", version = "=29.0.0" } +wasmtime-fiber = { path = "crates/fiber", version = "=29.0.0" } +wasmtime-jit-debug = { path = "crates/jit-debug", version = "=29.0.0" } +wasmtime-wast = { path = "crates/wast", version = "=29.0.0" } +wasmtime-wasi = { path = "crates/wasi", version = "29.0.0", default-features = false } +wasmtime-wasi-http = { path = "crates/wasi-http", version = "=29.0.0", default-features = false } +wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "29.0.0" } +wasmtime-wasi-config = { path = "crates/wasi-config", version = "29.0.0" } +wasmtime-wasi-keyvalue = { path = "crates/wasi-keyvalue", version = "29.0.0" } +wasmtime-wasi-threads = { path = "crates/wasi-threads", version = "29.0.0" } +wasmtime-component-util = { path = "crates/component-util", version = "=29.0.0" } +wasmtime-component-macro = { path = "crates/component-macro", version = "=29.0.0" } +wasmtime-asm-macros = { path = "crates/asm-macros", version = "=29.0.0" } +wasmtime-versioned-export-macros = { path = "crates/versioned-export-macros", version = "=29.0.0" } +wasmtime-slab = { path = "crates/slab", version = "=29.0.0" } component-test-util = { path = "crates/misc/component-test-util" } component-fuzz-util = { path = "crates/misc/component-fuzz-util" } -wiggle = { path = "crates/wiggle", version = "=28.0.0", default-features = false } -wiggle-macro = { path = "crates/wiggle/macro", version = "=28.0.0" } -wiggle-generate = { path = "crates/wiggle/generate", version = "=28.0.0" } -wasi-common = { path = "crates/wasi-common", version = "=28.0.0", default-features = false } +wiggle = { path = "crates/wiggle", version = "=29.0.0", default-features = false } +wiggle-macro = { path = "crates/wiggle/macro", version = "=29.0.0" } +wiggle-generate = { path = "crates/wiggle/generate", version = "=29.0.0" } +wasi-common = { path = "crates/wasi-common", version = "=29.0.0", default-features = false } wasmtime-fuzzing = { path = "crates/fuzzing" } -wasmtime-jit-icache-coherence = { path = "crates/jit-icache-coherence", version = "=28.0.0" } -wasmtime-wit-bindgen = { path = "crates/wit-bindgen", version = "=28.0.0" } +wasmtime-jit-icache-coherence = { path = "crates/jit-icache-coherence", version = "=29.0.0" } +wasmtime-wit-bindgen = { path = "crates/wit-bindgen", version = "=29.0.0" } test-programs-artifacts = { path = 'crates/test-programs/artifacts' } -pulley-interpreter = { path = 'pulley', version = "=28.0.0" } +pulley-interpreter = { path = 'pulley', version = "=29.0.0" } pulley-interpreter-fuzz = { path = 'pulley/fuzz' } -cranelift-codegen = { path = "cranelift/codegen", version = "0.115.0", default-features = false, features = ["std", "unwind"] } -cranelift-frontend = { path = "cranelift/frontend", version = "0.115.0" } -cranelift-entity = { path = "cranelift/entity", version = "0.115.0" } -cranelift-native = { path = "cranelift/native", version = "0.115.0" } -cranelift-module = { path = "cranelift/module", version = "0.115.0" } -cranelift-interpreter = { path = "cranelift/interpreter", version = "0.115.0" } -cranelift-reader = { path = "cranelift/reader", version = "0.115.0" } +cranelift-codegen = { path = "cranelift/codegen", version = "0.116.0", default-features = false, features = ["std", "unwind"] } +cranelift-frontend = { path = "cranelift/frontend", version = "0.116.0" } +cranelift-entity = { path = "cranelift/entity", version = "0.116.0" } +cranelift-native = { path = "cranelift/native", version = "0.116.0" } +cranelift-module = { path = "cranelift/module", version = "0.116.0" } +cranelift-interpreter = { path = "cranelift/interpreter", version = "0.116.0" } +cranelift-reader = { path = "cranelift/reader", version = "0.116.0" } cranelift-filetests = { path = "cranelift/filetests" } -cranelift-object = { path = "cranelift/object", version = "0.115.0" } -cranelift-jit = { path = "cranelift/jit", version = "0.115.0" } +cranelift-object = { path = "cranelift/object", version = "0.116.0" } +cranelift-jit = { path = "cranelift/jit", version = "0.116.0" } cranelift-fuzzgen = { path = "cranelift/fuzzgen" } -cranelift-bforest = { path = "cranelift/bforest", version = "0.115.0" } -cranelift-bitset = { path = "cranelift/bitset", version = "0.115.0" } -cranelift-control = { path = "cranelift/control", version = "0.115.0" } -cranelift = { path = "cranelift/umbrella", version = "0.115.0" } +cranelift-bforest = { path = "cranelift/bforest", version = "0.116.0" } +cranelift-bitset = { path = "cranelift/bitset", version = "0.116.0" } +cranelift-control = { path = "cranelift/control", version = "0.116.0" } +cranelift = { path = "cranelift/umbrella", version = "0.116.0" } -winch-codegen = { path = "winch/codegen", version = "=28.0.0" } +winch-codegen = { path = "winch/codegen", version = "=29.0.0" } wasi-preview1-component-adapter = { path = "crates/wasi-preview1-component-adapter" } byte-array-literals = { path = "crates/wasi-preview1-component-adapter/byte-array-literals" } diff --git a/RELEASES.md b/RELEASES.md index 868e9f306393..095959a5e42d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,4 +1,4 @@ -## 28.0.0 +## 29.0.0 Unreleased. @@ -12,6 +12,7 @@ Release notes for previous releases of Wasmtime can be found on the respective release branches of the Wasmtime repository. +* [28.0.x](https://github.com/bytecodealliance/wasmtime/blob/release-28.0.0/RELEASES.md) * [27.0.x](https://github.com/bytecodealliance/wasmtime/blob/release-27.0.0/RELEASES.md) * [26.0.x](https://github.com/bytecodealliance/wasmtime/blob/release-26.0.0/RELEASES.md) * [25.0.x](https://github.com/bytecodealliance/wasmtime/blob/release-25.0.0/RELEASES.md) diff --git a/cranelift/bforest/Cargo.toml b/cranelift/bforest/Cargo.toml index 55e3b6aef8c4..02f38e8a3ff8 100644 --- a/cranelift/bforest/Cargo.toml +++ b/cranelift/bforest/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-bforest" -version = "0.115.0" +version = "0.116.0" description = "A forest of B+-trees" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-bforest" diff --git a/cranelift/bitset/Cargo.toml b/cranelift/bitset/Cargo.toml index 4835ad8fbb4f..f9cd4521dd5f 100644 --- a/cranelift/bitset/Cargo.toml +++ b/cranelift/bitset/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-bitset" -version = "0.115.0" +version = "0.116.0" description = "Various bitset stuff for use inside Cranelift" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-bitset" diff --git a/cranelift/codegen/Cargo.toml b/cranelift/codegen/Cargo.toml index c8fa87090860..8c4a0a97f5b3 100644 --- a/cranelift/codegen/Cargo.toml +++ b/cranelift/codegen/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-codegen" -version = "0.115.0" +version = "0.116.0" description = "Low-level code generator library" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-codegen" @@ -24,7 +24,7 @@ features = ["all-arch"] anyhow = { workspace = true, optional = true, features = ['std'] } bumpalo = "3" capstone = { workspace = true, optional = true } -cranelift-codegen-shared = { path = "./shared", version = "0.115.0" } +cranelift-codegen-shared = { path = "./shared", version = "0.116.0" } cranelift-entity = { workspace = true } cranelift-bforest = { workspace = true } cranelift-bitset = { workspace = true } @@ -53,8 +53,8 @@ similar = "2.1.0" env_logger = { workspace = true } [build-dependencies] -cranelift-codegen-meta = { path = "meta", version = "0.115.0" } -cranelift-isle = { path = "../isle/isle", version = "=0.115.0" } +cranelift-codegen-meta = { path = "meta", version = "0.116.0" } +cranelift-isle = { path = "../isle/isle", version = "=0.116.0" } [features] default = ["std", "unwind", "host-arch", "timing"] diff --git a/cranelift/codegen/meta/Cargo.toml b/cranelift/codegen/meta/Cargo.toml index f89aef993796..52e3df080ff9 100644 --- a/cranelift/codegen/meta/Cargo.toml +++ b/cranelift/codegen/meta/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cranelift-codegen-meta" authors = ["The Cranelift Project Developers"] -version = "0.115.0" +version = "0.116.0" description = "Metaprogram for cranelift-codegen code generator library" license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasmtime" @@ -16,4 +16,4 @@ workspace = true rustdoc-args = [ "--document-private-items" ] [dependencies] -cranelift-codegen-shared = { path = "../shared", version = "0.115.0" } +cranelift-codegen-shared = { path = "../shared", version = "0.116.0" } diff --git a/cranelift/codegen/shared/Cargo.toml b/cranelift/codegen/shared/Cargo.toml index e2718a34a1db..8e8fde7efce8 100644 --- a/cranelift/codegen/shared/Cargo.toml +++ b/cranelift/codegen/shared/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-codegen-shared" -version = "0.115.0" +version = "0.116.0" description = "For code shared between cranelift-codegen-meta and cranelift-codegen" license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/control/Cargo.toml b/cranelift/control/Cargo.toml index 5b49a10733dc..10f44466b860 100644 --- a/cranelift/control/Cargo.toml +++ b/cranelift/control/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-control" -version = "0.115.0" +version = "0.116.0" description = "White-box fuzz testing framework" license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/entity/Cargo.toml b/cranelift/entity/Cargo.toml index 62625d33e128..3ea4fd842f81 100644 --- a/cranelift/entity/Cargo.toml +++ b/cranelift/entity/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-entity" -version = "0.115.0" +version = "0.116.0" description = "Data structures using entity references as mapping keys" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-entity" diff --git a/cranelift/frontend/Cargo.toml b/cranelift/frontend/Cargo.toml index 705465a795cd..88878c9ff153 100644 --- a/cranelift/frontend/Cargo.toml +++ b/cranelift/frontend/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-frontend" -version = "0.115.0" +version = "0.116.0" description = "Cranelift IR builder helper" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-frontend" diff --git a/cranelift/interpreter/Cargo.toml b/cranelift/interpreter/Cargo.toml index 35682924b644..96c2055011c6 100644 --- a/cranelift/interpreter/Cargo.toml +++ b/cranelift/interpreter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-interpreter" -version = "0.115.0" +version = "0.116.0" authors = ["The Cranelift Project Developers"] description = "Interpret Cranelift IR" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/isle/isle/Cargo.toml b/cranelift/isle/isle/Cargo.toml index 0f86584ed5f5..2707bffe8bee 100644 --- a/cranelift/isle/isle/Cargo.toml +++ b/cranelift/isle/isle/Cargo.toml @@ -7,7 +7,7 @@ license = "Apache-2.0 WITH LLVM-exception" name = "cranelift-isle" readme = "../README.md" repository = "https://github.com/bytecodealliance/wasmtime/tree/main/cranelift/isle" -version = "0.115.0" +version = "0.116.0" [lints] workspace = true diff --git a/cranelift/jit/Cargo.toml b/cranelift/jit/Cargo.toml index d07d33f2dbc2..201b478e745a 100644 --- a/cranelift/jit/Cargo.toml +++ b/cranelift/jit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-jit" -version = "0.115.0" +version = "0.116.0" authors = ["The Cranelift Project Developers"] description = "A JIT library backed by Cranelift" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/module/Cargo.toml b/cranelift/module/Cargo.toml index 999d878f9ae4..78e3391d8fa4 100644 --- a/cranelift/module/Cargo.toml +++ b/cranelift/module/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-module" -version = "0.115.0" +version = "0.116.0" authors = ["The Cranelift Project Developers"] description = "Support for linking functions and data with Cranelift" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/native/Cargo.toml b/cranelift/native/Cargo.toml index 9cdeab94e283..53b14b6fb625 100644 --- a/cranelift/native/Cargo.toml +++ b/cranelift/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-native" -version = "0.115.0" +version = "0.116.0" authors = ["The Cranelift Project Developers"] description = "Support for targeting the host with Cranelift" documentation = "https://docs.rs/cranelift-native" diff --git a/cranelift/object/Cargo.toml b/cranelift/object/Cargo.toml index e596d64b1f63..299ac3dde7a3 100644 --- a/cranelift/object/Cargo.toml +++ b/cranelift/object/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-object" -version = "0.115.0" +version = "0.116.0" authors = ["The Cranelift Project Developers"] description = "Emit Cranelift output to native object files with `object`" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/reader/Cargo.toml b/cranelift/reader/Cargo.toml index 62d568db1a2d..c19aad16b5a1 100644 --- a/cranelift/reader/Cargo.toml +++ b/cranelift/reader/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-reader" -version = "0.115.0" +version = "0.116.0" description = "Cranelift textual IR reader" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-reader" diff --git a/cranelift/serde/Cargo.toml b/cranelift/serde/Cargo.toml index 91df931730b1..753db4073bfc 100644 --- a/cranelift/serde/Cargo.toml +++ b/cranelift/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-serde" -version = "0.115.0" +version = "0.116.0" authors = ["The Cranelift Project Developers"] description = "Serializer/Deserializer for Cranelift IR" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/umbrella/Cargo.toml b/cranelift/umbrella/Cargo.toml index 1a941fe7af37..244bdfecaac9 100644 --- a/cranelift/umbrella/Cargo.toml +++ b/cranelift/umbrella/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift" -version = "0.115.0" +version = "0.116.0" description = "Umbrella for commonly-used cranelift crates" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift" diff --git a/crates/c-api/include/wasmtime.h b/crates/c-api/include/wasmtime.h index 25ca60024719..5cf6f3aa08e9 100644 --- a/crates/c-api/include/wasmtime.h +++ b/crates/c-api/include/wasmtime.h @@ -206,11 +206,11 @@ /** * \brief Wasmtime version string. */ -#define WASMTIME_VERSION "28.0.0" +#define WASMTIME_VERSION "29.0.0" /** * \brief Wasmtime major version number. */ -#define WASMTIME_VERSION_MAJOR 28 +#define WASMTIME_VERSION_MAJOR 29 /** * \brief Wasmtime minor version number. */ diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index df1c28beda17..d54501a21130 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -5,186 +5,370 @@ version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-bforest]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-bforest]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-bitset]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-bitset]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-codegen]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-codegen]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-codegen-meta]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-codegen-meta]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-codegen-shared]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-codegen-shared]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-control]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-control]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-entity]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-entity]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-frontend]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-frontend]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-interpreter]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-interpreter]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-isle]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-isle]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-jit]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-jit]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-module]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-module]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-native]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-native]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-object]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-object]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-reader]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-reader]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.cranelift-serde]] version = "0.115.0" audited_as = "0.113.1" +[[unpublished.cranelift-serde]] +version = "0.116.0" +audited_as = "0.114.0" + [[unpublished.pulley-interpreter]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.pulley-interpreter]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasi-common]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasi-common]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-asm-macros]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-asm-macros]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-cache]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-cache]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-cli]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-cli]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-cli-flags]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-cli-flags]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-component-macro]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-component-macro]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-component-util]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-component-util]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-cranelift]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-cranelift]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-environ]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-environ]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-explorer]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-explorer]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-fiber]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-fiber]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-jit-debug]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-jit-debug]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-jit-icache-coherence]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-jit-icache-coherence]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-slab]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-slab]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-wasi]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-wasi]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-wasi-config]] version = "28.0.0" audited_as = "27.0.0" +[[unpublished.wasmtime-wasi-config]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-wasi-http]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-wasi-http]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-wasi-keyvalue]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-wasi-keyvalue]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-wasi-nn]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-wasi-nn]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-wasi-threads]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-wasi-threads]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-wast]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-wast]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-winch]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-winch]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-wit-bindgen]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-wit-bindgen]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wasmtime-wmemcheck]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wasmtime-wmemcheck]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wiggle]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wiggle]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wiggle-generate]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wiggle-generate]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wiggle-macro]] version = "28.0.0" audited_as = "26.0.1" +[[unpublished.wiggle-macro]] +version = "29.0.0" +audited_as = "27.0.0" + [[unpublished.wiggle-test]] version = "0.0.0" audited_as = "0.1.0" @@ -193,6 +377,10 @@ audited_as = "0.1.0" version = "28.0.0" audited_as = "26.0.1" +[[unpublished.winch-codegen]] +version = "29.0.0" +audited_as = "27.0.0" + [[publisher.aho-corasick]] version = "1.0.2" when = "2023-06-04" @@ -376,104 +564,104 @@ user-login = "jrmuizel" user-name = "Jeff Muizelaar" [[publisher.cranelift]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-bforest]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-bitset]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-codegen]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-codegen-meta]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-codegen-shared]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-control]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-entity]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-frontend]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-interpreter]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-isle]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-jit]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-module]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-native]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-object]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-reader]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.cranelift-serde]] -version = "0.113.1" -when = "2024-11-05" +version = "0.114.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" @@ -667,8 +855,8 @@ user-login = "dtolnay" user-name = "David Tolnay" [[publisher.pulley-interpreter]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" @@ -896,8 +1084,8 @@ user-login = "BurntSushi" user-name = "Andrew Gallant" [[publisher.wasi-common]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" @@ -985,92 +1173,92 @@ user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-asm-macros]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-cache]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-cli]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-cli-flags]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-component-macro]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-component-util]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-cranelift]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-environ]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-explorer]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-fiber]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-jit-debug]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-jit-icache-coherence]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-slab]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-wasi]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" @@ -1081,50 +1269,50 @@ user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-wasi-http]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-wasi-keyvalue]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-wasi-nn]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-wasi-threads]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-wast]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-winch]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-wit-bindgen]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmtime-wmemcheck]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" @@ -1141,20 +1329,20 @@ user-id = 73222 user-login = "wasmtime-publish" [[publisher.wiggle]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wiggle-generate]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wiggle-macro]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish" @@ -1173,8 +1361,8 @@ user-login = "BurntSushi" user-name = "Andrew Gallant" [[publisher.winch-codegen]] -version = "26.0.1" -when = "2024-11-05" +version = "27.0.0" +when = "2024-11-20" user-id = 73222 user-login = "wasmtime-publish"