diff --git a/crates/c-api/include/wasmtime/trap.h b/crates/c-api/include/wasmtime/trap.h index 51c0d211470d..9f251363e7b2 100644 --- a/crates/c-api/include/wasmtime/trap.h +++ b/crates/c-api/include/wasmtime/trap.h @@ -47,12 +47,6 @@ enum wasmtime_trap_code_enum { WASMTIME_TRAP_CODE_UNREACHABLE_CODE_REACHED, /// Execution has potentially run too long and may be interrupted. WASMTIME_TRAP_CODE_INTERRUPT, - /// When the `component-model` feature is enabled this trap represents a - /// function that was `canon lift`'d, then `canon lower`'d, then called. - /// This combination of creation of a function in the component model - /// generates a function that always traps and, when called, produces this - /// flavor of trap. - WASMTIME_TRAP_CODE_ALWAYS_TRAP_ADAPTER, /// Execution has run out of the configured fuel amount. WASMTIME_TRAP_CODE_OUT_OF_FUEL, /// Used to indicate that a trap was raised by atomic wait operations on non @@ -74,9 +68,47 @@ enum wasmtime_trap_code_enum { /// Async-lifted export failed to produce a result by calling `task.return` /// before returning `STATUS_DONE` and/or after all host tasks completed. WASMTIME_TRAP_CODE_NO_ASYNC_RESULT, + /// We are suspending to a tag for which there is no active handler. + WASMTIME_TRAP_CODE_UNHANDLED_TAG, + /// Attempt to resume a continuation twice. + WASMTIME_TRAP_CODE_CONTINUATION_ALREADY_CONSUMED, /// A Pulley opcode was executed at runtime when the opcode was disabled at /// compile time. WASMTIME_TRAP_CODE_DISABLED_OPCODE, + /// Async event loop deadlocked; i.e. it cannot make further progress given + /// that all host tasks have completed and any/all host-owned stream/future + /// handles have been dropped. + WASMTIME_TRAP_CODE_ASYNC_DEADLOCK, + /// When the `component-model` feature is enabled this trap represents a + /// scenario where a component instance tried to call an import or intrinsic + /// when it wasn't allowed to, e.g. from a post-return function. + WASMTIME_TRAP_CODE_CANNOT_LEAVE_COMPONENT, + /// A synchronous task attempted to make a potentially blocking call prior + /// to returning. + WASMTIME_TRAP_CODE_CANNOT_BLOCK_SYNC_TASK, + /// A component tried to lift a `char` with an invalid bit pattern. + WASMTIME_TRAP_CODE_INVALID_CHAR, + /// Debug assertion generated for a fused adapter regarding the expected + /// completion of a string encoding operation. + WASMTIME_TRAP_CODE_DEBUG_ASSERT_STRING_ENCODING_FINISHED, + /// Debug assertion generated for a fused adapter regarding a string + /// encoding operation. + WASMTIME_TRAP_CODE_DEBUG_ASSERT_EQUAL_CODE_UNITS, + /// Debug assertion generated for a fused adapter regarding the alignment of + /// a pointer. + WASMTIME_TRAP_CODE_DEBUG_ASSERT_POINTER_ALIGNED, + /// Debug assertion generated for a fused adapter regarding the upper bits + /// of a 64-bit value. + WASMTIME_TRAP_CODE_DEBUG_ASSERT_UPPER_BITS_UNSET, + /// A component tried to lift or lower a string past the end of its memory. + WASMTIME_TRAP_CODE_STRING_OUT_OF_BOUNDS, + /// A component tried to lift or lower a list past the end of its memory. + WASMTIME_TRAP_CODE_LIST_OUT_OF_BOUNDS, + /// A component used an invalid discriminant when lowering a variant value. + WASMTIME_TRAP_CODE_INVALID_DISCRIMINANT, + /// A component passed an unaligned pointer when lifting or lowering a + /// value. + WASMTIME_TRAP_CODE_UNALIGNED_POINTER, }; /** diff --git a/crates/c-api/src/trap.rs b/crates/c-api/src/trap.rs index 9a8b6b7f864e..1eb3a1c508de 100644 --- a/crates/c-api/src/trap.rs +++ b/crates/c-api/src/trap.rs @@ -2,6 +2,46 @@ use crate::{wasm_frame_vec_t, wasm_instance_t, wasm_name_t, wasm_store_t}; use std::cell::OnceCell; use wasmtime::{Error, Trap, WasmBacktrace, format_err}; +// Help ensure the Rust enum matches the C one. If any of these assertions +// fail, please update both this code and `trap.h` to sync them with +// `trap_encoding.rs`. +const _: () = { + assert!(Trap::StackOverflow as u8 == 0); + assert!(Trap::MemoryOutOfBounds as u8 == 1); + assert!(Trap::HeapMisaligned as u8 == 2); + assert!(Trap::TableOutOfBounds as u8 == 3); + assert!(Trap::IndirectCallToNull as u8 == 4); + assert!(Trap::BadSignature as u8 == 5); + assert!(Trap::IntegerOverflow as u8 == 6); + assert!(Trap::IntegerDivisionByZero as u8 == 7); + assert!(Trap::BadConversionToInteger as u8 == 8); + assert!(Trap::UnreachableCodeReached as u8 == 9); + assert!(Trap::Interrupt as u8 == 10); + assert!(Trap::OutOfFuel as u8 == 11); + assert!(Trap::AtomicWaitNonSharedMemory as u8 == 12); + assert!(Trap::NullReference as u8 == 13); + assert!(Trap::ArrayOutOfBounds as u8 == 14); + assert!(Trap::AllocationTooLarge as u8 == 15); + assert!(Trap::CastFailure as u8 == 16); + assert!(Trap::CannotEnterComponent as u8 == 17); + assert!(Trap::NoAsyncResult as u8 == 18); + assert!(Trap::UnhandledTag as u8 == 19); + assert!(Trap::ContinuationAlreadyConsumed as u8 == 20); + assert!(Trap::DisabledOpcode as u8 == 21); + assert!(Trap::AsyncDeadlock as u8 == 22); + assert!(Trap::CannotLeaveComponent as u8 == 23); + assert!(Trap::CannotBlockSyncTask as u8 == 24); + assert!(Trap::InvalidChar as u8 == 25); + assert!(Trap::DebugAssertStringEncodingFinished as u8 == 26); + assert!(Trap::DebugAssertEqualCodeUnits as u8 == 27); + assert!(Trap::DebugAssertPointerAligned as u8 == 28); + assert!(Trap::DebugAssertUpperBitsUnset as u8 == 29); + assert!(Trap::StringOutOfBounds as u8 == 30); + assert!(Trap::ListOutOfBounds as u8 == 31); + assert!(Trap::InvalidDiscriminant as u8 == 32); + assert!(Trap::UnalignedPointer as u8 == 33); +}; + #[repr(C)] pub struct wasm_trap_t { pub(crate) error: Error, diff --git a/crates/c-api/tests/trap.cc b/crates/c-api/tests/trap.cc index ec059d792972..7b41e37190ae 100644 --- a/crates/c-api/tests/trap.cc +++ b/crates/c-api/tests/trap.cc @@ -60,7 +60,6 @@ TEST(Trap, Codes) { TEST_CODE(BAD_CONVERSION_TO_INTEGER); TEST_CODE(UNREACHABLE_CODE_REACHED); TEST_CODE(INTERRUPT); - TEST_CODE(ALWAYS_TRAP_ADAPTER); TEST_CODE(OUT_OF_FUEL); TEST_CODE(ATOMIC_WAIT_NON_SHARED_MEMORY); TEST_CODE(NULL_REFERENCE); diff --git a/crates/component-macro/tests/expanded/char_concurrent.rs b/crates/component-macro/tests/expanded/char_concurrent.rs index cd266fa9b8de..41963cad8457 100644 --- a/crates/component-macro/tests/expanded/char_concurrent.rs +++ b/crates/component-macro/tests/expanded/char_concurrent.rs @@ -191,12 +191,12 @@ pub mod foo { use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { /// A function that accepts a character - fn take_char( + fn take_char( accessor: &wasmtime::component::Accessor, x: char, ) -> impl ::core::future::Future + Send; /// A function that returns a character - fn return_char( + fn return_char( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/conventions_concurrent.rs b/crates/component-macro/tests/expanded/conventions_concurrent.rs index 73061589895e..a5678bed85d4 100644 --- a/crates/component-macro/tests/expanded/conventions_concurrent.rs +++ b/crates/component-macro/tests/expanded/conventions_concurrent.rs @@ -224,29 +224,29 @@ pub mod foo { ); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn kebab_case( + fn kebab_case( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, x: LudicrousSpeed, ) -> impl ::core::future::Future + Send; - fn function_with_dashes( + fn function_with_dashes( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn function_with_no_weird_characters( + fn function_with_no_weird_characters( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn apple( + fn apple( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn apple_pear( + fn apple_pear( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn apple_pear_grape( + fn apple_pear_grape( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn a0( + fn a0( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; /// Comment out identifiers that collide when mapped to snake_case, for now; see @@ -254,17 +254,17 @@ pub mod foo { /// APPLE: func() /// APPLE-pear-GRAPE: func() /// apple-PEAR-grape: func() - fn is_xml( + fn is_xml( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn explicit( + fn explicit( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn explicit_kebab( + fn explicit_kebab( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; /// Identifiers with the same name as keywords are quoted. - fn bool( + fn bool( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/dead-code_concurrent.rs b/crates/component-macro/tests/expanded/dead-code_concurrent.rs index a277b8c7dec2..b1277ba78c33 100644 --- a/crates/component-macro/tests/expanded/dead-code_concurrent.rs +++ b/crates/component-macro/tests/expanded/dead-code_concurrent.rs @@ -206,7 +206,7 @@ pub mod a { ); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn f( + fn f( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/direct-import_concurrent.rs b/crates/component-macro/tests/expanded/direct-import_concurrent.rs index 81606a4d8e92..b2da9df1ec20 100644 --- a/crates/component-macro/tests/expanded/direct-import_concurrent.rs +++ b/crates/component-macro/tests/expanded/direct-import_concurrent.rs @@ -99,7 +99,7 @@ pub struct FooIndices {} /// [`Linker`]: wasmtime::component::Linker pub struct Foo {} pub trait FooImportsWithStore: wasmtime::component::HasData + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/flags_concurrent.rs b/crates/component-macro/tests/expanded/flags_concurrent.rs index fa3e3b8906e4..6830b9702938 100644 --- a/crates/component-macro/tests/expanded/flags_concurrent.rs +++ b/crates/component-macro/tests/expanded/flags_concurrent.rs @@ -304,31 +304,31 @@ pub mod foo { assert!(4 == < Flag64 as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn roundtrip_flag1( + fn roundtrip_flag1( accessor: &wasmtime::component::Accessor, x: Flag1, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag2( + fn roundtrip_flag2( accessor: &wasmtime::component::Accessor, x: Flag2, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag4( + fn roundtrip_flag4( accessor: &wasmtime::component::Accessor, x: Flag4, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag8( + fn roundtrip_flag8( accessor: &wasmtime::component::Accessor, x: Flag8, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag16( + fn roundtrip_flag16( accessor: &wasmtime::component::Accessor, x: Flag16, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag32( + fn roundtrip_flag32( accessor: &wasmtime::component::Accessor, x: Flag32, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag64( + fn roundtrip_flag64( accessor: &wasmtime::component::Accessor, x: Flag64, ) -> impl ::core::future::Future + Send; diff --git a/crates/component-macro/tests/expanded/floats_concurrent.rs b/crates/component-macro/tests/expanded/floats_concurrent.rs index 14361bf3d49d..1d9a72f092fc 100644 --- a/crates/component-macro/tests/expanded/floats_concurrent.rs +++ b/crates/component-macro/tests/expanded/floats_concurrent.rs @@ -192,18 +192,18 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn f32_param( + fn f32_param( accessor: &wasmtime::component::Accessor, x: f32, ) -> impl ::core::future::Future + Send; - fn f64_param( + fn f64_param( accessor: &wasmtime::component::Accessor, x: f64, ) -> impl ::core::future::Future + Send; - fn f32_result( + fn f32_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn f64_result( + fn f64_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/host-world_concurrent.rs b/crates/component-macro/tests/expanded/host-world_concurrent.rs index a5e3b741ac25..8e49386e3c10 100644 --- a/crates/component-macro/tests/expanded/host-world_concurrent.rs +++ b/crates/component-macro/tests/expanded/host-world_concurrent.rs @@ -99,7 +99,7 @@ pub struct Host_Indices {} /// [`Linker`]: wasmtime::component::Linker pub struct Host_ {} pub trait Host_ImportsWithStore: wasmtime::component::HasData + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/integers_concurrent.rs b/crates/component-macro/tests/expanded/integers_concurrent.rs index aceff239d6bd..43959402cdb9 100644 --- a/crates/component-macro/tests/expanded/integers_concurrent.rs +++ b/crates/component-macro/tests/expanded/integers_concurrent.rs @@ -192,39 +192,39 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn a1( + fn a1( accessor: &wasmtime::component::Accessor, x: u8, ) -> impl ::core::future::Future + Send; - fn a2( + fn a2( accessor: &wasmtime::component::Accessor, x: i8, ) -> impl ::core::future::Future + Send; - fn a3( + fn a3( accessor: &wasmtime::component::Accessor, x: u16, ) -> impl ::core::future::Future + Send; - fn a4( + fn a4( accessor: &wasmtime::component::Accessor, x: i16, ) -> impl ::core::future::Future + Send; - fn a5( + fn a5( accessor: &wasmtime::component::Accessor, x: u32, ) -> impl ::core::future::Future + Send; - fn a6( + fn a6( accessor: &wasmtime::component::Accessor, x: i32, ) -> impl ::core::future::Future + Send; - fn a7( + fn a7( accessor: &wasmtime::component::Accessor, x: u64, ) -> impl ::core::future::Future + Send; - fn a8( + fn a8( accessor: &wasmtime::component::Accessor, x: i64, ) -> impl ::core::future::Future + Send; - fn a9( + fn a9( accessor: &wasmtime::component::Accessor, p1: u8, p2: i8, @@ -235,31 +235,31 @@ pub mod foo { p7: u64, p8: i64, ) -> impl ::core::future::Future + Send; - fn r1( + fn r1( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r2( + fn r2( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r3( + fn r3( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r4( + fn r4( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r5( + fn r5( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r6( + fn r6( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r7( + fn r7( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r8( + fn r8( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn pair_ret( + fn pair_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/lists_concurrent.rs b/crates/component-macro/tests/expanded/lists_concurrent.rs index 13a868eba225..1739476f6bc1 100644 --- a/crates/component-macro/tests/expanded/lists_concurrent.rs +++ b/crates/component-macro/tests/expanded/lists_concurrent.rs @@ -370,116 +370,116 @@ pub mod foo { ); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn list_u8_param( + fn list_u8_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_u16_param( + fn list_u16_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_u32_param( + fn list_u32_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_u64_param( + fn list_u64_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_s8_param( + fn list_s8_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_s16_param( + fn list_s16_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_s32_param( + fn list_s32_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_s64_param( + fn list_s64_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_f32_param( + fn list_f32_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_f64_param( + fn list_f64_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_u8_ret( + fn list_u8_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_u16_ret( + fn list_u16_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_u32_ret( + fn list_u32_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_u64_ret( + fn list_u64_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_s8_ret( + fn list_s8_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_s16_ret( + fn list_s16_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_s32_ret( + fn list_s32_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_s64_ret( + fn list_s64_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_f32_ret( + fn list_f32_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_f64_ret( + fn list_f64_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn tuple_list( + fn tuple_list( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec<(u8, i8)>, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec<(i64, u32)>, > + Send; - fn string_list_arg( + fn string_list_arg( accessor: &wasmtime::component::Accessor, a: wasmtime::component::__internal::Vec< wasmtime::component::__internal::String, >, ) -> impl ::core::future::Future + Send; - fn string_list_ret( + fn string_list_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec< wasmtime::component::__internal::String, >, > + Send; - fn tuple_string_list( + fn tuple_string_list( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec< (u8, wasmtime::component::__internal::String), @@ -489,7 +489,7 @@ pub mod foo { (wasmtime::component::__internal::String, u8), >, > + Send; - fn string_list( + fn string_list( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec< wasmtime::component::__internal::String, @@ -499,25 +499,25 @@ pub mod foo { wasmtime::component::__internal::String, >, > + Send; - fn record_list( + fn record_list( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn record_list_reverse( + fn record_list_reverse( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn variant_list( + fn variant_list( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn load_store_everything( + fn load_store_everything( accessor: &wasmtime::component::Accessor, a: LoadStoreAllSizes, ) -> impl ::core::future::Future + Send; diff --git a/crates/component-macro/tests/expanded/many-arguments_concurrent.rs b/crates/component-macro/tests/expanded/many-arguments_concurrent.rs index 32b4e7ab57e7..2eb2eab78860 100644 --- a/crates/component-macro/tests/expanded/many-arguments_concurrent.rs +++ b/crates/component-macro/tests/expanded/many-arguments_concurrent.rs @@ -273,7 +273,7 @@ pub mod foo { ); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn many_args( + fn many_args( accessor: &wasmtime::component::Accessor, a1: u64, a2: u64, @@ -292,7 +292,7 @@ pub mod foo { a15: u64, a16: u64, ) -> impl ::core::future::Future + Send; - fn big_argument( + fn big_argument( accessor: &wasmtime::component::Accessor, x: BigStruct, ) -> impl ::core::future::Future + Send; diff --git a/crates/component-macro/tests/expanded/multiversion_concurrent.rs b/crates/component-macro/tests/expanded/multiversion_concurrent.rs index 0153166b6af9..e7451285c055 100644 --- a/crates/component-macro/tests/expanded/multiversion_concurrent.rs +++ b/crates/component-macro/tests/expanded/multiversion_concurrent.rs @@ -201,7 +201,7 @@ pub mod my { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn x( + fn x( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -237,7 +237,7 @@ pub mod my { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn x( + fn x( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/records_concurrent.rs b/crates/component-macro/tests/expanded/records_concurrent.rs index 2c78b2450054..dd97f8e22d48 100644 --- a/crates/component-macro/tests/expanded/records_concurrent.rs +++ b/crates/component-macro/tests/expanded/records_concurrent.rs @@ -347,42 +347,42 @@ pub mod foo { ); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn tuple_arg( + fn tuple_arg( accessor: &wasmtime::component::Accessor, x: (char, u32), ) -> impl ::core::future::Future + Send; - fn tuple_result( + fn tuple_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn empty_arg( + fn empty_arg( accessor: &wasmtime::component::Accessor, x: Empty, ) -> impl ::core::future::Future + Send; - fn empty_result( + fn empty_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn scalar_arg( + fn scalar_arg( accessor: &wasmtime::component::Accessor, x: Scalars, ) -> impl ::core::future::Future + Send; - fn scalar_result( + fn scalar_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn flags_arg( + fn flags_arg( accessor: &wasmtime::component::Accessor, x: ReallyFlags, ) -> impl ::core::future::Future + Send; - fn flags_result( + fn flags_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn aggregate_arg( + fn aggregate_arg( accessor: &wasmtime::component::Accessor, x: Aggregates, ) -> impl ::core::future::Future + Send; - fn aggregate_result( + fn aggregate_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn typedef_inout( + fn typedef_inout( accessor: &wasmtime::component::Accessor, e: TupleTypedef2, ) -> impl ::core::future::Future + Send; diff --git a/crates/component-macro/tests/expanded/rename_concurrent.rs b/crates/component-macro/tests/expanded/rename_concurrent.rs index 5f036f6cddc9..45bea9853835 100644 --- a/crates/component-macro/tests/expanded/rename_concurrent.rs +++ b/crates/component-macro/tests/expanded/rename_concurrent.rs @@ -216,7 +216,7 @@ pub mod foo { assert!(4 == < Thing as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/resources-import_concurrent.rs b/crates/component-macro/tests/expanded/resources-import_concurrent.rs index ea6347bc068d..8b77ffc65b87 100644 --- a/crates/component-macro/tests/expanded/resources-import_concurrent.rs +++ b/crates/component-macro/tests/expanded/resources-import_concurrent.rs @@ -6,16 +6,16 @@ pub trait HostWorldResourceWithStore: wasmtime::component::HasData + Send { ) -> impl ::core::future::Future> + Send where Self: Sized; - fn new( + fn new( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::Resource, > + Send; - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, self_: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; - fn static_foo( + fn static_foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -128,7 +128,7 @@ pub struct TheWorld { some_world_func2: wasmtime::component::Func, } pub trait TheWorldImportsWithStore: wasmtime::component::HasData + HostWorldResourceWithStore + Send { - fn some_world_func( + fn some_world_func( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::Resource, @@ -391,15 +391,15 @@ pub mod foo { ) -> impl ::core::future::Future> + Send where Self: Sized; - fn new( + fn new( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::Resource, > + Send; - fn static_a( + fn static_a( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn method_a( + fn method_a( accessor: &wasmtime::component::Accessor, self_: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; @@ -469,7 +469,7 @@ pub mod foo { ) -> impl ::core::future::Future> + Send where Self: Sized; - fn new( + fn new( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result< @@ -481,89 +481,89 @@ pub mod foo { pub trait HostFallible: Send {} impl<_T: HostFallible + ?Sized + Send> HostFallible for &mut _T {} pub trait HostWithStore: wasmtime::component::HasData + HostBarWithStore + HostFallibleWithStore + Send { - fn bar_own_arg( + fn bar_own_arg( accessor: &wasmtime::component::Accessor, x: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; - fn bar_borrow_arg( + fn bar_borrow_arg( accessor: &wasmtime::component::Accessor, x: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; - fn bar_result( + fn bar_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::Resource, > + Send; - fn tuple_own_arg( + fn tuple_own_arg( accessor: &wasmtime::component::Accessor, x: (wasmtime::component::Resource, u32), ) -> impl ::core::future::Future + Send; - fn tuple_borrow_arg( + fn tuple_borrow_arg( accessor: &wasmtime::component::Accessor, x: (wasmtime::component::Resource, u32), ) -> impl ::core::future::Future + Send; - fn tuple_result( + fn tuple_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = (wasmtime::component::Resource, u32), > + Send; - fn option_own_arg( + fn option_own_arg( accessor: &wasmtime::component::Accessor, x: Option>, ) -> impl ::core::future::Future + Send; - fn option_borrow_arg( + fn option_borrow_arg( accessor: &wasmtime::component::Accessor, x: Option>, ) -> impl ::core::future::Future + Send; - fn option_result( + fn option_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Option>, > + Send; - fn result_own_arg( + fn result_own_arg( accessor: &wasmtime::component::Accessor, x: Result, ()>, ) -> impl ::core::future::Future + Send; - fn result_borrow_arg( + fn result_borrow_arg( accessor: &wasmtime::component::Accessor, x: Result, ()>, ) -> impl ::core::future::Future + Send; - fn result_result( + fn result_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result, ()>, > + Send; - fn list_own_arg( + fn list_own_arg( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec< wasmtime::component::Resource, >, ) -> impl ::core::future::Future + Send; - fn list_borrow_arg( + fn list_borrow_arg( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec< wasmtime::component::Resource, >, ) -> impl ::core::future::Future + Send; - fn list_result( + fn list_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec< wasmtime::component::Resource, >, > + Send; - fn record_own_arg( + fn record_own_arg( accessor: &wasmtime::component::Accessor, x: NestedOwn, ) -> impl ::core::future::Future + Send; - fn record_borrow_arg( + fn record_borrow_arg( accessor: &wasmtime::component::Accessor, x: NestedBorrow, ) -> impl ::core::future::Future + Send; - fn record_result( + fn record_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn func_with_handle_typedef( + fn func_with_handle_typedef( accessor: &wasmtime::component::Accessor, x: SomeHandle, ) -> impl ::core::future::Future + Send; @@ -1014,7 +1014,7 @@ pub mod foo { use wasmtime::component::__internal::Box; pub type A = super::super::super::foo::foo::long_use_chain3::A; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::Resource, diff --git a/crates/component-macro/tests/expanded/share-types_concurrent.rs b/crates/component-macro/tests/expanded/share-types_concurrent.rs index 8d2d4e406bbc..4966d78fb646 100644 --- a/crates/component-macro/tests/expanded/share-types_concurrent.rs +++ b/crates/component-macro/tests/expanded/share-types_concurrent.rs @@ -265,7 +265,7 @@ pub mod http_fetch { assert!(4 == < Response as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn fetch_request( + fn fetch_request( accessor: &wasmtime::component::Accessor, request: Request, ) -> impl ::core::future::Future + Send; diff --git a/crates/component-macro/tests/expanded/simple-functions_concurrent.rs b/crates/component-macro/tests/expanded/simple-functions_concurrent.rs index bab73ac4a359..f7b043e72162 100644 --- a/crates/component-macro/tests/expanded/simple-functions_concurrent.rs +++ b/crates/component-macro/tests/expanded/simple-functions_concurrent.rs @@ -192,25 +192,25 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn f1( + fn f1( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn f2( + fn f2( accessor: &wasmtime::component::Accessor, a: u32, ) -> impl ::core::future::Future + Send; - fn f3( + fn f3( accessor: &wasmtime::component::Accessor, a: u32, b: u32, ) -> impl ::core::future::Future + Send; - fn f4( + fn f4( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn f5( + fn f5( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn f6( + fn f6( accessor: &wasmtime::component::Accessor, a: u32, b: u32, diff --git a/crates/component-macro/tests/expanded/simple-lists_concurrent.rs b/crates/component-macro/tests/expanded/simple-lists_concurrent.rs index 8eaf44b90ce6..8e0c428b1dba 100644 --- a/crates/component-macro/tests/expanded/simple-lists_concurrent.rs +++ b/crates/component-macro/tests/expanded/simple-lists_concurrent.rs @@ -192,16 +192,16 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn simple_list1( + fn simple_list1( accessor: &wasmtime::component::Accessor, l: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn simple_list2( + fn simple_list2( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn simple_list3( + fn simple_list3( accessor: &wasmtime::component::Accessor, a: wasmtime::component::__internal::Vec, b: wasmtime::component::__internal::Vec, @@ -211,7 +211,7 @@ pub mod foo { wasmtime::component::__internal::Vec, ), > + Send; - fn simple_list4( + fn simple_list4( accessor: &wasmtime::component::Accessor, l: wasmtime::component::__internal::Vec< wasmtime::component::__internal::Vec, diff --git a/crates/component-macro/tests/expanded/simple-wasi_concurrent.rs b/crates/component-macro/tests/expanded/simple-wasi_concurrent.rs index 94cd4b0c7a28..629d6b81eb2d 100644 --- a/crates/component-macro/tests/expanded/simple-wasi_concurrent.rs +++ b/crates/component-macro/tests/expanded/simple-wasi_concurrent.rs @@ -246,10 +246,10 @@ pub mod foo { assert!(1 == < Errno as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn create_directory_at( + fn create_directory_at( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn stat( + fn stat( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result, diff --git a/crates/component-macro/tests/expanded/small-anonymous_concurrent.rs b/crates/component-macro/tests/expanded/small-anonymous_concurrent.rs index c33b98a1f5cc..10033c54a968 100644 --- a/crates/component-macro/tests/expanded/small-anonymous_concurrent.rs +++ b/crates/component-macro/tests/expanded/small-anonymous_concurrent.rs @@ -235,7 +235,7 @@ pub mod foo { assert!(1 == < Error as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn option_test( + fn option_test( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result< diff --git a/crates/component-macro/tests/expanded/smoke_concurrent.rs b/crates/component-macro/tests/expanded/smoke_concurrent.rs index db37d59b587a..2754c31736a4 100644 --- a/crates/component-macro/tests/expanded/smoke_concurrent.rs +++ b/crates/component-macro/tests/expanded/smoke_concurrent.rs @@ -179,7 +179,7 @@ pub mod imports { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn y( + fn y( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/strings_concurrent.rs b/crates/component-macro/tests/expanded/strings_concurrent.rs index 40ece95cc2c8..190835af96c7 100644 --- a/crates/component-macro/tests/expanded/strings_concurrent.rs +++ b/crates/component-macro/tests/expanded/strings_concurrent.rs @@ -192,16 +192,16 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn a( + fn a( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::String, ) -> impl ::core::future::Future + Send; - fn b( + fn b( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::String, > + Send; - fn c( + fn c( accessor: &wasmtime::component::Accessor, a: wasmtime::component::__internal::String, b: wasmtime::component::__internal::String, diff --git a/crates/component-macro/tests/expanded/unstable-features_concurrent.rs b/crates/component-macro/tests/expanded/unstable-features_concurrent.rs index 10fa5d11c89a..14157466b2a9 100644 --- a/crates/component-macro/tests/expanded/unstable-features_concurrent.rs +++ b/crates/component-macro/tests/expanded/unstable-features_concurrent.rs @@ -86,7 +86,7 @@ pub trait HostBazWithStore: wasmtime::component::HasData + Send { ) -> impl ::core::future::Future> + Send where Self: Sized; - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, self_: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; @@ -194,7 +194,7 @@ pub struct TheWorldIndices {} /// [`Linker`]: wasmtime::component::Linker pub struct TheWorld {} pub trait TheWorldImportsWithStore: wasmtime::component::HasData + HostBazWithStore + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -399,7 +399,7 @@ pub mod foo { ) -> impl ::core::future::Future> + Send where Self: Sized; - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, self_: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; @@ -407,7 +407,7 @@ pub mod foo { pub trait HostBar: Send {} impl<_T: HostBar + ?Sized + Send> HostBar for &mut _T {} pub trait HostWithStore: wasmtime::component::HasData + HostBarWithStore + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/unversioned-foo_concurrent.rs b/crates/component-macro/tests/expanded/unversioned-foo_concurrent.rs index 1ec481afba6b..c658c7b0dd81 100644 --- a/crates/component-macro/tests/expanded/unversioned-foo_concurrent.rs +++ b/crates/component-macro/tests/expanded/unversioned-foo_concurrent.rs @@ -209,7 +209,7 @@ pub mod foo { assert!(4 == < Error as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn g( + fn g( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; } diff --git a/crates/component-macro/tests/expanded/use-paths_concurrent.rs b/crates/component-macro/tests/expanded/use-paths_concurrent.rs index a275a676c154..0cc1d8b81346 100644 --- a/crates/component-macro/tests/expanded/use-paths_concurrent.rs +++ b/crates/component-macro/tests/expanded/use-paths_concurrent.rs @@ -203,7 +203,7 @@ pub mod foo { assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn a( + fn a( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -242,7 +242,7 @@ pub mod foo { assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn a( + fn a( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -281,7 +281,7 @@ pub mod foo { assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn a( + fn a( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -322,7 +322,7 @@ pub mod d { assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn b( + fn b( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/variants_concurrent.rs b/crates/component-macro/tests/expanded/variants_concurrent.rs index 25e0b0d62346..10c7ca604cf2 100644 --- a/crates/component-macro/tests/expanded/variants_concurrent.rs +++ b/crates/component-macro/tests/expanded/variants_concurrent.rs @@ -464,28 +464,28 @@ pub mod foo { assert!(4 == < IsClone as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn e1_arg( + fn e1_arg( accessor: &wasmtime::component::Accessor, x: E1, ) -> impl ::core::future::Future + Send; - fn e1_result( + fn e1_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn v1_arg( + fn v1_arg( accessor: &wasmtime::component::Accessor, x: V1, ) -> impl ::core::future::Future + Send; - fn v1_result( + fn v1_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn bool_arg( + fn bool_arg( accessor: &wasmtime::component::Accessor, x: bool, ) -> impl ::core::future::Future + Send; - fn bool_result( + fn bool_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn option_arg( + fn option_arg( accessor: &wasmtime::component::Accessor, a: Option, b: Option<()>, @@ -494,7 +494,7 @@ pub mod foo { e: Option, g: Option>, ) -> impl ::core::future::Future + Send; - fn option_result( + fn option_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = ( @@ -506,7 +506,7 @@ pub mod foo { Option>, ), > + Send; - fn casts( + fn casts( accessor: &wasmtime::component::Accessor, a: Casts1, b: Casts2, @@ -517,7 +517,7 @@ pub mod foo { ) -> impl ::core::future::Future< Output = (Casts1, Casts2, Casts3, Casts4, Casts5, Casts6), > + Send; - fn result_arg( + fn result_arg( accessor: &wasmtime::component::Accessor, a: Result<(), ()>, b: Result<(), E1>, @@ -529,7 +529,7 @@ pub mod foo { wasmtime::component::__internal::Vec, >, ) -> impl ::core::future::Future + Send; - fn result_result( + fn result_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = ( @@ -544,36 +544,36 @@ pub mod foo { >, ), > + Send; - fn return_result_sugar( + fn return_result_sugar( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn return_result_sugar2( + fn return_result_sugar2( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn return_result_sugar3( + fn return_result_sugar3( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result, > + Send; - fn return_result_sugar4( + fn return_result_sugar4( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result<(i32, u32), MyErrno>, > + Send; - fn return_option_sugar( + fn return_option_sugar( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn return_option_sugar2( + fn return_option_sugar2( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn result_simple( + fn result_simple( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn is_clone_arg( + fn is_clone_arg( accessor: &wasmtime::component::Accessor, a: IsClone, ) -> impl ::core::future::Future + Send; - fn is_clone_return( + fn is_clone_return( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/cranelift/src/compiler/component.rs b/crates/cranelift/src/compiler/component.rs index 2d7578c5af37..fc583c06827d 100644 --- a/crates/cranelift/src/compiler/component.rs +++ b/crates/cranelift/src/compiler/component.rs @@ -1,6 +1,6 @@ //! Compilation support for the component model. -use crate::{TRAP_ALWAYS, TRAP_CANNOT_ENTER, TRAP_INTERNAL_ASSERT, compiler::Compiler}; +use crate::{TRAP_INTERNAL_ASSERT, compiler::Compiler}; use cranelift_codegen::ir::condcodes::IntCC; use cranelift_codegen::ir::{self, InstBuilder, MemFlags, Value}; use cranelift_codegen::isa::{CallConv, TargetIsa}; @@ -20,7 +20,6 @@ struct TrampolineCompiler<'a> { offsets: VMComponentOffsets, block0: ir::Block, signature: &'a WasmFuncType, - tunables: &'a Tunables, } /// What host functions can be called, used in `translate_hostcall` below. @@ -100,7 +99,6 @@ impl<'a> TrampolineCompiler<'a> { component: &'a Component, types: &'a ComponentTypesBuilder, signature: &'a WasmFuncType, - tunables: &'a Tunables, ) -> TrampolineCompiler<'a> { let isa = &*compiler.isa; let func = ir::Function::with_name_signature( @@ -117,7 +115,6 @@ impl<'a> TrampolineCompiler<'a> { offsets: VMComponentOffsets::new(isa.pointer_bytes(), component), block0, signature, - tunables, } } @@ -160,21 +157,6 @@ impl<'a> TrampolineCompiler<'a> { }, ); } - Trampoline::AlwaysTrap => { - if self.tunables.signals_based_traps { - self.builder.ins().trap(TRAP_ALWAYS); - return; - } - self.translate_libcall( - host::trap, - TrapSentinel::Falsy, - WasmArgs::InRegisters, - |me, params| { - let code = wasmtime_environ::Trap::AlwaysTrapAdapter as u8; - params.push(me.builder.ins().iconst(ir::types::I32, i64::from(code))); - }, - ); - } Trampoline::ResourceNew { instance, ty } => { // Currently this only supports resources represented by `i32` assert_eq!(self.signature.params()[0], WasmValType::I32); @@ -1130,13 +1112,8 @@ impl<'a> TrampolineCompiler<'a> { // brif should_run_destructor, run_destructor_block, return_block // // run_destructor_block: - // ;; test may_enter, but only if the component instances - // ;; differ - // flags = load.i32 vmctx+$instance_flags_offset - // masked = band flags, $FLAG_MAY_ENTER - // trapz masked, CANNOT_ENTER_CODE - // - // ;; set may_block to false, saving the old value to restore later + // ;; set may_block to false, saving the old value to restore + // ;; later, but only if the component instances differ // old_may_block = load.i32 vmctx+$may_block_offset // store 0, vmctx+$may_block_offset // @@ -1184,25 +1161,13 @@ impl<'a> TrampolineCompiler<'a> { self.builder.switch_to_block(run_destructor_block); - // If this is a defined resource within the component itself then a - // check needs to be emitted for the `may_enter` flag. Note though - // that this check can be elided if the resource table resides in - // the same component instance that defined the resource as the - // component is calling itself. + // If this is a defined resource within the component itself then the + // `may_block` field must be updated. Note though that this update can + // be elided if the resource table resides in the same component + // instance that defined the resource as the component is calling + // itself. let old_may_block = if let Some(def) = resource_def { if self.types[resource].unwrap_concrete_instance() != def.instance { - let flags = self.builder.ins().load( - ir::types::I32, - trusted, - vmctx, - i32::try_from(self.offsets.instance_flags(def.instance)).unwrap(), - ); - let masked = self - .builder - .ins() - .band_imm(flags, i64::from(FLAG_MAY_ENTER)); - self.builder.ins().trapz(masked, TRAP_CANNOT_ENTER); - // Stash the old value of `may_block` and then set it to false. let old_may_block = self.builder.ins().load( ir::types::I32, @@ -1434,7 +1399,7 @@ impl ComponentCompiler for Compiler { types: &ComponentTypesBuilder, key: FuncKey, abi: Abi, - tunables: &Tunables, + _tunables: &Tunables, symbol: &str, ) -> Result { let (abi2, trampoline_index) = key.unwrap_component_trampoline(); @@ -1466,14 +1431,7 @@ impl ComponentCompiler for Compiler { } let mut compiler = self.function_compiler(); - let mut c = TrampolineCompiler::new( - self, - &mut compiler, - &component.component, - types, - sig, - tunables, - ); + let mut c = TrampolineCompiler::new(self, &mut compiler, &component.component, types, sig); // If we are crossing the Wasm-to-native boundary, we need to save the // exit FP and return address for stack walking purposes. However, we @@ -1512,7 +1470,7 @@ impl ComponentCompiler for Compiler { fn compile_intrinsic( &self, - tunables: &Tunables, + _tunables: &Tunables, component: &ComponentTranslation, types: &ComponentTypesBuilder, intrinsic: UnsafeIntrinsic, @@ -1557,7 +1515,6 @@ impl ComponentCompiler for Compiler { &component.component, &types, &wasm_func_ty, - tunables, ); match intrinsic { diff --git a/crates/cranelift/src/lib.rs b/crates/cranelift/src/lib.rs index b44e3cde445e..5ebcf2bcd158 100644 --- a/crates/cranelift/src/lib.rs +++ b/crates/cranelift/src/lib.rs @@ -48,10 +48,6 @@ use self::compiler::Compiler; const TRAP_INTERNAL_ASSERT: TrapCode = TrapCode::unwrap_user(1); const TRAP_OFFSET: u8 = 2; -pub const TRAP_ALWAYS: TrapCode = - TrapCode::unwrap_user(Trap::AlwaysTrapAdapter as u8 + TRAP_OFFSET); -pub const TRAP_CANNOT_ENTER: TrapCode = - TrapCode::unwrap_user(Trap::CannotEnterComponent as u8 + TRAP_OFFSET); pub const TRAP_INDIRECT_CALL_TO_NULL: TrapCode = TrapCode::unwrap_user(Trap::IndirectCallToNull as u8 + TRAP_OFFSET); pub const TRAP_BAD_SIGNATURE: TrapCode = diff --git a/crates/environ/src/component/dfg.rs b/crates/environ/src/component/dfg.rs index 5f5a3b84faed..1c7e9910744d 100644 --- a/crates/environ/src/component/dfg.rs +++ b/crates/environ/src/component/dfg.rs @@ -326,7 +326,6 @@ pub enum Trampoline { to: MemoryId, to64: bool, }, - AlwaysTrap, ResourceNew { instance: RuntimeComponentInstanceIndex, ty: TypeResourceTableIndex, @@ -945,7 +944,6 @@ impl LinearizeDfg<'_> { to: self.runtime_memory(*to), to64: *to64, }, - Trampoline::AlwaysTrap => info::Trampoline::AlwaysTrap, Trampoline::ResourceNew { instance, ty } => info::Trampoline::ResourceNew { instance: *instance, ty: *ty, diff --git a/crates/environ/src/component/info.rs b/crates/environ/src/component/info.rs index 65a12aebdb35..ea1cb94f7ea9 100644 --- a/crates/environ/src/component/info.rs +++ b/crates/environ/src/component/info.rs @@ -734,10 +734,6 @@ pub enum Trampoline { to64: bool, }, - /// A small adapter which simply traps, used for degenerate lift/lower - /// combinations. - AlwaysTrap, - /// A `resource.new` intrinsic which will inject a new resource into the /// table specified. ResourceNew { @@ -1199,7 +1195,6 @@ impl Trampoline { let to = if *to64 { "64" } else { "32" }; format!("component-transcode-{op}-m{from}-m{to}") } - AlwaysTrap => format!("component-always-trap"), ResourceNew { ty, .. } => format!("component-resource-new[{}]", ty.as_u32()), ResourceRep { ty, .. } => format!("component-resource-rep[{}]", ty.as_u32()), ResourceDrop { ty, .. } => format!("component-resource-drop[{}]", ty.as_u32()), diff --git a/crates/environ/src/component/translate/adapt.rs b/crates/environ/src/component/translate/adapt.rs index 2f66974a7a4c..d528099a2069 100644 --- a/crates/environ/src/component/translate/adapt.rs +++ b/crates/environ/src/component/translate/adapt.rs @@ -166,6 +166,9 @@ pub struct AdapterOptions { /// The Wasmtime-assigned component instance index where the options were /// originally specified. pub instance: RuntimeComponentInstanceIndex, + /// The ancestors (i.e. chain of instantiating instances) of the instance + /// specified in the `instance` field. + pub ancestors: Vec, /// How strings are encoded. pub string_encoding: StringEncoding, /// The async callback function used by these options, if specified. diff --git a/crates/environ/src/component/translate/inline.rs b/crates/environ/src/component/translate/inline.rs index afff24fc414d..b6004c62ce1b 100644 --- a/crates/environ/src/component/translate/inline.rs +++ b/crates/environ/src/component/translate/inline.rs @@ -386,7 +386,7 @@ impl<'a> Inliner<'a> { // Process the initializer and if it started the instantiation // of another component then we push that frame on the stack to // continue onwards. - Some(init) => match self.initializer(frame, types, init)? { + Some(init) => match self.initializer(frames, types, init)? { Some(new_frame) => { frames.push((new_frame, types.resources_mut().clone())); } @@ -422,12 +422,13 @@ impl<'a> Inliner<'a> { fn initializer( &mut self, - frame: &mut InlinerFrame<'a>, + frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>, types: &mut ComponentTypesBuilder, initializer: &'a LocalInitializer, ) -> Result>> { use LocalInitializer::*; + let (frame, _) = frames.last_mut().unwrap(); match initializer { // When a component imports an item the actual definition of the // item is looked up here (not at runtime) via its name. The @@ -512,7 +513,8 @@ impl<'a> Inliner<'a> { } => { let lower_ty = types.convert_component_func_type(frame.translation.types_ref(), *lower_ty)?; - let options_lower = self.adapter_options(frame, types, options); + let options_lower = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let lower_core_type = options_lower.core_type; let func = match &frame.component_funcs[*func] { // If this component function was originally a host import @@ -533,45 +535,8 @@ impl<'a> Inliner<'a> { dfg::CoreDef::Trampoline(index) } - // This case handles when a lifted function is later - // lowered, and both the lowering and the lifting are - // happening within the same component instance. - // - // In this situation if the `canon.lower`'d function is - // called then it immediately sets `may_enter` to `false`. - // When calling the callee, however, that's `canon.lift` - // which immediately traps if `may_enter` is `false`. That - // means that this pairing of functions creates a function - // that always traps. - // - // When closely reading the spec though the precise trap - // that comes out can be somewhat variable. Technically the - // function yielded here is one that should validate the - // arguments by lifting them, and then trap. This means that - // the trap could be different depending on whether all - // arguments are valid for now. This was discussed in - // WebAssembly/component-model#51 somewhat and the - // conclusion was that we can probably get away with "always - // trap" here. - // - // The `CoreDef::AlwaysTrap` variant here is used to - // indicate that this function is valid but if something - // actually calls it then it just generates a trap - // immediately. - ComponentFuncDef::Lifted { - options: options_lift, - .. - } if options_lift.instance == options_lower.instance => { - let index = self - .result - .trampolines - .push((lower_core_type, dfg::Trampoline::AlwaysTrap)); - dfg::CoreDef::Trampoline(index) - } - - // Lowering a lifted function where the destination - // component is different than the source component means - // that a "fused adapter" was just identified. + // Lowering a lifted functio means that a "fused adapter" + // was just identified. // // Metadata about this fused adapter is recorded in the // `Adapters` output of this compilation pass. Currently the @@ -624,7 +589,8 @@ impl<'a> Inliner<'a> { // plumbed through to exports or a fused adapter later on. Lift(ty, func, options) => { let ty = types.convert_component_func_type(frame.translation.types_ref(), *ty)?; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let func = frame.funcs[*func].1.clone(); frame .component_funcs @@ -724,7 +690,8 @@ impl<'a> Inliner<'a> { .collect::>()?; let results = types.new_tuple_type(results); let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -756,7 +723,8 @@ impl<'a> Inliner<'a> { } WaitableSetWait { options } => { let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -769,7 +737,8 @@ impl<'a> Inliner<'a> { } WaitableSetPoll { options } => { let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -849,7 +818,8 @@ impl<'a> Inliner<'a> { unreachable!() }; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -868,7 +838,8 @@ impl<'a> Inliner<'a> { unreachable!() }; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -964,7 +935,8 @@ impl<'a> Inliner<'a> { unreachable!() }; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -983,7 +955,8 @@ impl<'a> Inliner<'a> { unreachable!() }; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -1060,7 +1033,8 @@ impl<'a> Inliner<'a> { ErrorContextNew { options } => { let ty = types.error_context_table_type()?; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -1075,7 +1049,8 @@ impl<'a> Inliner<'a> { ErrorContextDebugMessage { options } => { let ty = types.error_context_table_type()?; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -1559,10 +1534,11 @@ impl<'a> Inliner<'a> { /// specified into a runtime representation. fn adapter_options( &mut self, - frame: &InlinerFrame<'a>, + frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>, types: &ComponentTypesBuilder, options: &LocalCanonicalOptions, ) -> AdapterOptions { + let (frame, _) = frames.last_mut().unwrap(); let data_model = match options.data_model { LocalDataModel::Gc {} => DataModel::Gc {}, LocalDataModel::LinearMemory { memory, realloc } => { @@ -1584,6 +1560,12 @@ impl<'a> Inliner<'a> { let post_return = options.post_return.map(|i| frame.funcs[i].1.clone()); AdapterOptions { instance: frame.instance, + ancestors: frames + .iter() + .rev() + .skip(1) + .map(|(frame, _)| frame.instance) + .collect(), string_encoding: options.string_encoding, callback, post_return, diff --git a/crates/environ/src/component/vmcomponent_offsets.rs b/crates/environ/src/component/vmcomponent_offsets.rs index 6743dbba2fa8..2fc76f7e03a5 100644 --- a/crates/environ/src/component/vmcomponent_offsets.rs +++ b/crates/environ/src/component/vmcomponent_offsets.rs @@ -29,10 +29,6 @@ pub const VMCOMPONENT_MAGIC: u32 = u32::from_le_bytes(*b"comp"); /// canonical ABI flag `may_leave` pub const FLAG_MAY_LEAVE: i32 = 1 << 0; -/// Flag for the `VMComponentContext::flags` field which corresponds to the -/// canonical ABI flag `may_enter` -pub const FLAG_MAY_ENTER: i32 = 1 << 1; - /// Flag for the `VMComponentContext::flags` field which is set whenever a /// function is called to indicate that `post_return` must be called next. pub const FLAG_NEEDS_POST_RETURN: i32 = 1 << 2; diff --git a/crates/environ/src/fact.rs b/crates/environ/src/fact.rs index 686c0ba96b56..77011665a017 100644 --- a/crates/environ/src/fact.rs +++ b/crates/environ/src/fact.rs @@ -114,9 +114,6 @@ struct AdapterData { /// The core wasm function that this adapter will be calling (the original /// function that was `canon lift`'d) callee: FuncIndex, - /// FIXME(#4185) should be plumbed and handled as part of the new reentrance - /// rules not yet implemented here. - called_as_export: bool, } /// Configuration options which apply at the "global adapter" level. @@ -124,7 +121,12 @@ struct AdapterData { /// These options are typically unique per-adapter and generally aren't needed /// when translating recursive types within an adapter. struct AdapterOptions { + /// The Wasmtime-assigned component instance index where the options were + /// originally specified. instance: RuntimeComponentInstanceIndex, + /// The ancestors (i.e. chain of instantiating instances) of the instance + /// specified in the `instance` field. + ancestors: Vec, /// The ascribed type of this adapter. ty: TypeFuncIndex, /// The global that represents the instance flags for where this adapter @@ -307,9 +309,6 @@ impl<'a> Module<'a> { lift, lower, callee, - // FIXME(#4185) should be plumbed and handled as part of the new - // reentrance rules not yet implemented here. - called_as_export: true, }, ); @@ -321,6 +320,7 @@ impl<'a> Module<'a> { fn import_options(&mut self, ty: TypeFuncIndex, options: &AdapterOptionsDfg) -> AdapterOptions { let AdapterOptionsDfg { instance, + ancestors, string_encoding, post_return: _, // handled above callback, @@ -399,6 +399,7 @@ impl<'a> Module<'a> { AdapterOptions { instance: *instance, + ancestors: ancestors.clone(), ty, flags, post_return: None, diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs index 2df0b1e6babb..d3bdecc42b8e 100644 --- a/crates/environ/src/fact/trampoline.rs +++ b/crates/environ/src/fact/trampoline.rs @@ -16,8 +16,8 @@ //! can be somewhat arbitrary, an intentional decision. use crate::component::{ - CanonicalAbiInfo, ComponentTypesBuilder, FLAG_MAY_ENTER, FLAG_MAY_LEAVE, FixedEncoding as FE, - FlatType, InterfaceType, MAX_FLAT_ASYNC_PARAMS, MAX_FLAT_PARAMS, PREPARE_ASYNC_NO_RESULT, + CanonicalAbiInfo, ComponentTypesBuilder, FLAG_MAY_LEAVE, FixedEncoding as FE, FlatType, + InterfaceType, MAX_FLAT_ASYNC_PARAMS, MAX_FLAT_PARAMS, PREPARE_ASYNC_NO_RESULT, PREPARE_ASYNC_WITH_RESULT, START_FLAG_ASYNC_CALLEE, StringEncoding, Transcode, TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, TypeFixedLengthListIndex, TypeFlagsIndex, TypeFutureTableIndex, TypeListIndex, TypeOptionIndex, TypeRecordIndex, @@ -114,6 +114,19 @@ pub(super) fn compile(module: &mut Module<'_>, adapter: &AdapterData) { ) } + // If the lift and lower instances are equal, or if one is an ancestor of + // the other, we trap unconditionally. This ensures that recursive + // reentrance via an adapter is impossible. + if adapter.lift.instance == adapter.lower.instance + || adapter.lower.ancestors.contains(&adapter.lift.instance) + || adapter.lift.ancestors.contains(&adapter.lower.instance) + { + let (mut compiler, _, _) = compiler(module, adapter); + compiler.trap(Trap::CannotEnterComponent); + compiler.finish(); + return; + } + // This closure compiles a function to be exported to the host which host to // lift the parameters from the caller and lower them to the callee. // @@ -739,20 +752,6 @@ impl<'a, 'b> Compiler<'a, 'b> { FLAG_MAY_LEAVE, Trap::CannotLeaveComponent, ); - if adapter.called_as_export { - self.trap_if_not_flag( - adapter.lift.flags, - FLAG_MAY_ENTER, - Trap::CannotEnterComponent, - ); - self.set_flag(adapter.lift.flags, FLAG_MAY_ENTER, false); - } else if self.module.debug { - self.assert_not_flag( - adapter.lift.flags, - FLAG_MAY_ENTER, - Trap::DebugAssertMayEnterUnset, - ); - } let task_may_block = self.module.import_task_may_block(); let old_task_may_block = if self.types[adapter.lift.ty].async_ { @@ -831,9 +830,6 @@ impl<'a, 'b> Compiler<'a, 'b> { } self.instruction(Call(func.as_u32())); } - if adapter.called_as_export { - self.set_flag(adapter.lift.flags, FLAG_MAY_ENTER, true); - } for tmp in temps { self.free_temp_local(tmp); @@ -3399,15 +3395,6 @@ impl<'a, 'b> Compiler<'a, 'b> { self.instruction(End); } - fn assert_not_flag(&mut self, flags_global: GlobalIndex, flag_to_test: i32, trap: Trap) { - self.instruction(GlobalGet(flags_global.as_u32())); - self.instruction(I32Const(flag_to_test)); - self.instruction(I32And); - self.instruction(If(BlockType::Empty)); - self.trap(trap); - self.instruction(End); - } - fn set_flag(&mut self, flags_global: GlobalIndex, flag_to_set: i32, value: bool) { self.instruction(GlobalGet(flags_global.as_u32())); if value { diff --git a/crates/environ/src/trap_encoding.rs b/crates/environ/src/trap_encoding.rs index 95bc95c70407..f9d22368eb85 100644 --- a/crates/environ/src/trap_encoding.rs +++ b/crates/environ/src/trap_encoding.rs @@ -16,7 +16,7 @@ pub struct TrapInformation { // The code can be accessed from the c-api, where the possible values are // translated into enum values defined there: // -// * `wasm_trap_code` in c-api/src/trap.rs, and +// * the const assertions in c-api/src/trap.rs, and // * `wasmtime_trap_code_enum` in c-api/include/wasmtime/trap.h. // // These need to be kept in sync. @@ -57,13 +57,6 @@ pub enum Trap { /// Execution has potentially run too long and may be interrupted. Interrupt, - /// When the `component-model` feature is enabled this trap represents a - /// function that was `canon lift`'d, then `canon lower`'d, then called. - /// This combination of creation of a function in the component model - /// generates a function that always traps and, when called, produces this - /// flavor of trap. - AlwaysTrapAdapter, - /// When wasm code is configured to consume fuel and it runs out of fuel /// then this trap will be raised. OutOfFuel, @@ -128,13 +121,6 @@ pub enum Trap { /// encoding operation. DebugAssertEqualCodeUnits, - /// Debug assertion generated for a fused adapter regarding the expected - /// value of the `may_enter` flag for an instance. - /// - /// TODO: Remove this once - /// https://github.com/bytecodealliance/wasmtime/pull/12153 has been merged. - DebugAssertMayEnterUnset, - /// Debug assertion generated for a fused adapter regarding the alignment of /// a pointer. DebugAssertPointerAligned, @@ -155,7 +141,8 @@ pub enum Trap { /// A component passed an unaligned pointer when lifting or lowering a /// value. UnalignedPointer, - // if adding a variant here be sure to update the `check!` macro below + // if adding a variant here be sure to update the `check!` macro below, and + // remember to update `trap.rs` and `trap.h` as mentioned above } impl Trap { @@ -183,7 +170,6 @@ impl Trap { BadConversionToInteger UnreachableCodeReached Interrupt - AlwaysTrapAdapter OutOfFuel AtomicWaitNonSharedMemory NullReference @@ -201,7 +187,6 @@ impl Trap { InvalidChar DebugAssertStringEncodingFinished DebugAssertEqualCodeUnits - DebugAssertMayEnterUnset DebugAssertPointerAligned DebugAssertUpperBitsUnset StringOutOfBounds @@ -230,7 +215,6 @@ impl fmt::Display for Trap { BadConversionToInteger => "invalid conversion to integer", UnreachableCodeReached => "wasm `unreachable` instruction executed", Interrupt => "interrupt", - AlwaysTrapAdapter => "degenerate component adapter called", OutOfFuel => "all fuel consumed by WebAssembly", AtomicWaitNonSharedMemory => "atomic wait on non-shared memory", NullReference => "null reference", @@ -248,7 +232,6 @@ impl fmt::Display for Trap { InvalidChar => "invalid `char` bit pattern", DebugAssertStringEncodingFinished => "should have finished string encoding", DebugAssertEqualCodeUnits => "code units should be equal", - DebugAssertMayEnterUnset => "`may_enter` flag should be unset", DebugAssertPointerAligned => "pointer should be aligned", DebugAssertUpperBitsUnset => "upper bits should be unset", StringOutOfBounds => "string content out-of-bounds", diff --git a/crates/misc/component-async-tests/src/round_trip.rs b/crates/misc/component-async-tests/src/round_trip.rs index d8894c5473d3..7308abfecee1 100644 --- a/crates/misc/component-async-tests/src/round_trip.rs +++ b/crates/misc/component-async-tests/src/round_trip.rs @@ -6,6 +6,7 @@ pub mod bindings { wasmtime::component::bindgen!({ path: "wit", world: "round-trip", + imports: { default: trappable }, }); } @@ -18,9 +19,9 @@ pub mod non_concurrent_export_bindings { } impl bindings::local::local::baz::HostWithStore for Ctx { - async fn foo(_: &Accessor, s: String) -> String { + async fn foo(_: &Accessor, s: String) -> wasmtime::Result { crate::util::sleep(Duration::from_millis(10)).await; - format!("{s} - entered host - exited host") + Ok(format!("{s} - entered host - exited host")) } } diff --git a/crates/misc/component-async-tests/tests/scenario/round_trip.rs b/crates/misc/component-async-tests/tests/scenario/round_trip.rs index b2a14c30f1ed..ac4d444de3ec 100644 --- a/crates/misc/component-async-tests/tests/scenario/round_trip.rs +++ b/crates/misc/component-async-tests/tests/scenario/round_trip.rs @@ -12,9 +12,11 @@ use futures::{ channel::oneshot, stream::{FuturesUnordered, TryStreamExt}, }; -use wasmtime::component::{Accessor, AccessorTask, HasSelf, Instance, Linker, ResourceTable, Val}; -use wasmtime::{Engine, Result, Store, format_err}; -use wasmtime_wasi::WasiCtxBuilder; +use wasmtime::component::{ + Accessor, AccessorTask, HasData, HasSelf, Instance, Linker, ResourceTable, Val, +}; +use wasmtime::{Engine, Result, Store, Trap, format_err}; +use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView}; #[tokio::test] pub async fn async_round_trip_stackful() -> Result<()> { @@ -203,6 +205,143 @@ pub async fn async_round_trip_stackless_sync_import() -> Result<()> { .await } +#[tokio::test] +pub async fn async_round_trip_stackless_recurse() -> Result<()> { + test_round_trip_recurse( + test_programs_artifacts::ASYNC_ROUND_TRIP_STACKLESS_COMPONENT, + false, + ) + .await +} + +#[tokio::test] +pub async fn async_round_trip_stackless_recurse_trap() -> Result<()> { + let error = test_round_trip_recurse( + test_programs_artifacts::ASYNC_ROUND_TRIP_STACKLESS_COMPONENT, + true, + ) + .await + .unwrap_err(); + + assert_eq!(error.downcast::()?, Trap::CannotEnterComponent); + + Ok(()) +} + +#[tokio::test] +pub async fn async_round_trip_synchronous_recurse() -> Result<()> { + test_round_trip_recurse( + test_programs_artifacts::ASYNC_ROUND_TRIP_SYNCHRONOUS_COMPONENT, + false, + ) + .await +} + +#[tokio::test] +pub async fn async_round_trip_synchronous_recurse_trap() -> Result<()> { + let error = test_round_trip_recurse( + test_programs_artifacts::ASYNC_ROUND_TRIP_SYNCHRONOUS_COMPONENT, + true, + ) + .await + .unwrap_err(); + + assert_eq!(error.downcast::()?, Trap::CannotEnterComponent); + + Ok(()) +} + +async fn test_round_trip_recurse(component: &str, same_instance: bool) -> Result<()> { + pub struct MyCtx { + wasi: WasiCtx, + table: ResourceTable, + instance: Option>, + } + + impl WasiView for MyCtx { + fn ctx(&mut self) -> WasiCtxView<'_> { + WasiCtxView { + ctx: &mut self.wasi, + table: &mut self.table, + } + } + } + + impl HasData for MyCtx { + type Data<'a> = &'a mut Self; + } + + impl component_async_tests::round_trip::bindings::local::local::baz::HostWithStore for MyCtx { + async fn foo(accessor: &Accessor, s: String) -> wasmtime::Result { + if let Some(instance) = accessor.with(|mut access| access.get().instance.take()) { + run(accessor, &instance).await?; + accessor.with(|mut access| access.get().instance = Some(instance)); + } + Ok(format!("{s} - entered host - exited host")) + } + } + + impl component_async_tests::round_trip::bindings::local::local::baz::Host for MyCtx {} + + async fn run(accessor: &Accessor, instance: &Instance) -> Result<()> { + let round_trip = accessor.with(|mut access| { + component_async_tests::round_trip::bindings::RoundTrip::new(&mut access, &instance) + })?; + + let input = "hello, world!"; + let expected = "hello, world! - entered guest - entered host - exited host - exited guest"; + + let actual = round_trip + .local_local_baz() + .call_foo(accessor, input.into()) + .await?; + + assert_eq!(expected, actual); + + Ok(()) + } + + let engine = Engine::new(&config())?; + + let mut linker = Linker::new(&engine); + + wasmtime_wasi::p2::add_to_linker_async(&mut linker)?; + component_async_tests::round_trip::bindings::local::local::baz::add_to_linker::<_, MyCtx>( + &mut linker, + |ctx| ctx, + )?; + + let component = make_component(&engine, &[component]).await?; + + let mut store = Store::new( + &engine, + MyCtx { + wasi: WasiCtxBuilder::new().inherit_stdio().build(), + table: ResourceTable::default(), + instance: None, + }, + ); + + let instance = Arc::new(linker.instantiate_async(&mut store, &component).await?); + store.data_mut().instance = Some(instance.clone()); + + let instance = if same_instance { + instance + } else { + Arc::new(linker.instantiate_async(&mut store, &component).await?) + }; + + store + .run_concurrent(async move |accessor| { + run(&accessor.with_getter(|ctx| ctx), &instance).await + }) + .await??; + + store.assert_concurrent_state_empty(); + + Ok(()) +} + pub async fn test_round_trip( components: &[&str], inputs_and_outputs: &[(&str, &str)], diff --git a/crates/wasmtime/src/runtime/component/concurrent.rs b/crates/wasmtime/src/runtime/component/concurrent.rs index 2ad06ef271da..e8198a4a38e8 100644 --- a/crates/wasmtime/src/runtime/component/concurrent.rs +++ b/crates/wasmtime/src/runtime/component/concurrent.rs @@ -51,15 +51,12 @@ //! in host functions. use crate::component::func::{self, Func}; -use crate::component::store::StoreComponentInstanceId; use crate::component::{ - ComponentInstanceId, HasData, HasSelf, Instance, Resource, ResourceTable, ResourceTableError, + HasData, HasSelf, Instance, Resource, ResourceTable, ResourceTableError, RuntimeInstance, }; use crate::fiber::{self, StoreFiber, StoreFiberYield}; use crate::store::{Store, StoreId, StoreInner, StoreOpaque, StoreToken}; -use crate::vm::component::{ - CallContext, ComponentInstance, HandleTable, InstanceFlags, ResourceTables, -}; +use crate::vm::component::{CallContext, ComponentInstance, HandleTable, ResourceTables}; use crate::vm::{AlwaysMut, SendSyncPtr, VMFuncRef, VMMemoryDefinition, VMStore}; use crate::{ AsContext, AsContextMut, FuncType, Result, StoreContext, StoreContextMut, ValRaw, ValType, @@ -444,7 +441,7 @@ where /// Run the specified closure, passing it mutable access to the store. /// /// This function is one of the main building blocks of the [`Accessor`] - /// type. This yields synchronous, blocking, access to store via an + /// type. This yields synchronous, blocking, access to the store via an /// [`Access`]. The [`Access`] implements [`AsContextMut`] in addition to /// providing the ability to access `D` via [`Access::get`]. Note that the /// `fun` here is given only temporary access to the store and `T`/`D` @@ -720,7 +717,7 @@ pub(crate) enum WaitResult { pub(crate) fn poll_and_block( store: &mut dyn VMStore, future: impl Future> + Send + 'static, - caller_instance: RuntimeComponentInstanceIndex, + caller_instance: RuntimeInstance, ) -> Result { let state = store.concurrent_state_mut(); @@ -852,7 +849,7 @@ fn handle_guest_call(store: &mut dyn VMStore, call: GuestCall) -> Result<()> { .take() .unwrap(); - let code = callback(store, runtime_instance.index, event, handle)?; + let code = callback(store, event, handle)?; store .concurrent_state_mut() @@ -1386,18 +1383,89 @@ impl StoreContextMut<'_, T> { } } -#[derive(Debug, Copy, Clone)] -pub struct RuntimeInstance { - pub instance: ComponentInstanceId, - pub index: RuntimeComponentInstanceIndex, -} - impl StoreOpaque { + /// Determine whether the specified instance may be entered from the host. + /// + /// We return `true` here only if all of the following hold: + /// + /// - The top-level instance is not already on the current task's call stack. + /// - The instance is not in need of a post-return function call. + /// - `self` has not been poisoned due to a trap. + pub(crate) fn may_enter(&mut self, instance: RuntimeInstance) -> bool { + let state = self.concurrent_state_mut(); + if let Some(caller) = state.guest_thread { + instance != state.get_mut(caller.task).unwrap().instance + && self.may_enter_from_caller(caller.task, instance) + } else { + self.may_enter_at_all(instance) + } + } + + fn may_enter_at_all(&self, instance: RuntimeInstance) -> bool { + if self.trapped() { + return false; + } + + let flags = self + .component_instance(instance.instance) + .instance_flags(instance.index); + + unsafe { !flags.needs_post_return() } + } + + /// Variation of `may_enter` which takes a `TableId` representing + /// the callee. + fn may_enter_task(&mut self, task: TableId) -> bool { + let instance = self.concurrent_state_mut().get_mut(task).unwrap().instance; + self.may_enter_from_caller(task, instance) + } + + /// Variation of `may_enter` which takes a `TableId` representing + /// the caller, plus a `RuntimeInstance` representing the callee. + fn may_enter_from_caller( + &mut self, + mut guest_task: TableId, + instance: RuntimeInstance, + ) -> bool { + self.may_enter_at_all(instance) && { + let state = self.concurrent_state_mut(); + let guest_instance = instance.instance; + loop { + // Note that we only compare top-level instance IDs here. The + // idea is that the host is not allowed to recursively enter a + // top-level instance even if the specific leaf instance is not + // on the stack. This the behavior defined in the spec, and it + // allows us to elide runtime checks in guest-to-guest adapters. + let next_thread = match &state.get_mut(guest_task).unwrap().caller { + Caller::Host { caller: None, .. } => break true, + &Caller::Host { + caller: Some(caller), + .. + } => { + let instance = state.get_mut(caller.task).unwrap().instance; + if instance.instance == guest_instance { + break false; + } else { + caller + } + } + &Caller::Guest { thread, instance } => { + if instance.instance == guest_instance { + break false; + } else { + thread + } + } + }; + guest_task = next_thread.task; + } + } + } + /// Helper function to retrieve the `ConcurrentInstanceState` for the /// specified instance. fn instance_state(&mut self, instance: RuntimeInstance) -> &mut ConcurrentInstanceState { - StoreComponentInstanceId::new(self.id(), instance.instance) - .get_mut(self) + self.component_instance_mut(instance.instance) .instance_state(instance.index) .concurrent_state() } @@ -1405,8 +1473,7 @@ impl StoreOpaque { /// Helper function to retrieve the `HandleTable` for the specified /// instance. fn handle_table(&mut self, instance: RuntimeInstance) -> &mut HandleTable { - StoreComponentInstanceId::new(self.id(), instance.instance) - .get_mut(self) + self.component_instance_mut(instance.instance) .instance_state(instance.index) .handle_table() } @@ -1420,8 +1487,7 @@ impl StoreOpaque { let old_thread = state.guest_thread.take(); if let Some(old_thread) = old_thread { let instance = state.get_mut(old_thread.task).unwrap().instance.instance; - StoreComponentInstanceId::new(self.id(), instance) - .get_mut(self) + self.component_instance_mut(instance) .set_task_may_block(false) } @@ -1443,8 +1509,7 @@ impl StoreOpaque { let guest_thread = state.guest_thread.unwrap(); let instance = state.get_mut(guest_thread.task).unwrap().instance.instance; let may_block = self.concurrent_state_mut().may_block(guest_thread.task); - StoreComponentInstanceId::new(self.id(), instance) - .get_mut(self) + self.component_instance_mut(instance) .set_task_may_block(may_block) } @@ -1452,9 +1517,7 @@ impl StoreOpaque { let state = self.concurrent_state_mut(); let task = state.guest_thread.unwrap().task; let instance = state.get_mut(task).unwrap().instance.instance; - let task_may_block = StoreComponentInstanceId::new(self.id(), instance) - .get_mut(self) - .get_task_may_block(); + let task_may_block = self.component_instance(instance).get_task_may_block(); if task_may_block { Ok(()) @@ -1894,7 +1957,6 @@ impl Instance { callee: SendSyncPtr, param_count: usize, result_count: usize, - flags: Option, async_: bool, callback: Option>, post_return: Option>, @@ -1919,7 +1981,6 @@ impl Instance { callee: SendSyncPtr, param_count: usize, result_count: usize, - flags: Option, ) -> impl FnOnce(&mut dyn VMStore) -> Result<[MaybeUninit; MAX_FLAT_PARAMS]> + Send + Sync @@ -1934,7 +1995,6 @@ impl Instance { .get_mut(guest_thread.thread)? .state = GuestThreadState::Running; let task = store.concurrent_state_mut().get_mut(guest_thread.task)?; - let may_enter_after_call = task.call_post_return_automatically(); let lower = task.lower_params.take().unwrap(); lower(store, &mut storage[..param_count])?; @@ -1944,9 +2004,6 @@ impl Instance { // SAFETY: Per the contract documented in `make_call's` // documentation, `callee` must be a valid pointer. unsafe { - if let Some(mut flags) = flags { - flags.set_may_enter(false); - } crate::Func::call_unchecked_raw( &mut store, callee.as_non_null(), @@ -1956,9 +2013,6 @@ impl Instance { ) .unwrap(), )?; - if let Some(mut flags) = flags { - flags.set_may_enter(may_enter_after_call); - } } Ok(storage) @@ -1975,7 +2029,6 @@ impl Instance { callee, param_count, result_count, - flags, ) }; @@ -2131,7 +2184,6 @@ impl Instance { unsafe { flags.set_may_leave(true); - flags.set_may_enter(true); } } @@ -2345,11 +2397,16 @@ impl Instance { }, Caller::Guest { thread: old_thread.unwrap(), - instance: caller_instance, + instance: RuntimeInstance { + instance: self.id().instance(), + index: caller_instance, + }, }, None, - self, - callee_instance, + RuntimeInstance { + instance: self.id().instance(), + index: callee_instance, + }, callee_async, )?; @@ -2360,10 +2417,6 @@ impl Instance { let state = store.0.concurrent_state_mut(); if let Some(old_thread) = old_thread { - if !state.may_enter(guest_task) { - bail!(crate::Trap::CannotEnterComponent); - } - state.get_mut(old_thread.task)?.subtasks.insert(guest_task); }; @@ -2387,14 +2440,10 @@ impl Instance { unsafe fn call_callback( self, mut store: StoreContextMut, - callee_instance: RuntimeComponentInstanceIndex, function: SendSyncPtr, event: Event, handle: u32, - may_enter_after_call: bool, ) -> Result { - let mut flags = self.id().get(store.0).instance_flags(callee_instance); - let (ordinal, result) = event.parts(); let params = &mut [ ValRaw::u32(ordinal), @@ -2406,13 +2455,11 @@ impl Instance { // `component::Options`. Per `wasmparser` callback signature // validation, we know it takes three parameters and returns one. unsafe { - flags.set_may_enter(false); crate::Func::call_unchecked_raw( &mut store, function.as_non_null(), params.as_mut_slice().into(), )?; - flags.set_may_enter(may_enter_after_call); } Ok(params[0].get_u32()) } @@ -2445,9 +2492,6 @@ impl Instance { let state = store.0.concurrent_state_mut(); let guest_thread = state.guest_thread.unwrap(); let callee_async = state.get_mut(guest_thread.task)?.async_function; - let may_enter_after_call = state - .get_mut(guest_thread.task)? - .call_post_return_automatically(); let callee = SendSyncPtr::new(NonNull::new(callee).unwrap()); let param_count = usize::try_from(param_count).unwrap(); assert!(param_count <= MAX_FLAT_PARAMS); @@ -2460,18 +2504,9 @@ impl Instance { // the callback and related context as part of the task so we can // call it later when needed. let callback = SendSyncPtr::new(NonNull::new(callback).unwrap()); - task.callback = Some(Box::new(move |store, runtime_instance, event, handle| { + task.callback = Some(Box::new(move |store, event, handle| { let store = token.as_context_mut(store); - unsafe { - self.call_callback::( - store, - runtime_instance, - callback, - event, - handle, - may_enter_after_call, - ) - } + unsafe { self.call_callback::(store, callback, event, handle) } })); } @@ -2487,14 +2522,6 @@ impl Instance { let caller = *caller; let caller_instance = *runtime_instance; - let callee_instance = task.instance; - - let instance_flags = if callback.is_null() { - None - } else { - Some(self.id().get(store.0).instance_flags(callee_instance.index)) - }; - // Queue the call as a "high priority" work item. unsafe { self.queue_call( @@ -2503,7 +2530,6 @@ impl Instance { callee, param_count, result_count, - instance_flags, (flags & START_FLAG_ASYNC_CALLEE) != 0, NonNull::new(callback).map(SendSyncPtr::new), NonNull::new(post_return).map(SendSyncPtr::new), @@ -2567,10 +2593,7 @@ impl Instance { // waitable and return the status. let handle = store .0 - .handle_table(RuntimeInstance { - instance: self.id().instance(), - index: caller_instance, - }) + .handle_table(caller_instance) .subtask_insert_guest(guest_thread.task.rep())?; store .0 @@ -2679,7 +2702,13 @@ impl Instance { // We create a new host task even though it might complete immediately // (in which case we won't need to pass a waitable back to the guest). // If it does complete immediately, we'll remove it before we return. - let task = state.push(HostTask::new(caller_instance, Some(join_handle)))?; + let task = state.push(HostTask::new( + RuntimeInstance { + instance: self.id().instance(), + index: caller_instance, + }, + Some(join_handle), + ))?; log::trace!("new host task child of {caller:?}: {task:?}"); @@ -3034,7 +3063,13 @@ impl Instance { // Since waitables can neither be passed between instances nor forged, // this should never fail unless there's a bug in Wasmtime, but we check // here to be sure: - assert_eq!(expected_caller_instance, caller_instance); + assert_eq!( + expected_caller_instance, + RuntimeInstance { + instance: self.id().instance(), + index: caller_instance + } + ); log::trace!("subtask_drop {waitable:?} (handle {task_id})"); Ok(()) } @@ -3462,7 +3497,13 @@ impl Instance { // Since waitables can neither be passed between instances nor forged, // this should never fail unless there's a bug in Wasmtime, but we check // here to be sure: - assert_eq!(expected_caller_instance, caller_instance); + assert_eq!( + expected_caller_instance, + RuntimeInstance { + instance: self.id().instance(), + index: caller_instance + } + ); log::trace!("subtask_cancel {waitable:?} (handle {task_id})"); @@ -4091,15 +4132,12 @@ type HostTaskFuture = Pin> + Send + 'static>> /// Represents the state of a pending host task. struct HostTask { common: WaitableCommon, - caller_instance: RuntimeComponentInstanceIndex, + caller_instance: RuntimeInstance, join_handle: Option, } impl HostTask { - fn new( - caller_instance: RuntimeComponentInstanceIndex, - join_handle: Option, - ) -> Self { + fn new(caller_instance: RuntimeInstance, join_handle: Option) -> Self { Self { common: WaitableCommon::default(), caller_instance, @@ -4114,12 +4152,7 @@ impl TableDebug for HostTask { } } -type CallbackFn = Box< - dyn Fn(&mut dyn VMStore, RuntimeComponentInstanceIndex, Event, u32) -> Result - + Send - + Sync - + 'static, ->; +type CallbackFn = Box Result + Send + Sync + 'static>; /// Represents the caller of a given guest task. enum Caller { @@ -4139,6 +4172,11 @@ enum Caller { host_future_present: bool, /// If true, call `post-return` function (if any) automatically. call_post_return_automatically: bool, + /// If `Some`, represents the `QualifiedThreadId` caller of the host + /// function which called back into a guest. Note that this thread + /// could belong to an entirely unrelated top-level component instance + /// than the one the host called into. + caller: Option, }, /// Another guest thread called the guest task Guest { @@ -4149,7 +4187,7 @@ enum Caller { /// Note that this might not be the same as the instance the caller task /// started executing in given that one or more synchronous guest->guest /// calls may have occurred involving multiple instances. - instance: RuntimeComponentInstanceIndex, + instance: RuntimeInstance, }, } @@ -4389,8 +4427,7 @@ impl GuestTask { lift_result: LiftResult, caller: Caller, callback: Option, - component_instance: Instance, - instance: RuntimeComponentInstanceIndex, + instance: RuntimeInstance, async_function: bool, ) -> Result { let sync_call_set = state.push(WaitableSet::default())?; @@ -4420,10 +4457,7 @@ impl GuestTask { starting_sent: false, subtasks: HashSet::new(), sync_call_set, - instance: RuntimeInstance { - instance: component_instance.id().instance(), - index: instance, - }, + instance, event: None, function_index: None, exited: false, @@ -4472,7 +4506,9 @@ impl GuestTask { }; } } - Caller::Host { exit_tx, .. } => { + Caller::Host { + exit_tx, caller, .. + } => { for subtask in &self.subtasks { state.get_mut(*subtask)?.caller = Caller::Host { tx: None, @@ -4482,6 +4518,7 @@ impl GuestTask { exit_tx: exit_tx.clone(), host_future_present: false, call_post_return_automatically: true, + caller: *caller, }; } } @@ -4925,40 +4962,6 @@ impl ConcurrentState { } } - /// Determine whether the instance associated with the specified guest task - /// may be entered (i.e. is not already on the async call stack). - /// - /// This is an additional check on top of the "may_enter" instance flag; - /// it's needed because async-lifted exports with callback functions must - /// not call their own instances directly or indirectly, and due to the - /// "stackless" nature of callback-enabled guest tasks this may happen even - /// if there are no activation records on the stack (i.e. the "may_enter" - /// field is `true`) for that instance. - fn may_enter(&mut self, mut guest_task: TableId) -> bool { - let guest_instance = self.get_mut(guest_task).unwrap().instance; - - // Walk the task tree back to the root, looking for potential - // reentrance. - // - // TODO: This could be optimized by maintaining a per-`GuestTask` bitset - // such that each bit represents and instance which has been entered by - // that task or an ancestor of that task, in which case this would be a - // constant time check. - loop { - let next_thread = match &self.get_mut(guest_task).unwrap().caller { - Caller::Host { .. } => break true, - Caller::Guest { thread, instance } => { - if *instance == guest_instance.index { - break false; - } else { - *thread - } - } - }; - guest_task = next_thread.task; - } - } - /// Implements the `context.get` intrinsic. pub(crate) fn context_get(&mut self, slot: u32) -> Result { let thread = self.guest_thread.unwrap(); @@ -5174,6 +5177,7 @@ pub(crate) fn prepare_call( let (tx, rx) = oneshot::channel(); let (exit_tx, exit_rx) = oneshot::channel(); + let caller = state.guest_thread; let mut task = GuestTask::new( state, Box::new(for_any_lower(move |store, params| { @@ -5192,30 +5196,22 @@ pub(crate) fn prepare_call( exit_tx: Arc::new(exit_tx), host_future_present, call_post_return_automatically, + caller, }, callback.map(|callback| { let callback = SendSyncPtr::new(callback); let instance = handle.instance(); - Box::new( - move |store: &mut dyn VMStore, runtime_instance, event, handle| { - let store = token.as_context_mut(store); - // SAFETY: Per the contract of `prepare_call`, the callback - // will remain valid at least as long is this task exists. - unsafe { - instance.call_callback( - store, - runtime_instance, - callback, - event, - handle, - call_post_return_automatically, - ) - } - }, - ) as CallbackFn + Box::new(move |store: &mut dyn VMStore, event, handle| { + let store = token.as_context_mut(store); + // SAFETY: Per the contract of `prepare_call`, the callback + // will remain valid at least as long is this task exists. + unsafe { instance.call_callback(store, callback, event, handle) } + }) as CallbackFn }), - handle.instance(), - component_instance, + RuntimeInstance { + instance: handle.instance().id().instance(), + index: component_instance, + }, async_function, )?; task.function_index = Some(handle.index()); @@ -5224,6 +5220,10 @@ pub(crate) fn prepare_call( let thread = state.push(GuestThread::new_implicit(task))?; state.get_mut(task)?.threads.insert(thread); + if !store.0.may_enter_task(task) { + bail!(crate::Trap::CannotEnterComponent); + } + Ok(PreparedCall { handle, thread: QualifiedThreadId { task, thread }, @@ -5273,7 +5273,7 @@ fn queue_call0( guest_thread: QualifiedThreadId, param_count: usize, ) -> Result<()> { - let (_options, flags, _ty, raw_options) = handle.abi_info(store.0); + let (_options, _, _ty, raw_options) = handle.abi_info(store.0); let is_concurrent = raw_options.async_; let callback = raw_options.callback; let instance = handle.instance(); @@ -5286,12 +5286,6 @@ fn queue_call0( log::trace!("queueing call {guest_thread:?}"); - let instance_flags = if callback.is_none() { - None - } else { - Some(flags) - }; - // SAFETY: `callee`, `callback`, and `post_return` are valid pointers // (with signatures appropriate for this call) and will remain valid as // long as this instance is valid. @@ -5302,7 +5296,6 @@ fn queue_call0( SendSyncPtr::new(callee), param_count, 1, - instance_flags, is_concurrent, callback, post_return.map(SendSyncPtr::new), diff --git a/crates/wasmtime/src/runtime/component/concurrent_disabled.rs b/crates/wasmtime/src/runtime/component/concurrent_disabled.rs index 2843cd5b2ff6..0437c1f540d7 100644 --- a/crates/wasmtime/src/runtime/component/concurrent_disabled.rs +++ b/crates/wasmtime/src/runtime/component/concurrent_disabled.rs @@ -1,6 +1,6 @@ use crate::component::func::{LiftContext, LowerContext}; use crate::component::matching::InstanceType; -use crate::component::{ComponentType, Lift, Lower, Val}; +use crate::component::{ComponentType, Lift, Lower, RuntimeInstance, Val}; use crate::store::StoreOpaque; use crate::{Result, bail, error::format_err}; use core::convert::Infallible; @@ -155,4 +155,16 @@ impl StoreOpaque { pub(crate) fn check_blocking(&mut self) -> Result<()> { Ok(()) } + + pub(crate) fn may_enter(&mut self, instance: RuntimeInstance) -> bool { + if self.trapped() { + return false; + } + + let flags = self + .component_instance(instance.instance) + .instance_flags(instance.index); + + unsafe { !flags.needs_post_return() } + } } diff --git a/crates/wasmtime/src/runtime/component/func.rs b/crates/wasmtime/src/runtime/component/func.rs index 2abb0b4b8b43..0cbbff714f2f 100644 --- a/crates/wasmtime/src/runtime/component/func.rs +++ b/crates/wasmtime/src/runtime/component/func.rs @@ -1,3 +1,4 @@ +use crate::component::RuntimeInstance; use crate::component::instance::Instance; use crate::component::matching::InstanceType; use crate::component::storage::storage_as_slice; @@ -614,6 +615,15 @@ impl Func { LowerReturn: Copy, { let export = self.lifted_core_func(store.0); + let (_options, _flags, _ty, raw_options) = self.abi_info(store.0); + let instance = RuntimeInstance { + instance: self.instance.id().instance(), + index: raw_options.instance, + }; + + if !store.0.may_enter(instance) { + bail!(crate::Trap::CannotEnterComponent); + } #[repr(C)] union Union { @@ -788,9 +798,6 @@ impl Func { ); let post_return_arg = post_return_arg.expect("calling post_return on wrong function"); - // This is a sanity-check assert which shouldn't ever trip. - assert!(!flags.may_enter()); - // Unset the "needs post return" flag now that post-return is being // processed. This will cause future invocations of this method to // panic, even if the function call below traps. @@ -802,10 +809,6 @@ impl Func { // If the function actually had a `post-return` configured in its // canonical options that's executed here. - // - // Note that if this traps (returns an error) this function - // intentionally leaves the instance in a "poisoned" state where it - // can no longer be entered because `may_enter` is `false`. if let Some(func) = post_return { crate::Func::call_unchecked_raw( &mut store, @@ -816,9 +819,8 @@ impl Func { } // And finally if everything completed successfully then the "may - // enter" and "may leave" flags are set to `true` again here which - // enables further use of the component. - flags.set_may_enter(true); + // leave" flags is set to `true` again here which enables further + // use of the component. flags.set_may_leave(true); let (calls, host_table, _, instance) = store @@ -943,26 +945,12 @@ impl Func { fn with_lower_context( self, mut store: StoreContextMut, - may_enter: bool, + call_post_return_automatically: bool, lower: impl FnOnce(&mut LowerContext, InterfaceType) -> Result<()>, ) -> Result<()> { let (options_idx, mut flags, ty, options) = self.abi_info(store.0); let async_ = options.async_; - // Test the "may enter" flag which is a "lock" on this instance. - // This is immediately set to `false` afterwards and note that - // there's no on-cleanup setting this flag back to true. That's an - // intentional design aspect where if anything goes wrong internally - // from this point on the instance is considered "poisoned" and can - // never be entered again. The only time this flag is set to `true` - // again is after post-return logic has completed successfully. - unsafe { - if !flags.may_enter() { - bail!(crate::Trap::CannotEnterComponent); - } - flags.set_may_enter(false); - } - // Perform the actual lowering, where while this is running the // component is forbidden from calling imports. unsafe { @@ -975,14 +963,10 @@ impl Func { unsafe { flags.set_may_leave(true) }; result?; - // If this is an async function and `may_enter == true` then we're - // allowed to reenter the component at this point, and otherwise flag a - // post-return call being required as we're about to enter wasm and - // afterwards need a post-return. + // If needed, flag a post-return call being required as we're about to + // enter wasm and afterwards need a post-return. unsafe { - if may_enter && async_ { - flags.set_may_enter(true); - } else { + if !(call_post_return_automatically && async_) { flags.set_needs_post_return(true); } } diff --git a/crates/wasmtime/src/runtime/component/func/host.rs b/crates/wasmtime/src/runtime/component/func/host.rs index 9c27afef8b31..29de0616532f 100644 --- a/crates/wasmtime/src/runtime/component/func/host.rs +++ b/crates/wasmtime/src/runtime/component/func/host.rs @@ -1,5 +1,7 @@ //! Implementation of calling Rust-defined functions from components. +#[cfg(feature = "component-model-async")] +use crate::component::RuntimeInstance; #[cfg(feature = "component-model-async")] use crate::component::concurrent; #[cfg(feature = "component-model-async")] @@ -339,9 +341,14 @@ where let ret = match self.run(store.as_context_mut(), params) { HostResult::Done(result) => result?, #[cfg(feature = "component-model-async")] - HostResult::Future(future) => { - concurrent::poll_and_block(store.0, future, caller_instance)? - } + HostResult::Future(future) => concurrent::poll_and_block( + store.0, + future, + RuntimeInstance { + instance: instance.id().instance(), + index: caller_instance, + }, + )?, }; let mut lower = LowerContext::new(store, options, instance); diff --git a/crates/wasmtime/src/runtime/component/func/options.rs b/crates/wasmtime/src/runtime/component/func/options.rs index 02a04df69ac0..55df5005cce7 100644 --- a/crates/wasmtime/src/runtime/component/func/options.rs +++ b/crates/wasmtime/src/runtime/component/func/options.rs @@ -2,12 +2,10 @@ use crate::StoreContextMut; use crate::component::concurrent::ConcurrentState; use crate::component::matching::InstanceType; use crate::component::resources::{HostResourceData, HostResourceIndex, HostResourceTables}; -use crate::component::{Instance, ResourceType}; +use crate::component::{Instance, ResourceType, RuntimeInstance}; use crate::prelude::*; use crate::runtime::vm::VMFuncRef; -use crate::runtime::vm::component::{ - CallContexts, ComponentInstance, HandleTable, InstanceFlags, ResourceTables, -}; +use crate::runtime::vm::component::{CallContexts, ComponentInstance, HandleTable, ResourceTables}; use crate::store::{StoreId, StoreOpaque}; use alloc::sync::Arc; use core::pin::Pin; @@ -260,10 +258,10 @@ impl<'a, T: 'static> LowerContext<'a, T> { &mut self, rep: u32, dtor: Option>, - flags: Option, + instance: Option, ) -> Result { self.resource_tables() - .host_resource_lower_own(rep, dtor, flags) + .host_resource_lower_own(rep, dtor, instance) } /// Returns the underlying resource type for the `ty` table specified. @@ -422,10 +420,10 @@ impl<'a> LiftContext<'a> { &mut self, ty: TypeResourceTableIndex, idx: u32, - ) -> Result<(u32, Option>, Option)> { + ) -> Result<(u32, Option>, Option)> { let idx = self.resource_tables().guest_resource_lift_own(idx, ty)?; - let (dtor, flags) = self.instance.dtor_and_flags(ty); - Ok((idx, dtor, flags)) + let (dtor, instance) = self.instance.dtor_and_instance(ty); + Ok((idx, dtor, instance)) } /// Lifts a `borrow` resource from the guest at the `idx` specified. @@ -443,10 +441,10 @@ impl<'a> LiftContext<'a> { &mut self, rep: u32, dtor: Option>, - flags: Option, + instance: Option, ) -> Result { self.resource_tables() - .host_resource_lower_own(rep, dtor, flags) + .host_resource_lower_own(rep, dtor, instance) } /// Lowers a resource into the host-owned table, returning the index it was diff --git a/crates/wasmtime/src/runtime/component/mod.rs b/crates/wasmtime/src/runtime/component/mod.rs index 38896e2e2a25..a641c02d8dab 100644 --- a/crates/wasmtime/src/runtime/component/mod.rs +++ b/crates/wasmtime/src/runtime/component/mod.rs @@ -139,7 +139,7 @@ pub use self::values::Val; pub(crate) use self::instance::RuntimeImport; pub(crate) use self::resources::HostResourceData; -pub(crate) use self::store::ComponentInstanceId; +pub(crate) use self::store::{ComponentInstanceId, RuntimeInstance}; // Re-export wasm_wave crate so the compatible version of this dep doesn't have to be // tracked separately from wasmtime. diff --git a/crates/wasmtime/src/runtime/component/resources/any.rs b/crates/wasmtime/src/runtime/component/resources/any.rs index 343b331bcc49..052c6ae5b4eb 100644 --- a/crates/wasmtime/src/runtime/component/resources/any.rs +++ b/crates/wasmtime/src/runtime/component/resources/any.rs @@ -192,11 +192,9 @@ impl ResourceAny { // Note that this should be safe because the raw pointer access in // `flags` is valid due to `store` being the owner of the flags and // flags are never destroyed within the store. - if let Some(flags) = slot.flags { - unsafe { - if !flags.may_enter() { - bail!(Trap::CannotEnterComponent); - } + if let Some(instance) = slot.instance { + if !store.0.may_enter(instance) { + bail!(Trap::CannotEnterComponent); } } diff --git a/crates/wasmtime/src/runtime/component/resources/host_tables.rs b/crates/wasmtime/src/runtime/component/resources/host_tables.rs index a5e965688156..3ef7253897f9 100644 --- a/crates/wasmtime/src/runtime/component/resources/host_tables.rs +++ b/crates/wasmtime/src/runtime/component/resources/host_tables.rs @@ -21,9 +21,8 @@ //! the own is removed or otherwise taken out. use crate::prelude::*; -use crate::runtime::vm::component::{ - InstanceFlags, ResourceTables, TypedResource, TypedResourceIndex, -}; +use crate::runtime::component::RuntimeInstance; +use crate::runtime::vm::component::{ResourceTables, TypedResource, TypedResourceIndex}; use crate::runtime::vm::{SendSyncPtr, VMFuncRef}; use crate::store::StoreOpaque; use core::ptr::NonNull; @@ -69,7 +68,7 @@ pub struct HostResourceData { #[derive(Copy, Clone)] pub struct TableSlot { generation: u32, - pub(super) flags: Option, + pub(super) instance: Option, pub(super) dtor: Option>, } @@ -144,16 +143,16 @@ impl<'a> HostResourceTables<'a> { /// will point to the `rep` specified. The returned index is suitable for /// conversion into either [`Resource`] or [`ResourceAny`]. /// - /// The `dtor` and instance `flags` are specified as well to know what + /// The `dtor` and instance `instance` are specified as well to know what /// destructor to run when this resource is destroyed. pub fn host_resource_lower_own( &mut self, rep: u32, dtor: Option>, - flags: Option, + instance: Option, ) -> Result { let idx = self.tables.resource_lower_own(TypedResource::Host(rep))?; - Ok(self.new_host_index(idx, dtor, flags)) + Ok(self.new_host_index(idx, dtor, instance)) } /// See [`HostResourceTables::host_resource_lower_own`]. @@ -208,12 +207,12 @@ impl<'a> HostResourceTables<'a> { &mut self, idx: u32, dtor: Option>, - flags: Option, + instance: Option, ) -> HostResourceIndex { let list = &mut self.host_resource_data.table_slot_metadata; let info = TableSlot { generation: self.host_resource_data.cur_generation, - flags, + instance, dtor: dtor.map(SendSyncPtr::new), }; match list.get_mut(idx as usize) { @@ -225,7 +224,7 @@ impl<'a> HostResourceTables<'a> { assert_eq!(idx, 1); list.push(TableSlot { generation: 0, - flags: None, + instance: None, dtor: None, }); } diff --git a/crates/wasmtime/src/runtime/component/store.rs b/crates/wasmtime/src/runtime/component/store.rs index c24070c7eed2..0b2d571aa52d 100644 --- a/crates/wasmtime/src/runtime/component/store.rs +++ b/crates/wasmtime/src/runtime/component/store.rs @@ -6,16 +6,36 @@ use crate::store::{StoreData, StoreId, StoreOpaque}; use alloc::vec::Vec; use core::pin::Pin; use wasmtime_environ::PrimaryMap; +use wasmtime_environ::component::RuntimeComponentInstanceIndex; #[derive(Default)] pub struct ComponentStoreData { instances: PrimaryMap>, + + /// Whether an instance belonging to this store has trapped. + trapped: bool, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct ComponentInstanceId(u32); wasmtime_environ::entity_impl!(ComponentInstanceId); +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct RuntimeInstance { + pub instance: ComponentInstanceId, + pub index: RuntimeComponentInstanceIndex, +} + +impl StoreOpaque { + pub(crate) fn trapped(&self) -> bool { + self.store_data().components.trapped + } + + pub(crate) fn set_trapped(&mut self) { + self.store_data_mut().components.trapped = true; + } +} + impl StoreData { pub(crate) fn push_component_instance( &mut self, @@ -85,6 +105,14 @@ impl StoreOpaque { pub(crate) fn component_instance(&self, id: ComponentInstanceId) -> &ComponentInstance { self.store_data().component_instance(id) } + + #[cfg(feature = "component-model-async")] + pub(crate) fn component_instance_mut( + &mut self, + id: ComponentInstanceId, + ) -> Pin<&mut ComponentInstance> { + self.store_data_mut().component_instance_mut(id) + } } /// A type used to represent an allocated `ComponentInstance` located within a diff --git a/crates/wasmtime/src/runtime/func.rs b/crates/wasmtime/src/runtime/func.rs index ae4ec58da371..dd347a11b569 100644 --- a/crates/wasmtime/src/runtime/func.rs +++ b/crates/wasmtime/src/runtime/func.rs @@ -1510,6 +1510,10 @@ pub(crate) fn invoke_wasm_and_catch_traps( return Err(trap); } let result = crate::runtime::vm::catch_traps(store, &mut previous_runtime_state, closure); + #[cfg(feature = "component-model")] + if result.is_err() { + store.0.set_trapped(); + } core::mem::drop(previous_runtime_state); store.0.call_hook(CallHook::ReturningFromWasm)?; result diff --git a/crates/wasmtime/src/runtime/vm/component.rs b/crates/wasmtime/src/runtime/vm/component.rs index 35feb448d607..89ebc4796e26 100644 --- a/crates/wasmtime/src/runtime/vm/component.rs +++ b/crates/wasmtime/src/runtime/vm/component.rs @@ -9,9 +9,9 @@ use crate::Result; use crate::component::{Component, Instance, InstancePre, ResourceType, RuntimeImport}; use crate::module::ModuleRegistry; -use crate::runtime::component::ComponentInstanceId; #[cfg(feature = "component-model-async")] use crate::runtime::component::concurrent::ConcurrentInstanceState; +use crate::runtime::component::{ComponentInstanceId, RuntimeInstance}; use crate::runtime::vm::instance::{InstanceLayout, OwnedInstance, OwnedVMContext}; use crate::runtime::vm::vmcontext::VMFunctionBody; use crate::runtime::vm::{ @@ -700,7 +700,7 @@ impl ComponentInstance { // SAFETY: this is a valid initialization of all globals which are // 32-bit values. unsafe { - *def.as_i32_mut() = FLAG_MAY_ENTER | FLAG_MAY_LEAVE; + *def.as_i32_mut() = FLAG_MAY_LEAVE; self.instance_flags(i).as_raw().write(def); } } @@ -880,18 +880,20 @@ impl ComponentInstance { /// /// This will lookup the origin definition of the `ty` table and return the /// destructor/flags for that. - pub fn dtor_and_flags( + pub fn dtor_and_instance( &self, ty: TypeResourceTableIndex, - ) -> (Option>, Option) { + ) -> (Option>, Option) { let resource = self.component.types()[ty].unwrap_concrete_ty(); let dtor = self.resource_destructor(resource); let component = self.component.env_component(); - let flags = component.defined_resource_index(resource).map(|i| { - let instance = component.defined_resource_instances[i]; - self.instance_flags(instance) - }); - (dtor, flags) + let instance = component + .defined_resource_index(resource) + .map(|i| RuntimeInstance { + instance: self.id(), + index: component.defined_resource_instances[i], + }); + (dtor, instance) } /// Returns the store-local id that points to this component. @@ -1121,22 +1123,6 @@ impl InstanceFlags { } } - #[inline] - pub unsafe fn may_enter(&self) -> bool { - unsafe { *self.as_raw().as_ref().as_i32() & FLAG_MAY_ENTER != 0 } - } - - #[inline] - pub unsafe fn set_may_enter(&mut self, val: bool) { - unsafe { - if val { - *self.as_raw().as_mut().as_i32_mut() |= FLAG_MAY_ENTER; - } else { - *self.as_raw().as_mut().as_i32_mut() &= !FLAG_MAY_ENTER; - } - } - } - #[inline] pub unsafe fn needs_post_return(&self) -> bool { unsafe { *self.as_raw().as_ref().as_i32() & FLAG_NEEDS_POST_RETURN != 0 } diff --git a/crates/wasmtime/src/runtime/vm/component/libcalls.rs b/crates/wasmtime/src/runtime/vm/component/libcalls.rs index ae3d18edb635..bb426e98e11a 100644 --- a/crates/wasmtime/src/runtime/vm/component/libcalls.rs +++ b/crates/wasmtime/src/runtime/vm/component/libcalls.rs @@ -5,7 +5,9 @@ use crate::component::Instance; use crate::component::concurrent::WaitResult; use crate::prelude::*; #[cfg(feature = "component-model-async")] -use crate::runtime::component::concurrent::{ResourcePair, RuntimeInstance}; +use crate::runtime::component::RuntimeInstance; +#[cfg(feature = "component-model-async")] +use crate::runtime::component::concurrent::ResourcePair; use crate::runtime::vm::component::{ComponentInstance, VMComponentContext}; use crate::runtime::vm::{HostResultHasUnwindSentinel, VMStore, VmSafe}; use core::cell::Cell; diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs index 5fd35d7d9db3..426768977f19 100644 --- a/crates/wit-bindgen/src/lib.rs +++ b/crates/wit-bindgen/src/lib.rs @@ -2636,7 +2636,7 @@ impl<'a> InterfaceGenerator<'a> { if flags.contains(FunctionFlags::STORE | FunctionFlags::ASYNC) { uwrite!( self.src, - "(accessor: &{wt}::component::Accessor, " + "(accessor: &{wt}::component::Accessor, " ); } else if flags.contains(FunctionFlags::STORE) { uwrite!(self.src, "(host: {wt}::component::Access, "); diff --git a/tests/all/component_model/func.rs b/tests/all/component_model/func.rs index d0e8dc924fec..f35a8a1e26a2 100644 --- a/tests/all/component_model/func.rs +++ b/tests/all/component_model/func.rs @@ -183,8 +183,7 @@ fn integers() -> Result<()> { let engine = super::engine(); let component = Component::new(&engine, component)?; let mut store = Store::new(&engine, ()); - let new_instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component); - let instance = new_instance(&mut store)?; + let instance = Linker::new(&engine).instantiate(&mut store, &component)?; // Passing in 100 is valid for all primitives instance @@ -213,46 +212,62 @@ fn integers() -> Result<()> { .call_and_post_return(&mut store, (100,))?; // This specific wasm instance traps if any value other than 100 is passed - new_instance(&mut store)? - .get_typed_func::<(u8,), ()>(&mut store, "take-u8")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(i8,), ()>(&mut store, "take-s8")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(u16,), ()>(&mut store, "take-u16")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(i16,), ()>(&mut store, "take-s16")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(u32,), ()>(&mut store, "take-u32")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(i32,), ()>(&mut store, "take-s32")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(u64,), ()>(&mut store, "take-u64")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(i64,), ()>(&mut store, "take-s64")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(u8,), ()>(&mut *store, "take-u8")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(i8,), ()>(&mut *store, "take-s8")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(u16,), ()>(&mut *store, "take-u16")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(i16,), ()>(&mut *store, "take-s16")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(u32,), ()>(&mut *store, "take-u32")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(i32,), ()>(&mut *store, "take-s32")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(u64,), ()>(&mut *store, "take-u64")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(i64,), ()>(&mut *store, "take-s64")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; // Zero can be returned as any integer assert_eq!( @@ -1991,35 +2006,39 @@ fn some_traps() -> Result<()> { let engine = super::engine(); let component = Component::new(&engine, component)?; - let mut store = Store::new(&engine, ()); - let instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component); // This should fail when calling the allocator function for the argument - let err = instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-unreachable")? - .call(&mut store, (&[],)) - .unwrap_err() - .downcast::()?; + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-unreachable")? + .call(store, (&[],)) + .unwrap_err() + .downcast::() + })?; assert_eq!(err, Trap::UnreachableCodeReached); // This should fail when calling the allocator function for the argument - let err = instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-unreachable")? - .call(&mut store, ("",)) - .unwrap_err() - .downcast::()?; + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-unreachable")? + .call(store, ("",)) + .unwrap_err() + .downcast::() + })?; assert_eq!(err, Trap::UnreachableCodeReached); // This should fail when calling the allocator function for the space // to store the arguments (before arguments are even lowered) - let err = instance(&mut store)? - .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( - &mut store, - "take-many-unreachable", - )? - .call(&mut store, ("", "", "", "", "", "", "", "", "", "")) - .unwrap_err() - .downcast::()?; + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( + &mut *store, + "take-many-unreachable", + )? + .call(store, ("", "", "", "", "", "", "", "", "", "")) + .unwrap_err() + .downcast::() + })?; assert_eq!(err, Trap::UnreachableCodeReached); // Assert that when the base pointer returned by malloc is out of bounds @@ -2036,87 +2055,115 @@ fn some_traps() -> Result<()> { "{err:?}", ); } - let err = instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")? - .call(&mut store, (&[],)) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-base-oob")? + .call(store, (&[],)) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")? - .call(&mut store, (&[1],)) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-base-oob")? + .call(store, (&[1],)) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")? - .call(&mut store, ("",)) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-base-oob")? + .call(store, ("",)) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")? - .call(&mut store, ("x",)) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-base-oob")? + .call(store, ("x",)) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( - &mut store, - "take-many-base-oob", - )? - .call(&mut store, ("", "", "", "", "", "", "", "", "", "")) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( + &mut *store, + "take-many-base-oob", + )? + .call(store, ("", "", "", "", "", "", "", "", "", "")) + }) + .unwrap_err(); assert_oob(&err); // Test here that when the returned pointer from malloc is one byte from the // end of memory that empty things are fine, but larger things are not. - instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")? - .call_and_post_return(&mut store, (&[],))?; - instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")? - .call_and_post_return(&mut store, (&[1, 2, 3, 4],))?; - let err = instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")? - .call(&mut store, (&[1, 2, 3, 4, 5],)) - .unwrap_err(); + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-end-oob")? + .call_and_post_return(store, (&[],)) + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-end-oob")? + .call_and_post_return(store, (&[1, 2, 3, 4],)) + })?; + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-end-oob")? + .call(store, (&[1, 2, 3, 4, 5],)) + }) + .unwrap_err(); assert_oob(&err); - instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")? - .call_and_post_return(&mut store, ("",))?; - instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")? - .call_and_post_return(&mut store, ("abcd",))?; - let err = instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")? - .call(&mut store, ("abcde",)) - .unwrap_err(); + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-end-oob")? + .call_and_post_return(store, ("",)) + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-end-oob")? + .call_and_post_return(store, ("abcd",)) + })?; + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-end-oob")? + .call(store, ("abcde",)) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( - &mut store, - "take-many-end-oob", - )? - .call(&mut store, ("", "", "", "", "", "", "", "", "", "")) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( + &mut *store, + "take-many-end-oob", + )? + .call(store, ("", "", "", "", "", "", "", "", "", "")) + }) + .unwrap_err(); assert_oob(&err); // For this function the first allocation, the space to store all the // arguments, is in-bounds but then all further allocations, such as for // each individual string, are all out of bounds. - let err = instance(&mut store)? - .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( - &mut store, - "take-many-second-oob", - )? - .call(&mut store, ("", "", "", "", "", "", "", "", "", "")) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( + &mut *store, + "take-many-second-oob", + )? + .call(store, ("", "", "", "", "", "", "", "", "", "")) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( - &mut store, - "take-many-second-oob", - )? - .call(&mut store, ("", "", "", "", "", "", "", "", "", "x")) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( + &mut *store, + "take-many-second-oob", + )? + .call(store, ("", "", "", "", "", "", "", "", "", "x")) + }) + .unwrap_err(); assert_oob(&err); Ok(()) } @@ -3223,24 +3270,39 @@ fn errors_that_poison_instance() -> Result<()> { let engine = super::engine(); let component = Component::new(&engine, component)?; - let mut store = Store::new(&engine, ()); let linker = Linker::new(&engine); - let instance = linker.instantiate(&mut store, &component)?; - let f1 = instance.get_typed_func::<(), ()>(&mut store, "f1")?; - let f2 = instance.get_typed_func::<(), ()>(&mut store, "f2")?; - assert_unreachable(f1.call(&mut store, ())); - assert_poisoned(f1.call(&mut store, ())); - assert_poisoned(f2.call(&mut store, ())); - let instance = linker.instantiate(&mut store, &component)?; - let f3 = instance.get_typed_func::<(&str,), ()>(&mut store, "f3")?; - assert_unreachable(f3.call(&mut store, ("x",))); - assert_poisoned(f3.call(&mut store, ("x",))); + { + let mut store = Store::new(&engine, ()); + let instance = linker.instantiate(&mut store, &component)?; + let f1 = instance.get_typed_func::<(), ()>(&mut store, "f1")?; + let f2 = instance.get_typed_func::<(), ()>(&mut store, "f2")?; + assert_unreachable(f1.call(&mut store, ())); + assert_poisoned(f1.call(&mut store, ())); + assert_poisoned(f2.call(&mut store, ())); + } - let instance = linker.instantiate(&mut store, &component)?; - let f4 = instance.get_typed_func::<(), (WasmStr,)>(&mut store, "f4")?; - assert!(f4.call(&mut store, ()).is_err()); - assert_poisoned(f4.call(&mut store, ())); + { + let mut store = Store::new(&engine, ()); + let instance = linker.instantiate(&mut store, &component)?; + let f3 = instance.get_typed_func::<(&str,), ()>(&mut store, "f3")?; + assert_unreachable(f3.call(&mut store, ("x",))); + assert_poisoned(f3.call(&mut store, ("x",))); + + // Since we actually poison the store, even an unrelated instance will + // be considered poisoned: + let instance = linker.instantiate(&mut store, &component)?; + let f3 = instance.get_typed_func::<(&str,), ()>(&mut store, "f3")?; + assert_poisoned(f3.call(&mut store, ("x",))); + } + + { + let mut store = Store::new(&engine, ()); + let instance = linker.instantiate(&mut store, &component)?; + let f4 = instance.get_typed_func::<(), (WasmStr,)>(&mut store, "f4")?; + assert!(f4.call(&mut store, ()).is_err()); + assert_poisoned(f4.call(&mut store, ())); + } return Ok(()); @@ -3316,3 +3378,98 @@ fn run_export_with_internal_adapter() -> Result<()> { assert_eq!(run.call(&mut store, ())?, (5,)); Ok(()) } + +enum RecurseKind { + AThenA, + AThenB, + AThenBThenA, +} + +#[test] +fn recurse() -> Result<()> { + test_recurse(RecurseKind::AThenB) +} + +#[test] +fn recurse_trap() -> Result<()> { + let error = test_recurse(RecurseKind::AThenA).unwrap_err(); + + assert_eq!(error.downcast::()?, Trap::CannotEnterComponent); + + Ok(()) +} + +#[test] +fn recurse_more_trap() -> Result<()> { + let error = test_recurse(RecurseKind::AThenBThenA).unwrap_err(); + + assert_eq!(error.downcast::()?, Trap::CannotEnterComponent); + + Ok(()) +} + +fn test_recurse(kind: RecurseKind) -> Result<()> { + #[derive(Default)] + struct Ctx { + instances: Vec>, + } + + let component = r#" +(component + (import "import" (func $import)) + (core func $import (canon lower (func $import))) + (core module $m + (func $import (import "" "import")) + (func (export "export") call $import) + ) + (core instance $m (instantiate $m (with "" (instance + (export "import" (func $import)) + )))) + (func (export "export") (canon lift (core func $m "export"))) +) +"#; + let engine = super::engine(); + let component = Component::new(&engine, component)?; + let mut store = Store::new(&engine, Ctx::default()); + let mut linker = Linker::::new(&engine); + linker.root().func_wrap("import", |mut store, (): ()| { + if let Some(instance) = store.data_mut().instances.pop() { + let run = instance.get_typed_func::<(), ()>(&mut store, "export")?; + run.call(&mut store, ())?; + store.data_mut().instances.push(instance); + } + Ok(()) + })?; + let instance = Arc::new(linker.instantiate(&mut store, &component)?); + let instance = match kind { + RecurseKind::AThenA => { + store.data_mut().instances.push(instance.clone()); + instance + } + RecurseKind::AThenB => { + let other = Arc::new(linker.instantiate(&mut store, &component)?); + store.data_mut().instances.push(other); + instance + } + RecurseKind::AThenBThenA => { + store.data_mut().instances.push(instance.clone()); + let other = Arc::new(linker.instantiate(&mut store, &component)?); + store.data_mut().instances.push(other); + instance + } + }; + + let run = instance.get_typed_func::<(), ()>(&mut store, "export")?; + run.call(&mut store, ())?; + Ok(()) +} + +fn with_new_instance( + engine: &Engine, + component: &Component, + fun: impl Fn(&mut Store<()>, Instance) -> wasmtime::Result, +) -> wasmtime::Result { + let mut store = Store::new(engine, ()); + let instance = Linker::new(engine).instantiate(&mut store, component)?; + fun(&mut store, instance) +} diff --git a/tests/all/component_model/import.rs b/tests/all/component_model/import.rs index 3ab9c50d8188..b83e0cd95d21 100644 --- a/tests/all/component_model/import.rs +++ b/tests/all/component_model/import.rs @@ -348,55 +348,63 @@ fn attempt_to_leave_during_malloc() -> Result<()> { Ok(("hello".to_string(),)) })?; let component = Component::new(&engine, component)?; - let mut store = Store::new(&engine, ()); - // Assert that during a host import if we return values to wasm that a trap - // happens if we try to leave the instance. - let trap = linker - .instantiate(&mut store, &component)? - .get_typed_func::<(), ()>(&mut store, "run")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - format!("{trap:?}").contains("cannot leave component instance"), - "bad trap: {trap:?}", - ); + { + let mut store = Store::new(&engine, ()); + + // Assert that during a host import if we return values to wasm that a trap + // happens if we try to leave the instance. + let trap = linker + .instantiate(&mut store, &component)? + .get_typed_func::<(), ()>(&mut store, "run")? + .call(&mut store, ()) + .unwrap_err(); + assert!( + format!("{trap:?}").contains("cannot leave component instance"), + "bad trap: {trap:?}", + ); + + let trace = trap.downcast_ref::().unwrap().frames(); + assert_eq!(trace.len(), 4); + + // This was our entry point... + assert_eq!(trace[3].module().name(), Some("m")); + assert_eq!(trace[3].func_name(), Some("run")); + + // ... which called an imported function which ends up being originally + // defined by the shim instance. The shim instance then does an indirect + // call through a table which goes to the `canon.lower`'d host function + assert_eq!(trace[2].module().name(), Some("host_shim")); + assert_eq!(trace[2].func_name(), Some("shim_ret_string")); + + // ... and the lowered host function will call realloc to allocate space for + // the result + assert_eq!(trace[1].module().name(), Some("m")); + assert_eq!(trace[1].func_name(), Some("realloc")); + + // ... but realloc calls the shim instance and tries to exit the + // component, triggering a dynamic trap + assert_eq!(trace[0].module().name(), Some("host_shim")); + assert_eq!(trace[0].func_name(), Some("shim_thunk")); + } + + { + let mut store = Store::new(&engine, ()); + + // In addition to the above trap also ensure that when we enter a wasm + // component if we try to leave while lowering then that's also a dynamic + // trap. + let trap = linker + .instantiate(&mut store, &component)? + .get_typed_func::<(&str,), ()>(&mut store, "take-string")? + .call(&mut store, ("x",)) + .unwrap_err(); + assert!( + format!("{trap:?}").contains("cannot leave component instance"), + "bad trap: {trap:?}", + ); + } - let trace = trap.downcast_ref::().unwrap().frames(); - assert_eq!(trace.len(), 4); - - // This was our entry point... - assert_eq!(trace[3].module().name(), Some("m")); - assert_eq!(trace[3].func_name(), Some("run")); - - // ... which called an imported function which ends up being originally - // defined by the shim instance. The shim instance then does an indirect - // call through a table which goes to the `canon.lower`'d host function - assert_eq!(trace[2].module().name(), Some("host_shim")); - assert_eq!(trace[2].func_name(), Some("shim_ret_string")); - - // ... and the lowered host function will call realloc to allocate space for - // the result - assert_eq!(trace[1].module().name(), Some("m")); - assert_eq!(trace[1].func_name(), Some("realloc")); - - // ... but realloc calls the shim instance and tries to exit the - // component, triggering a dynamic trap - assert_eq!(trace[0].module().name(), Some("host_shim")); - assert_eq!(trace[0].func_name(), Some("shim_thunk")); - - // In addition to the above trap also ensure that when we enter a wasm - // component if we try to leave while lowering then that's also a dynamic - // trap. - let trap = linker - .instantiate(&mut store, &component)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string")? - .call(&mut store, ("x",)) - .unwrap_err(); - assert!( - format!("{trap:?}").contains("cannot leave component instance"), - "bad trap: {trap:?}", - ); Ok(()) } @@ -1048,28 +1056,34 @@ fn bad_import_alignment() -> Result<()> { -> Result<()> { unreachable!() }, )?; let component = Component::new(&engine, component)?; - let mut store = Store::new(&engine, ()); - let trap = linker - .instantiate(&mut store, &component)? - .get_typed_func::<(), ()>(&mut store, "unaligned-retptr2")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - format!("{trap:?}").contains("pointer not aligned"), - "{}", - trap - ); - let trap = linker - .instantiate(&mut store, &component)? - .get_typed_func::<(), ()>(&mut store, "unaligned-argptr2")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - format!("{trap:?}").contains("pointer not aligned"), - "{}", - trap - ); + { + let mut store = Store::new(&engine, ()); + let trap = linker + .instantiate(&mut store, &component)? + .get_typed_func::<(), ()>(&mut store, "unaligned-retptr2")? + .call(&mut store, ()) + .unwrap_err(); + assert!( + format!("{trap:?}").contains("pointer not aligned"), + "{}", + trap + ); + } + + { + let mut store = Store::new(&engine, ()); + let trap = linker + .instantiate(&mut store, &component)? + .get_typed_func::<(), ()>(&mut store, "unaligned-argptr2")? + .call(&mut store, ()) + .unwrap_err(); + assert!( + format!("{trap:?}").contains("pointer not aligned"), + "{}", + trap + ); + } Ok(()) } diff --git a/tests/all/component_model/strings.rs b/tests/all/component_model/strings.rs index 3caabf432531..ce60ea10fdb8 100644 --- a/tests/all/component_model/strings.rs +++ b/tests/all/component_model/strings.rs @@ -314,10 +314,10 @@ fn test_ptr_overflow(engine: &Engine, src: &str, dst: &str) -> Result<()> { ); let component = Component::new(engine, &component)?; - let mut store = Store::new(engine, ()); - let mut test_overflow = |size: u32| -> Result<()> { + let test_overflow = |size: u32| -> Result<()> { println!("src={src} dst={dst} size={size:#x}"); + let mut store = Store::new(engine, ()); let instance = Linker::new(engine).instantiate(&mut store, &component)?; let func = instance.get_typed_func::<(u32,), ()>(&mut store, "f")?; let trap = func diff --git a/tests/component-model b/tests/component-model index 48603cbc04db..ac37fe92a218 160000 --- a/tests/component-model +++ b/tests/component-model @@ -1 +1 @@ -Subproject commit 48603cbc04dbb3e69cefba5b259941876459fb8d +Subproject commit ac37fe92a21865aa8ca84b5bcbeb2da3746b6dc8 diff --git a/tests/disas/component-model/direct-adapter-calls-inlining.wat b/tests/disas/component-model/direct-adapter-calls-inlining.wat index 6c8f4fb6d8ba..5ebe6f42abce 100644 --- a/tests/disas/component-model/direct-adapter-calls-inlining.wat +++ b/tests/disas/component-model/direct-adapter-calls-inlining.wat @@ -64,8 +64,8 @@ ;; gv6 = load.i64 notrap aligned gv5+16 ;; gv7 = vmctx ;; gv8 = load.i64 notrap aligned readonly can_move gv7+120 -;; gv9 = load.i64 notrap aligned readonly can_move gv7+96 -;; gv10 = load.i64 notrap aligned readonly can_move gv7+144 +;; gv9 = load.i64 notrap aligned readonly can_move gv7+144 +;; gv10 = load.i64 notrap aligned readonly can_move gv7+96 ;; gv11 = vmctx ;; gv12 = load.i64 notrap aligned readonly gv11+8 ;; gv13 = load.i64 notrap aligned gv12+16 @@ -91,74 +91,51 @@ ;; brif v18, block4, block5 ;; ;; block4: -;; v92 = load.i64 notrap aligned readonly can_move v5+72 -;; v93 = load.i64 notrap aligned readonly can_move v5+88 -;; v19 = iconst.i32 24 -;; call_indirect sig1, v92(v93, v5, v19) ; v19 = 24 +;; v21 = load.i64 notrap aligned readonly can_move v5+72 +;; v20 = load.i64 notrap aligned readonly can_move v5+88 +;; v19 = iconst.i32 23 +;; call_indirect sig1, v21(v20, v5, v19) ; v19 = 23 ;; trap user11 ;; ;; block5: -;; v22 = load.i64 notrap aligned readonly can_move v5+96 +;; v22 = load.i64 notrap aligned readonly can_move v5+144 ;; v23 = load.i32 notrap aligned table v22 -;; v24 = iconst.i32 2 -;; v25 = band v23, v24 ; v24 = 2 -;; v81 = iconst.i32 0 -;; v82 = icmp eq v25, v81 ; v81 = 0 -;; v28 = uextend.i32 v82 -;; brif v28, block6, block7 +;; v61 = iconst.i32 0 +;; store notrap aligned table v61, v22 ; v61 = 0 +;; v26 = load.i64 notrap aligned readonly can_move v5+96 +;; v27 = load.i32 notrap aligned table v26 +;; v28 = iconst.i32 -2 +;; v29 = band v27, v28 ; v28 = -2 +;; store notrap aligned table v29, v26 +;; v62 = iconst.i32 1 +;; v63 = bor v27, v62 ; v62 = 1 +;; store notrap aligned table v63, v26 +;; jump block6 ;; ;; block6: -;; v21 = load.i64 notrap aligned readonly can_move v5+72 -;; v20 = load.i64 notrap aligned readonly can_move v5+88 -;; v29 = iconst.i32 18 -;; call_indirect sig1, v21(v20, v5, v29) ; v29 = 18 -;; trap user11 +;; jump block7 ;; ;; block7: -;; v34 = iconst.i32 -3 -;; v35 = band.i32 v23, v34 ; v34 = -3 -;; store notrap aligned table v35, v22 -;; v37 = load.i64 notrap aligned readonly can_move v5+144 -;; v38 = load.i32 notrap aligned table v37 -;; v83 = iconst.i32 0 -;; store notrap aligned table v83, v37 ; v83 = 0 -;; v42 = load.i32 notrap aligned table v22 -;; v43 = iconst.i32 -2 -;; v44 = band v42, v43 ; v43 = -2 -;; store notrap aligned table v44, v22 -;; v84 = iconst.i32 1 -;; v85 = bor v42, v84 ; v84 = 1 -;; store notrap aligned table v85, v22 ;; jump block8 ;; ;; block8: -;; jump block9 -;; -;; block9: -;; jump block10 -;; -;; block10: -;; v55 = load.i32 notrap aligned table v12 -;; v86 = iconst.i32 -2 -;; v87 = band v55, v86 ; v86 = -2 -;; store notrap aligned table v87, v12 -;; v88 = iconst.i32 1 -;; v89 = bor v55, v88 ; v88 = 1 -;; store notrap aligned table v89, v12 -;; v65 = load.i32 notrap aligned table v22 -;; v90 = iconst.i32 2 -;; v91 = bor v65, v90 ; v90 = 2 -;; store notrap aligned table v91, v22 -;; store.i32 notrap aligned table v38, v37 +;; v40 = load.i32 notrap aligned table v12 +;; v64 = iconst.i32 -2 +;; v65 = band v40, v64 ; v64 = -2 +;; store notrap aligned table v65, v12 +;; v66 = iconst.i32 1 +;; v67 = bor v40, v66 ; v66 = 1 +;; store notrap aligned table v67, v12 +;; store.i32 notrap aligned table v23, v22 ;; jump block3 ;; ;; block3: -;; jump block11 +;; jump block9 ;; -;; block11: +;; block9: ;; @00f0 jump block1 ;; ;; block1: -;; v72 = iconst.i32 1276 -;; @00f0 return v72 ; v72 = 1276 +;; v52 = iconst.i32 1276 +;; @00f0 return v52 ; v52 = 1276 ;; } diff --git a/tests/disas/component-model/direct-adapter-calls-x64.wat b/tests/disas/component-model/direct-adapter-calls-x64.wat index e1ef652561c1..d6d1684ba1eb 100644 --- a/tests/disas/component-model/direct-adapter-calls-x64.wat +++ b/tests/disas/component-model/direct-adapter-calls-x64.wat @@ -87,61 +87,47 @@ ;; movq 0x10(%r10), %r10 ;; addq $0x30, %r10 ;; cmpq %rsp, %r10 -;; ja 0x14e +;; ja 0x113 ;; 79: subq $0x20, %rsp ;; movq %rbx, (%rsp) ;; movq %r12, 8(%rsp) ;; movq %r14, 0x10(%rsp) -;; movq %r15, 0x18(%rsp) -;; movq 0x78(%rdi), %r12 -;; movl (%r12), %r8d -;; testl $1, %r8d -;; je 0x13a -;; a5: movq 0x60(%rdi), %rbx -;; movl (%rbx), %r9d -;; testl $2, %r9d -;; je 0x126 -;; b9: andl $0xfffffffd, %r9d -;; movl %r9d, (%rbx) -;; movq 0x90(%rdi), %r14 -;; movq %rdi, %r10 -;; movl (%r14), %r15d -;; movl $0, (%r14) -;; movl (%rbx), %esi -;; movq %rsi, %rax -;; andl $0xfffffffe, %eax -;; movl %eax, (%rbx) -;; orl $1, %esi -;; movl %esi, (%rbx) -;; movq 0x40(%r10), %rdi -;; movq %r10, %rsi +;; movq 0x78(%rdi), %r14 +;; movl (%r14), %esi +;; testl $1, %esi +;; je 0xff +;; 9e: movq 0x90(%rdi), %rbx +;; movl (%rbx), %r12d +;; movl $0, (%rbx) +;; movq 0x60(%rdi), %rcx +;; movq %rdi, %r9 +;; movl (%rcx), %eax +;; movq %rax, %r8 +;; andl $0xfffffffe, %r8d +;; movl %r8d, (%rcx) +;; orl $1, %eax +;; movl %eax, (%rcx) +;; movq 0x40(%r9), %rdi +;; movq %r9, %rsi ;; callq 0 -;; movl (%r12), %ecx -;; movq %rcx, %rdx -;; andl $0xfffffffe, %edx -;; movl %edx, (%r12) +;; movl (%r14), %ecx +;; movq %rcx, %r8 +;; andl $0xfffffffe, %r8d +;; movl %r8d, (%r14) ;; orl $1, %ecx -;; movl %ecx, (%r12) -;; orl $2, (%rbx) -;; movl %r15d, (%r14) +;; movl %ecx, (%r14) +;; movl %r12d, (%rbx) ;; movq (%rsp), %rbx ;; movq 8(%rsp), %r12 ;; movq 0x10(%rsp), %r14 -;; movq 0x18(%rsp), %r15 ;; addq $0x20, %rsp ;; movq %rbp, %rsp ;; popq %rbp ;; retq -;; 126: movq %rdi, %rsi -;; 129: movq 0x48(%rsi), %rax -;; 12d: movq 0x58(%rsi), %rdi -;; 131: movl $0x12, %edx -;; 136: callq *%rax -;; 138: ud2 -;; 13a: movq %rdi, %rsi -;; 13d: movq 0x48(%rsi), %rcx -;; 141: movq 0x58(%rsi), %rdi -;; 145: movl $0x18, %edx -;; 14a: callq *%rcx -;; 14c: ud2 -;; 14e: ud2 +;; ff: movq %rdi, %rsi +;; 102: movq 0x48(%rsi), %rax +;; 106: movq 0x58(%rsi), %rdi +;; 10a: movl $0x17, %edx +;; 10f: callq *%rax +;; 111: ud2 +;; 113: ud2 diff --git a/tests/disas/component-model/direct-adapter-calls.wat b/tests/disas/component-model/direct-adapter-calls.wat index ef9478ab57eb..26d94affea67 100644 --- a/tests/disas/component-model/direct-adapter-calls.wat +++ b/tests/disas/component-model/direct-adapter-calls.wat @@ -97,8 +97,8 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned readonly can_move gv3+120 -;; gv5 = load.i64 notrap aligned readonly can_move gv3+96 -;; gv6 = load.i64 notrap aligned readonly can_move gv3+144 +;; gv5 = load.i64 notrap aligned readonly can_move gv3+144 +;; gv6 = load.i64 notrap aligned readonly can_move gv3+96 ;; sig0 = (i64 vmctx, i64, i32) tail ;; sig1 = (i64 vmctx, i64, i32) -> i32 tail ;; fn0 = colocated u0:0 sig1 @@ -115,58 +115,35 @@ ;; @0098 brif v10, block2, block3 ;; ;; block2: -;; v94 = load.i64 notrap aligned readonly can_move v0+72 -;; v95 = load.i64 notrap aligned readonly can_move v0+88 -;; @009a v11 = iconst.i32 24 -;; @009c call_indirect sig0, v94(v95, v0, v11) ; v11 = 24 +;; @009c v14 = load.i64 notrap aligned readonly can_move v0+72 +;; @009c v13 = load.i64 notrap aligned readonly can_move v0+88 +;; @009a v11 = iconst.i32 23 +;; @009c call_indirect sig0, v14(v13, v0, v11) ; v11 = 23 ;; @009e trap user11 ;; ;; block3: -;; @00a0 v15 = load.i64 notrap aligned readonly can_move v0+96 +;; @00a0 v15 = load.i64 notrap aligned readonly can_move v0+144 ;; @00a0 v16 = load.i32 notrap aligned table v15 -;; @00a2 v17 = iconst.i32 2 -;; @00a4 v18 = band v16, v17 ; v17 = 2 -;; v86 = iconst.i32 0 -;; v87 = icmp eq v18, v86 ; v86 = 0 -;; @00a5 v20 = uextend.i32 v87 -;; @00a6 brif v20, block4, block5 -;; -;; block4: -;; @009c v14 = load.i64 notrap aligned readonly can_move v0+72 -;; @009c v13 = load.i64 notrap aligned readonly can_move v0+88 -;; @00a8 v21 = iconst.i32 18 -;; @00aa call_indirect sig0, v14(v13, v0, v21) ; v21 = 18 -;; @00ac trap user11 -;; -;; block5: -;; @00b0 v27 = iconst.i32 -3 -;; @00b2 v28 = band.i32 v16, v27 ; v27 = -3 -;; @00b3 store notrap aligned table v28, v15 -;; @00b5 v30 = load.i64 notrap aligned readonly can_move v0+144 -;; @00b5 v31 = load.i32 notrap aligned table v30 -;; v88 = iconst.i32 0 -;; @00bb store notrap aligned table v88, v30 ; v88 = 0 -;; @00bd v35 = load.i32 notrap aligned table v15 -;; @00bf v36 = iconst.i32 -2 -;; @00c1 v37 = band v35, v36 ; v36 = -2 -;; @00c2 store notrap aligned table v37, v15 -;; v89 = iconst.i32 1 -;; v90 = bor v35, v89 ; v89 = 1 -;; @00cb store notrap aligned table v90, v15 -;; @00cd v45 = load.i64 notrap aligned readonly can_move v0+64 -;; @00cd v46 = call fn0(v45, v0, v2) -;; @00d1 v48 = load.i32 notrap aligned table v5 -;; @00d5 v50 = band v48, v36 ; v36 = -2 -;; @00d6 store notrap aligned table v50, v5 -;; v91 = bor v48, v89 ; v89 = 1 -;; @00df store notrap aligned table v91, v5 -;; @00e1 v58 = load.i32 notrap aligned table v15 -;; v92 = iconst.i32 2 -;; v93 = bor v58, v92 ; v92 = 2 -;; @00e6 store notrap aligned table v93, v15 -;; @00ea store notrap aligned table v31, v30 -;; @00ec jump block1 +;; v60 = iconst.i32 0 +;; @00a6 store notrap aligned table v60, v15 ; v60 = 0 +;; @00a8 v19 = load.i64 notrap aligned readonly can_move v0+96 +;; @00a8 v20 = load.i32 notrap aligned table v19 +;; @00aa v21 = iconst.i32 -2 +;; @00ac v22 = band v20, v21 ; v21 = -2 +;; @00ad store notrap aligned table v22, v19 +;; v61 = iconst.i32 1 +;; v62 = bor v20, v61 ; v61 = 1 +;; @00b6 store notrap aligned table v62, v19 +;; @00b8 v30 = load.i64 notrap aligned readonly can_move v0+64 +;; @00b8 v31 = call fn0(v30, v0, v2) +;; @00bc v33 = load.i32 notrap aligned table v5 +;; @00c0 v35 = band v33, v21 ; v21 = -2 +;; @00c1 store notrap aligned table v35, v5 +;; v63 = bor v33, v61 ; v61 = 1 +;; @00ca store notrap aligned table v63, v5 +;; @00ce store notrap aligned table v16, v15 +;; @00d0 jump block1 ;; ;; block1: -;; @00ec return v46 +;; @00d0 return v31 ;; } diff --git a/tests/disas/gc/drc/array-fill.wat b/tests/disas/gc/drc/array-fill.wat index c29a4de19477..f11bbf32353c 100644 --- a/tests/disas/gc/drc/array-fill.wat +++ b/tests/disas/gc/drc/array-fill.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i64, v5: i32): -;; @0027 trapz v2, user16 +;; @0027 trapz v2, user15 ;; @0027 v41 = load.i64 notrap aligned readonly can_move v0+8 ;; @0027 v7 = load.i64 notrap aligned readonly can_move v41+24 ;; @0027 v6 = uextend.i64 v2 @@ -28,9 +28,9 @@ ;; @0027 v9 = iconst.i64 24 ;; @0027 v10 = iadd v8, v9 ; v9 = 24 ;; @0027 v11 = load.i32 notrap aligned readonly v10 -;; @0027 v12 = uadd_overflow_trap v3, v5, user17 +;; @0027 v12 = uadd_overflow_trap v3, v5, user16 ;; @0027 v13 = icmp ugt v12, v11 -;; @0027 trapnz v13, user17 +;; @0027 trapnz v13, user16 ;; @0027 v15 = uextend.i64 v11 ;; v43 = iconst.i64 3 ;; v44 = ishl v15, v43 ; v43 = 3 diff --git a/tests/disas/gc/drc/array-get-s.wat b/tests/disas/gc/drc/array-get-s.wat index 65a77207b1a2..518306068922 100644 --- a/tests/disas/gc/drc/array-get-s.wat +++ b/tests/disas/gc/drc/array-get-s.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v34 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v34+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 24 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v33 = iconst.i64 32 ;; @0022 v15 = ushr v13, v33 ; v33 = 32 diff --git a/tests/disas/gc/drc/array-get-u.wat b/tests/disas/gc/drc/array-get-u.wat index 6d8a36878e65..8c9ce0a97985 100644 --- a/tests/disas/gc/drc/array-get-u.wat +++ b/tests/disas/gc/drc/array-get-u.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v34 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v34+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 24 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v33 = iconst.i64 32 ;; @0022 v15 = ushr v13, v33 ; v33 = 32 diff --git a/tests/disas/gc/drc/array-get.wat b/tests/disas/gc/drc/array-get.wat index 306faaf2af32..8aaf3770c34f 100644 --- a/tests/disas/gc/drc/array-get.wat +++ b/tests/disas/gc/drc/array-get.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v33 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v33+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 24 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v35 = iconst.i64 3 ;; v36 = ishl v13, v35 ; v35 = 3 diff --git a/tests/disas/gc/drc/array-len.wat b/tests/disas/gc/drc/array-len.wat index 58f535721345..444db28ad6a1 100644 --- a/tests/disas/gc/drc/array-len.wat +++ b/tests/disas/gc/drc/array-len.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @001f trapz v2, user16 +;; @001f trapz v2, user15 ;; @001f v10 = load.i64 notrap aligned readonly can_move v0+8 ;; @001f v5 = load.i64 notrap aligned readonly can_move v10+24 ;; @001f v4 = uextend.i64 v2 diff --git a/tests/disas/gc/drc/array-new.wat b/tests/disas/gc/drc/array-new.wat index f2edee849f50..fd30585c07c4 100644 --- a/tests/disas/gc/drc/array-new.wat +++ b/tests/disas/gc/drc/array-new.wat @@ -26,11 +26,11 @@ ;; v36 = ishl v6, v35 ; v35 = 3 ;; v33 = iconst.i64 32 ;; @0022 v8 = ushr v36, v33 ; v33 = 32 -;; @0022 trapnz v8, user18 +;; @0022 trapnz v8, user17 ;; @0022 v5 = iconst.i32 32 ;; v42 = iconst.i32 3 ;; v43 = ishl v3, v42 ; v42 = 3 -;; @0022 v10 = uadd_overflow_trap v5, v43, user18 ; v5 = 32 +;; @0022 v10 = uadd_overflow_trap v5, v43, user17 ; v5 = 32 ;; @0022 v12 = iconst.i32 -1476395008 ;; @0022 v13 = iconst.i32 0 ;; v40 = iconst.i32 8 diff --git a/tests/disas/gc/drc/array-set.wat b/tests/disas/gc/drc/array-set.wat index b053ebb23bc4..c88b12650218 100644 --- a/tests/disas/gc/drc/array-set.wat +++ b/tests/disas/gc/drc/array-set.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i64): -;; @0024 trapz v2, user16 +;; @0024 trapz v2, user15 ;; @0024 v32 = load.i64 notrap aligned readonly can_move v0+8 ;; @0024 v6 = load.i64 notrap aligned readonly can_move v32+24 ;; @0024 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0024 v9 = iadd v7, v8 ; v8 = 24 ;; @0024 v10 = load.i32 notrap aligned readonly v9 ;; @0024 v11 = icmp ult v3, v10 -;; @0024 trapz v11, user17 +;; @0024 trapz v11, user16 ;; @0024 v13 = uextend.i64 v10 ;; v34 = iconst.i64 3 ;; v35 = ishl v13, v34 ; v34 = 3 diff --git a/tests/disas/gc/drc/funcref-in-gc-heap-get.wat b/tests/disas/gc/drc/funcref-in-gc-heap-get.wat index a0752b7806e9..d0dd4fe7e989 100644 --- a/tests/disas/gc/drc/funcref-in-gc-heap-get.wat +++ b/tests/disas/gc/drc/funcref-in-gc-heap-get.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0020 trapz v2, user16 +;; @0020 trapz v2, user15 ;; @0020 v13 = load.i64 notrap aligned readonly can_move v0+8 ;; @0020 v5 = load.i64 notrap aligned readonly can_move v13+24 ;; @0020 v4 = uextend.i64 v2 diff --git a/tests/disas/gc/drc/funcref-in-gc-heap-set.wat b/tests/disas/gc/drc/funcref-in-gc-heap-set.wat index 2cd534a9a214..7f82110b0ba1 100644 --- a/tests/disas/gc/drc/funcref-in-gc-heap-set.wat +++ b/tests/disas/gc/drc/funcref-in-gc-heap-set.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i64): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v10 = call fn0(v0, v3) ;; @0022 v11 = ireduce.i32 v10 ;; @0022 v12 = load.i64 notrap aligned readonly can_move v0+8 diff --git a/tests/disas/gc/drc/multiple-array-get.wat b/tests/disas/gc/drc/multiple-array-get.wat index 04159cf15663..4b4cabdf1c05 100644 --- a/tests/disas/gc/drc/multiple-array-get.wat +++ b/tests/disas/gc/drc/multiple-array-get.wat @@ -21,7 +21,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32): -;; @0024 trapz v2, user16 +;; @0024 trapz v2, user15 ;; @0024 v65 = load.i64 notrap aligned readonly can_move v0+8 ;; @0024 v8 = load.i64 notrap aligned readonly can_move v65+24 ;; @0024 v7 = uextend.i64 v2 @@ -30,7 +30,7 @@ ;; @0024 v11 = iadd v9, v10 ; v10 = 24 ;; @0024 v12 = load.i32 notrap aligned readonly v11 ;; @0024 v13 = icmp ult v3, v12 -;; @0024 trapz v13, user17 +;; @0024 trapz v13, user16 ;; @0024 v15 = uextend.i64 v12 ;; v67 = iconst.i64 3 ;; v68 = ishl v15, v67 ; v67 = 3 @@ -51,7 +51,7 @@ ;; @0024 v30 = isub v27, v29 ;; @0024 v31 = load.i64 notrap aligned little v30 ;; @002b v38 = icmp ult v4, v12 -;; @002b trapz v38, user17 +;; @002b trapz v38, user16 ;; v86 = ishl v4, v77 ; v77 = 3 ;; @002b v48 = iadd v86, v19 ; v19 = 32 ;; @002b v53 = isub v20, v48 diff --git a/tests/disas/gc/drc/multiple-struct-get.wat b/tests/disas/gc/drc/multiple-struct-get.wat index 35ef796ac449..bc1f3bc782ee 100644 --- a/tests/disas/gc/drc/multiple-struct-get.wat +++ b/tests/disas/gc/drc/multiple-struct-get.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0023 trapz v2, user16 +;; @0023 trapz v2, user15 ;; @0023 v20 = load.i64 notrap aligned readonly can_move v0+8 ;; @0023 v6 = load.i64 notrap aligned readonly can_move v20+24 ;; @0023 v5 = uextend.i64 v2 diff --git a/tests/disas/gc/drc/ref-cast.wat b/tests/disas/gc/drc/ref-cast.wat index 83fad1e6c005..4056ef24b30a 100644 --- a/tests/disas/gc/drc/ref-cast.wat +++ b/tests/disas/gc/drc/ref-cast.wat @@ -57,7 +57,7 @@ ;; @001e jump block4(v23) ;; ;; block4(v24: i32): -;; @001e trapz v24, user19 +;; @001e trapz v24, user18 ;; v25 = load.i32 notrap v36 ;; @0021 jump block1 ;; diff --git a/tests/disas/gc/drc/struct-get.wat b/tests/disas/gc/drc/struct-get.wat index c0221c3e1f6d..0c87b1bf42ab 100644 --- a/tests/disas/gc/drc/struct-get.wat +++ b/tests/disas/gc/drc/struct-get.wat @@ -34,7 +34,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0033 trapz v2, user16 +;; @0033 trapz v2, user15 ;; @0033 v10 = load.i64 notrap aligned readonly can_move v0+8 ;; @0033 v5 = load.i64 notrap aligned readonly can_move v10+24 ;; @0033 v4 = uextend.i64 v2 @@ -59,7 +59,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @003c trapz v2, user16 +;; @003c trapz v2, user15 ;; @003c v11 = load.i64 notrap aligned readonly can_move v0+8 ;; @003c v5 = load.i64 notrap aligned readonly can_move v11+24 ;; @003c v4 = uextend.i64 v2 @@ -85,7 +85,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0045 trapz v2, user16 +;; @0045 trapz v2, user15 ;; @0045 v11 = load.i64 notrap aligned readonly can_move v0+8 ;; @0045 v5 = load.i64 notrap aligned readonly can_move v11+24 ;; @0045 v4 = uextend.i64 v2 @@ -111,7 +111,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @004e trapz v2, user16 +;; @004e trapz v2, user15 ;; @004e v58 = load.i64 notrap aligned readonly can_move v0+8 ;; @004e v5 = load.i64 notrap aligned readonly can_move v58+24 ;; @004e v4 = uextend.i64 v2 diff --git a/tests/disas/gc/drc/struct-set.wat b/tests/disas/gc/drc/struct-set.wat index a762954a46c6..118899ecbc59 100644 --- a/tests/disas/gc/drc/struct-set.wat +++ b/tests/disas/gc/drc/struct-set.wat @@ -30,7 +30,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: f32): -;; @0034 trapz v2, user16 +;; @0034 trapz v2, user15 ;; @0034 v9 = load.i64 notrap aligned readonly can_move v0+8 ;; @0034 v5 = load.i64 notrap aligned readonly can_move v9+24 ;; @0034 v4 = uextend.i64 v2 @@ -55,7 +55,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @003f trapz v2, user16 +;; @003f trapz v2, user15 ;; @003f v9 = load.i64 notrap aligned readonly can_move v0+8 ;; @003f v5 = load.i64 notrap aligned readonly can_move v9+24 ;; @003f v4 = uextend.i64 v2 @@ -82,7 +82,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @004a trapz v2, user16 +;; @004a trapz v2, user15 ;; @004a v59 = load.i64 notrap aligned readonly can_move v0+8 ;; @004a v5 = load.i64 notrap aligned readonly can_move v59+24 ;; @004a v4 = uextend.i64 v2 diff --git a/tests/disas/gc/null/array-fill.wat b/tests/disas/gc/null/array-fill.wat index 2ddc505ea823..2dd07bec4326 100644 --- a/tests/disas/gc/null/array-fill.wat +++ b/tests/disas/gc/null/array-fill.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i64, v5: i32): -;; @0027 trapz v2, user16 +;; @0027 trapz v2, user15 ;; @0027 v41 = load.i64 notrap aligned readonly can_move v0+8 ;; @0027 v7 = load.i64 notrap aligned readonly can_move v41+24 ;; @0027 v6 = uextend.i64 v2 @@ -28,9 +28,9 @@ ;; @0027 v9 = iconst.i64 8 ;; @0027 v10 = iadd v8, v9 ; v9 = 8 ;; @0027 v11 = load.i32 notrap aligned readonly v10 -;; @0027 v12 = uadd_overflow_trap v3, v5, user17 +;; @0027 v12 = uadd_overflow_trap v3, v5, user16 ;; @0027 v13 = icmp ugt v12, v11 -;; @0027 trapnz v13, user17 +;; @0027 trapnz v13, user16 ;; @0027 v15 = uextend.i64 v11 ;; v43 = iconst.i64 3 ;; v44 = ishl v15, v43 ; v43 = 3 diff --git a/tests/disas/gc/null/array-get-s.wat b/tests/disas/gc/null/array-get-s.wat index d33eb7715b82..0a04f752e7e1 100644 --- a/tests/disas/gc/null/array-get-s.wat +++ b/tests/disas/gc/null/array-get-s.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v34 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v34+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 8 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v33 = iconst.i64 32 ;; @0022 v15 = ushr v13, v33 ; v33 = 32 diff --git a/tests/disas/gc/null/array-get-u.wat b/tests/disas/gc/null/array-get-u.wat index de64885a7dc1..8f2f564f7f82 100644 --- a/tests/disas/gc/null/array-get-u.wat +++ b/tests/disas/gc/null/array-get-u.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v34 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v34+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 8 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v33 = iconst.i64 32 ;; @0022 v15 = ushr v13, v33 ; v33 = 32 diff --git a/tests/disas/gc/null/array-get.wat b/tests/disas/gc/null/array-get.wat index f03c2b8d1cee..4037eb150dd9 100644 --- a/tests/disas/gc/null/array-get.wat +++ b/tests/disas/gc/null/array-get.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v33 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v33+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 8 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v35 = iconst.i64 3 ;; v36 = ishl v13, v35 ; v35 = 3 diff --git a/tests/disas/gc/null/array-len.wat b/tests/disas/gc/null/array-len.wat index 31ac5e588bed..e551e1e92136 100644 --- a/tests/disas/gc/null/array-len.wat +++ b/tests/disas/gc/null/array-len.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @001f trapz v2, user16 +;; @001f trapz v2, user15 ;; @001f v10 = load.i64 notrap aligned readonly can_move v0+8 ;; @001f v5 = load.i64 notrap aligned readonly can_move v10+24 ;; @001f v4 = uextend.i64 v2 diff --git a/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat b/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat index 59623535efad..57f8d27b2570 100644 --- a/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat +++ b/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat @@ -34,11 +34,11 @@ ;; @0025 v17 = load.i64 notrap aligned readonly v0+32 ;; @0025 v18 = load.i32 notrap aligned v17 ;; v82 = iconst.i32 7 -;; @0025 v21 = uadd_overflow_trap v18, v82, user18 ; v82 = 7 +;; @0025 v21 = uadd_overflow_trap v18, v82, user17 ; v82 = 7 ;; v89 = iconst.i32 -8 ;; @0025 v23 = band v21, v89 ; v89 = -8 ;; v74 = iconst.i32 24 -;; @0025 v24 = uadd_overflow_trap v23, v74, user18 ; v74 = 24 +;; @0025 v24 = uadd_overflow_trap v23, v74, user17 ; v74 = 24 ;; @0025 v56 = load.i64 notrap aligned readonly can_move v0+8 ;; @0025 v26 = load.i64 notrap aligned v56+32 ;; @0025 v25 = uextend.i64 v24 diff --git a/tests/disas/gc/null/array-new-fixed.wat b/tests/disas/gc/null/array-new-fixed.wat index 4c96c8c34f19..36422419ee1d 100644 --- a/tests/disas/gc/null/array-new-fixed.wat +++ b/tests/disas/gc/null/array-new-fixed.wat @@ -25,11 +25,11 @@ ;; @0025 v17 = load.i64 notrap aligned readonly v0+32 ;; @0025 v18 = load.i32 notrap aligned v17 ;; v73 = iconst.i32 7 -;; @0025 v21 = uadd_overflow_trap v18, v73, user18 ; v73 = 7 +;; @0025 v21 = uadd_overflow_trap v18, v73, user17 ; v73 = 7 ;; v80 = iconst.i32 -8 ;; @0025 v23 = band v21, v80 ; v80 = -8 ;; v65 = iconst.i32 40 -;; @0025 v24 = uadd_overflow_trap v23, v65, user18 ; v65 = 40 +;; @0025 v24 = uadd_overflow_trap v23, v65, user17 ; v65 = 40 ;; @0025 v50 = load.i64 notrap aligned readonly can_move v0+8 ;; @0025 v26 = load.i64 notrap aligned v50+32 ;; @0025 v25 = uextend.i64 v24 diff --git a/tests/disas/gc/null/array-new.wat b/tests/disas/gc/null/array-new.wat index d7d430bfe8aa..cd144cbb97a4 100644 --- a/tests/disas/gc/null/array-new.wat +++ b/tests/disas/gc/null/array-new.wat @@ -27,21 +27,21 @@ ;; v56 = ishl v6, v55 ; v55 = 3 ;; v53 = iconst.i64 32 ;; @0022 v8 = ushr v56, v53 ; v53 = 32 -;; @0022 trapnz v8, user18 +;; @0022 trapnz v8, user17 ;; @0022 v5 = iconst.i32 16 ;; v62 = iconst.i32 3 ;; v63 = ishl v3, v62 ; v62 = 3 -;; @0022 v10 = uadd_overflow_trap v5, v63, user18 ; v5 = 16 +;; @0022 v10 = uadd_overflow_trap v5, v63, user17 ; v5 = 16 ;; @0022 v12 = iconst.i32 -67108864 ;; @0022 v13 = band v10, v12 ; v12 = -67108864 -;; @0022 trapnz v13, user18 +;; @0022 trapnz v13, user17 ;; @0022 v15 = load.i64 notrap aligned readonly v0+32 ;; @0022 v16 = load.i32 notrap aligned v15 ;; v66 = iconst.i32 7 -;; @0022 v19 = uadd_overflow_trap v16, v66, user18 ; v66 = 7 +;; @0022 v19 = uadd_overflow_trap v16, v66, user17 ; v66 = 7 ;; v73 = iconst.i32 -8 ;; @0022 v21 = band v19, v73 ; v73 = -8 -;; @0022 v22 = uadd_overflow_trap v21, v10, user18 +;; @0022 v22 = uadd_overflow_trap v21, v10, user17 ;; @0022 v51 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v24 = load.i64 notrap aligned v51+32 ;; @0022 v23 = uextend.i64 v22 diff --git a/tests/disas/gc/null/array-set.wat b/tests/disas/gc/null/array-set.wat index 0c13a75c47a5..2f2540d42e54 100644 --- a/tests/disas/gc/null/array-set.wat +++ b/tests/disas/gc/null/array-set.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i64): -;; @0024 trapz v2, user16 +;; @0024 trapz v2, user15 ;; @0024 v32 = load.i64 notrap aligned readonly can_move v0+8 ;; @0024 v6 = load.i64 notrap aligned readonly can_move v32+24 ;; @0024 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0024 v9 = iadd v7, v8 ; v8 = 8 ;; @0024 v10 = load.i32 notrap aligned readonly v9 ;; @0024 v11 = icmp ult v3, v10 -;; @0024 trapz v11, user17 +;; @0024 trapz v11, user16 ;; @0024 v13 = uextend.i64 v10 ;; v34 = iconst.i64 3 ;; v35 = ishl v13, v34 ; v34 = 3 diff --git a/tests/disas/gc/null/funcref-in-gc-heap-get.wat b/tests/disas/gc/null/funcref-in-gc-heap-get.wat index 417531ae00be..78e4178a670d 100644 --- a/tests/disas/gc/null/funcref-in-gc-heap-get.wat +++ b/tests/disas/gc/null/funcref-in-gc-heap-get.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0020 trapz v2, user16 +;; @0020 trapz v2, user15 ;; @0020 v13 = load.i64 notrap aligned readonly can_move v0+8 ;; @0020 v5 = load.i64 notrap aligned readonly can_move v13+24 ;; @0020 v4 = uextend.i64 v2 diff --git a/tests/disas/gc/null/funcref-in-gc-heap-new.wat b/tests/disas/gc/null/funcref-in-gc-heap-new.wat index d2f8b7f83c90..baef7b3e99ad 100644 --- a/tests/disas/gc/null/funcref-in-gc-heap-new.wat +++ b/tests/disas/gc/null/funcref-in-gc-heap-new.wat @@ -27,11 +27,11 @@ ;; @0020 v9 = load.i64 notrap aligned readonly v0+32 ;; @0020 v10 = load.i32 notrap aligned v9 ;; v47 = iconst.i32 7 -;; @0020 v13 = uadd_overflow_trap v10, v47, user18 ; v47 = 7 +;; @0020 v13 = uadd_overflow_trap v10, v47, user17 ; v47 = 7 ;; v54 = iconst.i32 -8 ;; @0020 v15 = band v13, v54 ; v54 = -8 ;; @0020 v4 = iconst.i32 16 -;; @0020 v16 = uadd_overflow_trap v15, v4, user18 ; v4 = 16 +;; @0020 v16 = uadd_overflow_trap v15, v4, user17 ; v4 = 16 ;; @0020 v38 = load.i64 notrap aligned readonly can_move v0+8 ;; @0020 v18 = load.i64 notrap aligned v38+32 ;; @0020 v17 = uextend.i64 v16 diff --git a/tests/disas/gc/null/funcref-in-gc-heap-set.wat b/tests/disas/gc/null/funcref-in-gc-heap-set.wat index aeed15a95b27..02f060375cae 100644 --- a/tests/disas/gc/null/funcref-in-gc-heap-set.wat +++ b/tests/disas/gc/null/funcref-in-gc-heap-set.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i64): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v10 = call fn0(v0, v3) ;; @0022 v11 = ireduce.i32 v10 ;; @0022 v12 = load.i64 notrap aligned readonly can_move v0+8 diff --git a/tests/disas/gc/null/multiple-array-get.wat b/tests/disas/gc/null/multiple-array-get.wat index dfe6fe665640..0e7fc6d46961 100644 --- a/tests/disas/gc/null/multiple-array-get.wat +++ b/tests/disas/gc/null/multiple-array-get.wat @@ -21,7 +21,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32): -;; @0024 trapz v2, user16 +;; @0024 trapz v2, user15 ;; @0024 v65 = load.i64 notrap aligned readonly can_move v0+8 ;; @0024 v8 = load.i64 notrap aligned readonly can_move v65+24 ;; @0024 v7 = uextend.i64 v2 @@ -30,7 +30,7 @@ ;; @0024 v11 = iadd v9, v10 ; v10 = 8 ;; @0024 v12 = load.i32 notrap aligned readonly v11 ;; @0024 v13 = icmp ult v3, v12 -;; @0024 trapz v13, user17 +;; @0024 trapz v13, user16 ;; @0024 v15 = uextend.i64 v12 ;; v67 = iconst.i64 3 ;; v68 = ishl v15, v67 ; v67 = 3 @@ -51,7 +51,7 @@ ;; @0024 v30 = isub v27, v29 ;; @0024 v31 = load.i64 notrap aligned little v30 ;; @002b v38 = icmp ult v4, v12 -;; @002b trapz v38, user17 +;; @002b trapz v38, user16 ;; v86 = ishl v4, v77 ; v77 = 3 ;; @002b v48 = iadd v86, v19 ; v19 = 16 ;; @002b v53 = isub v20, v48 diff --git a/tests/disas/gc/null/multiple-struct-get.wat b/tests/disas/gc/null/multiple-struct-get.wat index 9896429ba224..dce103bd7b49 100644 --- a/tests/disas/gc/null/multiple-struct-get.wat +++ b/tests/disas/gc/null/multiple-struct-get.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0023 trapz v2, user16 +;; @0023 trapz v2, user15 ;; @0023 v20 = load.i64 notrap aligned readonly can_move v0+8 ;; @0023 v6 = load.i64 notrap aligned readonly can_move v20+24 ;; @0023 v5 = uextend.i64 v2 diff --git a/tests/disas/gc/null/ref-cast.wat b/tests/disas/gc/null/ref-cast.wat index 12e19ab58731..ce6c41a8d3f5 100644 --- a/tests/disas/gc/null/ref-cast.wat +++ b/tests/disas/gc/null/ref-cast.wat @@ -57,7 +57,7 @@ ;; @001e jump block4(v23) ;; ;; block4(v24: i32): -;; @001e trapz v24, user19 +;; @001e trapz v24, user18 ;; v25 = load.i32 notrap v36 ;; @0021 jump block1 ;; diff --git a/tests/disas/gc/null/struct-get.wat b/tests/disas/gc/null/struct-get.wat index 87a6dff893d2..ef75daf799e3 100644 --- a/tests/disas/gc/null/struct-get.wat +++ b/tests/disas/gc/null/struct-get.wat @@ -34,7 +34,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0033 trapz v2, user16 +;; @0033 trapz v2, user15 ;; @0033 v10 = load.i64 notrap aligned readonly can_move v0+8 ;; @0033 v5 = load.i64 notrap aligned readonly can_move v10+24 ;; @0033 v4 = uextend.i64 v2 @@ -59,7 +59,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @003c trapz v2, user16 +;; @003c trapz v2, user15 ;; @003c v11 = load.i64 notrap aligned readonly can_move v0+8 ;; @003c v5 = load.i64 notrap aligned readonly can_move v11+24 ;; @003c v4 = uextend.i64 v2 @@ -85,7 +85,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0045 trapz v2, user16 +;; @0045 trapz v2, user15 ;; @0045 v11 = load.i64 notrap aligned readonly can_move v0+8 ;; @0045 v5 = load.i64 notrap aligned readonly can_move v11+24 ;; @0045 v4 = uextend.i64 v2 @@ -111,7 +111,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @004e trapz v2, user16 +;; @004e trapz v2, user15 ;; @004e v10 = load.i64 notrap aligned readonly can_move v0+8 ;; @004e v5 = load.i64 notrap aligned readonly can_move v10+24 ;; @004e v4 = uextend.i64 v2 diff --git a/tests/disas/gc/null/struct-new-default.wat b/tests/disas/gc/null/struct-new-default.wat index 537dbde6d0ba..092c3deda1fc 100644 --- a/tests/disas/gc/null/struct-new-default.wat +++ b/tests/disas/gc/null/struct-new-default.wat @@ -27,11 +27,11 @@ ;; @0021 v11 = load.i64 notrap aligned readonly v0+32 ;; @0021 v12 = load.i32 notrap aligned v11 ;; v49 = iconst.i32 7 -;; @0021 v15 = uadd_overflow_trap v12, v49, user18 ; v49 = 7 +;; @0021 v15 = uadd_overflow_trap v12, v49, user17 ; v49 = 7 ;; v56 = iconst.i32 -8 ;; @0021 v17 = band v15, v56 ; v56 = -8 ;; @0021 v6 = iconst.i32 24 -;; @0021 v18 = uadd_overflow_trap v17, v6, user18 ; v6 = 24 +;; @0021 v18 = uadd_overflow_trap v17, v6, user17 ; v6 = 24 ;; @0021 v41 = load.i64 notrap aligned readonly can_move v0+8 ;; @0021 v20 = load.i64 notrap aligned v41+32 ;; @0021 v19 = uextend.i64 v18 diff --git a/tests/disas/gc/null/struct-new.wat b/tests/disas/gc/null/struct-new.wat index 679780701556..e9f75c07b4d8 100644 --- a/tests/disas/gc/null/struct-new.wat +++ b/tests/disas/gc/null/struct-new.wat @@ -30,11 +30,11 @@ ;; @002a v11 = load.i64 notrap aligned readonly v0+32 ;; @002a v12 = load.i32 notrap aligned v11 ;; v53 = iconst.i32 7 -;; @002a v15 = uadd_overflow_trap v12, v53, user18 ; v53 = 7 +;; @002a v15 = uadd_overflow_trap v12, v53, user17 ; v53 = 7 ;; v60 = iconst.i32 -8 ;; @002a v17 = band v15, v60 ; v60 = -8 ;; @002a v6 = iconst.i32 24 -;; @002a v18 = uadd_overflow_trap v17, v6, user18 ; v6 = 24 +;; @002a v18 = uadd_overflow_trap v17, v6, user17 ; v6 = 24 ;; @002a v43 = load.i64 notrap aligned readonly can_move v0+8 ;; @002a v20 = load.i64 notrap aligned v43+32 ;; @002a v19 = uextend.i64 v18 diff --git a/tests/disas/gc/null/struct-set.wat b/tests/disas/gc/null/struct-set.wat index fc82d6e27d85..f4677896664a 100644 --- a/tests/disas/gc/null/struct-set.wat +++ b/tests/disas/gc/null/struct-set.wat @@ -30,7 +30,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: f32): -;; @0034 trapz v2, user16 +;; @0034 trapz v2, user15 ;; @0034 v9 = load.i64 notrap aligned readonly can_move v0+8 ;; @0034 v5 = load.i64 notrap aligned readonly can_move v9+24 ;; @0034 v4 = uextend.i64 v2 @@ -55,7 +55,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @003f trapz v2, user16 +;; @003f trapz v2, user15 ;; @003f v9 = load.i64 notrap aligned readonly can_move v0+8 ;; @003f v5 = load.i64 notrap aligned readonly can_move v9+24 ;; @003f v4 = uextend.i64 v2 @@ -80,7 +80,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @004a trapz v2, user16 +;; @004a trapz v2, user15 ;; @004a v9 = load.i64 notrap aligned readonly can_move v0+8 ;; @004a v5 = load.i64 notrap aligned readonly can_move v9+24 ;; @004a v4 = uextend.i64 v2 diff --git a/tests/disas/gc/null/v128-fields.wat b/tests/disas/gc/null/v128-fields.wat index 9f08bb73563a..f721d0f21623 100644 --- a/tests/disas/gc/null/v128-fields.wat +++ b/tests/disas/gc/null/v128-fields.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v19 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v5 = load.i64 notrap aligned readonly can_move v19+24 ;; @0022 v4 = uextend.i64 v2 diff --git a/tests/disas/stack-switching/resume-suspend-data-passing.wat b/tests/disas/stack-switching/resume-suspend-data-passing.wat index b24ba2288e9b..95d4d42a7026 100644 --- a/tests/disas/stack-switching/resume-suspend-data-passing.wat +++ b/tests/disas/stack-switching/resume-suspend-data-passing.wat @@ -68,7 +68,7 @@ ;; block4(v11: i64, v12: i64, v52: i32): ;; v73 = iconst.i64 1 ;; v74 = icmp eq v11, v73 ; v73 = 1 -;; @0044 trapnz v74, user22 +;; @0044 trapnz v74, user21 ;; @0044 jump block5 ;; ;; block5: @@ -159,7 +159,7 @@ ;; block0(v0: i64, v1: i64): ;; @0056 v2 = iconst.i32 0 ;; @0056 v4 = call fn0(v0, v2) ; v2 = 0 -;; @0058 trapz v4, user16 +;; @0058 trapz v4, user15 ;; @0058 v8 = call fn1(v0, v4, v2, v2) ; v2 = 0, v2 = 0 ;; @0058 v9 = load.i64 notrap aligned v8+72 ;; @0058 v11 = uextend.i128 v9 @@ -188,13 +188,13 @@ ;; ;; block5: ;; @0062 v18 = ireduce.i64 v16 -;; @0062 trapz v18, user16 +;; @0062 trapz v18, user15 ;; @0062 v21 = load.i64 notrap aligned v18+72 ;; v128 = iconst.i64 64 ;; v129 = ushr.i128 v16, v128 ; v128 = 64 ;; @0062 v20 = ireduce.i64 v129 ;; @0062 v22 = icmp eq v21, v20 -;; @0062 trapz v22, user23 +;; @0062 trapz v22, user22 ;; v130 = iconst.i64 1 ;; v131 = iadd v21, v130 ; v130 = 1 ;; @0062 store notrap aligned v131, v18+72 diff --git a/tests/disas/stack-switching/resume-suspend.wat b/tests/disas/stack-switching/resume-suspend.wat index 1f09b66632f2..2600a0c36a86 100644 --- a/tests/disas/stack-switching/resume-suspend.wat +++ b/tests/disas/stack-switching/resume-suspend.wat @@ -41,7 +41,7 @@ ;; block2(v8: i64, v9: i64): ;; v62 = iconst.i64 1 ;; v63 = icmp eq v8, v62 ; v62 = 1 -;; @003b trapnz v63, user22 +;; @003b trapnz v63, user21 ;; @003b jump block3 ;; ;; block3: @@ -120,7 +120,7 @@ ;; block0(v0: i64, v1: i64): ;; @0043 v7 = iconst.i32 0 ;; @0043 v9 = call fn0(v0, v7) ; v7 = 0 -;; @0045 trapz v9, user16 +;; @0045 trapz v9, user15 ;; @0045 v13 = call fn1(v0, v9, v7, v7) ; v7 = 0, v7 = 0 ;; @0045 v14 = load.i64 notrap aligned v13+72 ;; @004e jump block3 @@ -131,14 +131,14 @@ ;; v134 = ishl v16, v130 ; v130 = 64 ;; v136 = ireduce.i64 v134 ;; v138 = bor v136, v13 -;; @004e trapz v138, user16 +;; @004e trapz v138, user15 ;; @004e v24 = load.i64 notrap aligned v138+72 ;; @0045 v15 = uextend.i128 v13 ;; @0045 v18 = bor v134, v15 ;; v140 = ushr v18, v130 ; v130 = 64 ;; @004e v23 = ireduce.i64 v140 ;; @004e v25 = icmp eq v24, v23 -;; @004e trapz v25, user23 +;; @004e trapz v25, user22 ;; v125 = iconst.i64 1 ;; @004e v26 = iadd v24, v125 ; v125 = 1 ;; @004e store notrap aligned v26, v138+72 diff --git a/tests/disas/stack-switching/symmetric-switch.wat b/tests/disas/stack-switching/symmetric-switch.wat index 666fcd8406ad..8423e68e50a3 100644 --- a/tests/disas/stack-switching/symmetric-switch.wat +++ b/tests/disas/stack-switching/symmetric-switch.wat @@ -40,7 +40,7 @@ ;; block0(v0: i64, v1: i64): ;; @003a v2 = iconst.i32 1 ;; @003a v4 = call fn0(v0, v2) ; v2 = 1 -;; @003c trapz v4, user16 +;; @003c trapz v4, user15 ;; @003c v5 = iconst.i32 1 ;; @003c v6 = iconst.i32 0 ;; @003c v8 = call fn1(v0, v4, v5, v6) ; v5 = 1, v6 = 0 @@ -56,10 +56,10 @@ ;; v137 = uextend.i128 v136 ; v136 = 64 ;; @003e v16 = ushr v13, v137 ;; @003e v17 = ireduce.i64 v16 -;; @003e trapz v15, user16 +;; @003e trapz v15, user15 ;; @003e v18 = load.i64 notrap aligned v15+72 ;; @003e v19 = icmp eq v18, v17 -;; @003e trapz v19, user23 +;; @003e trapz v19, user22 ;; v135 = iconst.i64 1 ;; @003e v20 = iadd v18, v135 ; v135 = 1 ;; @003e store notrap aligned v20, v15+72 @@ -73,7 +73,7 @@ ;; block2(v26: i64, v27: i64): ;; v133 = iconst.i64 1 ;; @003e v28 = icmp eq v26, v133 ; v133 = 1 -;; @003e trapnz v28, user22 +;; @003e trapnz v28, user21 ;; @003e jump block3 ;; ;; block3: @@ -255,7 +255,7 @@ ;; block0(v0: i64, v1: i64): ;; @0047 v2 = iconst.i32 0 ;; @0047 v4 = call fn0(v0, v2) ; v2 = 0 -;; @0049 trapz v4, user16 +;; @0049 trapz v4, user15 ;; @0049 v5 = iconst.i32 0 ;; @0049 v6 = iconst.i32 0 ;; @0049 v8 = call fn1(v0, v4, v5, v6) ; v5 = 0, v6 = 0 @@ -274,10 +274,10 @@ ;; v110 = uextend.i128 v109 ; v109 = 64 ;; @004b v16 = ushr.i128 v13, v110 ;; @004b v17 = ireduce.i64 v16 -;; @004b trapz v15, user16 +;; @004b trapz v15, user15 ;; @004b v18 = load.i64 notrap aligned v15+72 ;; @004b v19 = icmp eq v18, v17 -;; @004b trapz v19, user23 +;; @004b trapz v19, user22 ;; v108 = iconst.i64 1 ;; @004b v20 = iadd v18, v108 ; v108 = 1 ;; @004b store notrap aligned v20, v15+72 diff --git a/tests/disas/typed-funcrefs-eager-init.wat b/tests/disas/typed-funcrefs-eager-init.wat index 94b71da01a39..a2011f17c1d7 100644 --- a/tests/disas/typed-funcrefs-eager-init.wat +++ b/tests/disas/typed-funcrefs-eager-init.wat @@ -140,13 +140,13 @@ ;; v48 = iconst.i64 8 ;; @0048 v14 = iadd v12, v48 ; v48 = 8 ;; @0048 v17 = load.i64 user5 aligned table v14 -;; @004a v18 = load.i64 user16 aligned readonly v17+8 +;; @004a v18 = load.i64 user15 aligned readonly v17+8 ;; @004a v19 = load.i64 notrap aligned readonly v17+24 ;; @004a v20 = call_indirect sig0, v18(v19, v0, v2, v3, v4, v5) ;; v56 = iconst.i64 16 ;; @005b v28 = iadd v12, v56 ; v56 = 16 ;; @005b v31 = load.i64 user5 aligned table v28 -;; @005d v32 = load.i64 user16 aligned readonly v31+8 +;; @005d v32 = load.i64 user15 aligned readonly v31+8 ;; @005d v33 = load.i64 notrap aligned readonly v31+24 ;; @005d v34 = call_indirect sig0, v32(v33, v0, v2, v3, v4, v5) ;; @0066 jump block1 @@ -196,11 +196,11 @@ ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): ;; @009e v9 = load.i64 notrap aligned table v0+64 -;; @00a0 v10 = load.i64 user16 aligned readonly v9+8 +;; @00a0 v10 = load.i64 user15 aligned readonly v9+8 ;; @00a0 v11 = load.i64 notrap aligned readonly v9+24 ;; @00a0 v12 = call_indirect sig0, v10(v11, v0, v2, v3, v4, v5) ;; @00af v15 = load.i64 notrap aligned table v0+80 -;; @00b1 v16 = load.i64 user16 aligned readonly v15+8 +;; @00b1 v16 = load.i64 user15 aligned readonly v15+8 ;; @00b1 v17 = load.i64 notrap aligned readonly v15+24 ;; @00b1 v18 = call_indirect sig0, v16(v17, v0, v2, v3, v4, v5) ;; @00ba jump block1 diff --git a/tests/disas/typed-funcrefs.wat b/tests/disas/typed-funcrefs.wat index 32082555f273..bfed93b39dcd 100644 --- a/tests/disas/typed-funcrefs.wat +++ b/tests/disas/typed-funcrefs.wat @@ -153,7 +153,7 @@ ;; @0048 jump block3(v23) ;; ;; block3(v19: i64): -;; @004a v24 = load.i64 user16 aligned readonly v19+8 +;; @004a v24 = load.i64 user15 aligned readonly v19+8 ;; @004a v25 = load.i64 notrap aligned readonly v19+24 ;; @004a v26 = call_indirect sig1, v24(v25, v0, v2, v3, v4, v5) ;; v76 = iconst.i64 16 @@ -170,7 +170,7 @@ ;; @005b jump block5(v48) ;; ;; block5(v44: i64): -;; @005d v49 = load.i64 user16 aligned readonly v44+8 +;; @005d v49 = load.i64 user15 aligned readonly v44+8 ;; @005d v50 = load.i64 notrap aligned readonly v44+24 ;; @005d v51 = call_indirect sig1, v49(v50, v0, v2, v3, v4, v5) ;; @0066 jump block1 @@ -244,11 +244,11 @@ ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): ;; @009e v9 = load.i64 notrap aligned table v0+64 -;; @00a0 v10 = load.i64 user16 aligned readonly v9+8 +;; @00a0 v10 = load.i64 user15 aligned readonly v9+8 ;; @00a0 v11 = load.i64 notrap aligned readonly v9+24 ;; @00a0 v12 = call_indirect sig0, v10(v11, v0, v2, v3, v4, v5) ;; @00af v15 = load.i64 notrap aligned table v0+80 -;; @00b1 v16 = load.i64 user16 aligned readonly v15+8 +;; @00b1 v16 = load.i64 user15 aligned readonly v15+8 ;; @00b1 v17 = load.i64 notrap aligned readonly v15+24 ;; @00b1 v18 = call_indirect sig0, v16(v17, v0, v2, v3, v4, v5) ;; @00ba jump block1 diff --git a/tests/misc_testsuite/component-model/adapter.wast b/tests/misc_testsuite/component-model/adapter.wast index 0ca70a1dc63e..8432d5841a73 100644 --- a/tests/misc_testsuite/component-model/adapter.wast +++ b/tests/misc_testsuite/component-model/adapter.wast @@ -112,7 +112,7 @@ (with "" (instance (export "" (func $f2)))) )) ) - "degenerate component adapter called") + "cannot enter component instance") ;; fiddling with 0-sized lists (component $c diff --git a/tests/misc_testsuite/component-model/async/backpressure-deadlock.wast b/tests/misc_testsuite/component-model/async/backpressure-deadlock.wast index 5a45f89302a6..06e6df3df447 100644 --- a/tests/misc_testsuite/component-model/async/backpressure-deadlock.wast +++ b/tests/misc_testsuite/component-model/async/backpressure-deadlock.wast @@ -38,60 +38,71 @@ ) (instance $A (instantiate $A)) - (core module $libc (memory (export "mem") 1)) - (core instance $libc (instantiate $libc)) - - (core func $f (canon lower (func $A "f") async (memory $libc "mem"))) - (core func $turn-on-backpressure (canon lower (func $A "turn-on-backpressure"))) - (core func $waitable-set.new (canon waitable-set.new)) - (core func $waitable.join (canon waitable.join)) - (core func $waitable-set.wait (canon waitable-set.wait (memory $libc "mem"))) - - (core module $m - (import "" "f" (func $f (result i32))) - (import "" "turn-on-backpressure" (func $turn-on-backpressure)) - (import "" "waitable-set.new" (func $waitable-set.new (result i32))) - (import "" "waitable.join" (func $waitable.join (param i32 i32))) - (import "" "waitable-set.wait" (func $waitable-set.wait (param i32 i32) (result i32))) - - (func (export "f") - (local $status i32) - (local $set i32) - call $turn-on-backpressure - - (local.set $status (call $f)) - - ;; low 4 bits should be "STARTING == 0" - (i32.ne - (i32.const 0) - (i32.and - (local.get $status) - (i32.const 0xf))) - if unreachable end - - ;; make a new waitable set and join our subtask into it - (local.set $set (call $waitable-set.new)) - (call $waitable.join - (i32.shr_u (local.get $status) (i32.const 4)) - (local.get $set)) - - ;; block waiting for our task, which should deadlock (?) - (call $waitable-set.wait (local.get $set) (i32.const 0)) - unreachable + (component $B + (import "A" (instance $A + (export "f" (func)) + (export "turn-on-backpressure" (func)) + )) + + (core module $libc (memory (export "mem") 1)) + (core instance $libc (instantiate $libc)) + + (core func $f (canon lower (func $A "f") async (memory $libc "mem"))) + (core func $turn-on-backpressure (canon lower (func $A "turn-on-backpressure"))) + (core func $waitable-set.new (canon waitable-set.new)) + (core func $waitable.join (canon waitable.join)) + (core func $waitable-set.wait (canon waitable-set.wait (memory $libc "mem"))) + + (core module $m + (import "" "f" (func $f (result i32))) + (import "" "turn-on-backpressure" (func $turn-on-backpressure)) + (import "" "waitable-set.new" (func $waitable-set.new (result i32))) + (import "" "waitable.join" (func $waitable.join (param i32 i32))) + (import "" "waitable-set.wait" (func $waitable-set.wait (param i32 i32) (result i32))) + + (func (export "f") + (local $status i32) + (local $set i32) + call $turn-on-backpressure + + (local.set $status (call $f)) + + ;; low 4 bits should be "STARTING == 0" + (i32.ne + (i32.const 0) + (i32.and + (local.get $status) + (i32.const 0xf))) + if unreachable end + + ;; make a new waitable set and join our subtask into it + (local.set $set (call $waitable-set.new)) + (call $waitable.join + (i32.shr_u (local.get $status) (i32.const 4)) + (local.get $set)) + + ;; block waiting for our task, which should deadlock (?) + (call $waitable-set.wait (local.get $set) (i32.const 0)) + unreachable + ) ) + + (core instance $i (instantiate $m + (with "" (instance + (export "f" (func $f)) + (export "turn-on-backpressure" (func $turn-on-backpressure)) + (export "waitable-set.new" (func $waitable-set.new)) + (export "waitable.join" (func $waitable.join)) + (export "waitable-set.wait" (func $waitable-set.wait)) + )) + )) + + (func (export "f") async (canon lift (core func $i "f"))) ) - (core instance $i (instantiate $m - (with "" (instance - (export "f" (func $f)) - (export "turn-on-backpressure" (func $turn-on-backpressure)) - (export "waitable-set.new" (func $waitable-set.new)) - (export "waitable.join" (func $waitable.join)) - (export "waitable-set.wait" (func $waitable-set.wait)) - )) - )) + (instance $B (instantiate $B (with "A" (instance $A)))) - (func (export "f") async (canon lift (core func $i "f"))) + (func (export "f") (alias export $B "f")) ) (assert_trap (invoke "f") "deadlock detected") diff --git a/tests/misc_testsuite/component-model/async/future-cancel-write-completed.wast b/tests/misc_testsuite/component-model/async/future-cancel-write-completed.wast index 82a689baaf70..40a15db92fb4 100644 --- a/tests/misc_testsuite/component-model/async/future-cancel-write-completed.wast +++ b/tests/misc_testsuite/component-model/async/future-cancel-write-completed.wast @@ -42,55 +42,64 @@ ) (instance $c (instantiate $c)) - (core func $new (canon future.new $f)) - (core module $libc (memory (export "mem") 1)) - (core instance $libc (instantiate $libc)) - (core func $write (canon future.write $f async (memory $libc "mem"))) - (core func $cancel (canon future.cancel-write $f)) - (core func $drain (canon lower (func $c "f"))) - (core module $m - (import "" "new" (func $new (result i64))) - (import "" "write" (func $write (param i32 i32) (result i32))) - (import "" "cancel" (func $cancel (param i32) (result i32))) - (import "" "drain" (func $drain (param i32))) - - (func (export "f") (result i32) - (local $read i32) - (local $write i32) - (local $new i64) - - (local.set $new (call $new)) - (local.set $read (i32.wrap_i64 (local.get $new))) - (local.set $write (i32.wrap_i64 (i64.shr_u (local.get $new) (i64.const 32)))) - - ;; start a write - local.get $write - i32.const 0 - call $write - i32.const -1 - i32.ne - if unreachable end - - ;; drain the read end - local.get $read - call $drain - - ;; cancel the write, returning the result - local.get $write - call $cancel + (component $d + (import "c" (instance $c + (export "f" (func (param "x" $f))) + )) + + (core func $new (canon future.new $f)) + (core module $libc (memory (export "mem") 1)) + (core instance $libc (instantiate $libc)) + (core func $write (canon future.write $f async (memory $libc "mem"))) + (core func $cancel (canon future.cancel-write $f)) + (core func $drain (canon lower (func $c "f"))) + (core module $m + (import "" "new" (func $new (result i64))) + (import "" "write" (func $write (param i32 i32) (result i32))) + (import "" "cancel" (func $cancel (param i32) (result i32))) + (import "" "drain" (func $drain (param i32))) + + (func (export "f") (result i32) + (local $read i32) + (local $write i32) + (local $new i64) + + (local.set $new (call $new)) + (local.set $read (i32.wrap_i64 (local.get $new))) + (local.set $write (i32.wrap_i64 (i64.shr_u (local.get $new) (i64.const 32)))) + + ;; start a write + local.get $write + i32.const 0 + call $write + i32.const -1 + i32.ne + if unreachable end + + ;; drain the read end + local.get $read + call $drain + + ;; cancel the write, returning the result + local.get $write + call $cancel + ) ) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "new" (func $new)) - (export "write" (func $write)) - (export "cancel" (func $cancel)) - (export "drain" (func $drain)) + (core instance $i (instantiate $m + (with "" (instance + (export "new" (func $new)) + (export "write" (func $write)) + (export "cancel" (func $cancel)) + (export "drain" (func $drain)) + )) )) - )) - (func (export "f") async (result u32) (canon lift (core func $i "f"))) + (func (export "f") async (result u32) (canon lift (core func $i "f"))) + ) + (instance $d (instantiate $d (with "c" (instance $c)))) + + (func (export "f") (alias export $d "f")) ) (assert_return (invoke "f") (u32.const 0)) diff --git a/tests/misc_testsuite/component-model/async/future-read.wast b/tests/misc_testsuite/component-model/async/future-read.wast index ec80f85796b7..523dfb3f2c3a 100644 --- a/tests/misc_testsuite/component-model/async/future-read.wast +++ b/tests/misc_testsuite/component-model/async/future-read.wast @@ -30,27 +30,35 @@ ) (instance $child (instantiate $child)) - (type $future (future)) - (core func $new (canon future.new $future)) - (core func $child-run (canon lower (func $child "run"))) - - (core module $m - (import "" "new" (func $new (result i64))) - (import "" "child-run" (func $child-run (param i32))) - - (func (export "run") - (call $child-run (i32.wrap_i64 (call $new))) + (component $other-child + (type $future (future)) + (import "child" (instance $child + (export "run" (func async (param "x" $future))) + )) + + (core func $new (canon future.new $future)) + (core func $child-run (canon lower (func $child "run"))) + (core module $m + (import "" "new" (func $new (result i64))) + (import "" "child-run" (func $child-run (param i32))) + + (func (export "run") + (call $child-run (i32.wrap_i64 (call $new))) + ) ) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "new" (func $new)) - (export "child-run" (func $child-run)) + (core instance $i (instantiate $m + (with "" (instance + (export "new" (func $new)) + (export "child-run" (func $child-run)) + )) )) - )) + + (func (export "run") async + (canon lift (core func $i "run"))) + ) + (instance $other-child (instantiate $other-child (with "child" (instance $child)))) - (func (export "run") async - (canon lift (core func $i "run"))) + (func (export "run") (alias export $other-child "run")) ) ;; We expect deadlock since the write end is leaked: @@ -83,27 +91,35 @@ ) (instance $child (instantiate $child)) - (type $future (future)) - (core func $new (canon future.new $future)) - (core func $child-run (canon lower (func $child "run"))) - - (core module $m - (import "" "new" (func $new (result i64))) - (import "" "child-run" (func $child-run (param i32))) - - (func (export "run") - (call $child-run (i32.wrap_i64 (call $new))) + (component $other-child + (type $future (future)) + (import "child" (instance $child + (export "run" (func (param "x" $future))) + )) + (core func $new (canon future.new $future)) + (core func $child-run (canon lower (func $child "run"))) + + (core module $m + (import "" "new" (func $new (result i64))) + (import "" "child-run" (func $child-run (param i32))) + + (func (export "run") + (call $child-run (i32.wrap_i64 (call $new))) + ) ) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "new" (func $new)) - (export "child-run" (func $child-run)) + (core instance $i (instantiate $m + (with "" (instance + (export "new" (func $new)) + (export "child-run" (func $child-run)) + )) )) - )) + + (func (export "run") + (canon lift (core func $i "run"))) + ) + (instance $other-child (instantiate $other-child (with "child" (instance $child)))) - (func (export "run") - (canon lift (core func $i "run"))) + (func (export "run") (alias export $other-child "run")) ) (assert_return (invoke "run")) @@ -139,27 +155,35 @@ ) (instance $child (instantiate $child)) - (type $future (future)) - (core func $new (canon future.new $future)) - (core func $child-run (canon lower (func $child "run"))) - - (core module $m - (import "" "new" (func $new (result i64))) - (import "" "child-run" (func $child-run (param i32))) - - (func (export "run") - (call $child-run (i32.wrap_i64 (call $new))) + (component $other-child + (type $future (future)) + (import "child" (instance $child + (export "run" (func async (param "x" $future))) + )) + (core func $new (canon future.new $future)) + (core func $child-run (canon lower (func $child "run"))) + + (core module $m + (import "" "new" (func $new (result i64))) + (import "" "child-run" (func $child-run (param i32))) + + (func (export "run") + (call $child-run (i32.wrap_i64 (call $new))) + ) ) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "new" (func $new)) - (export "child-run" (func $child-run)) + (core instance $i (instantiate $m + (with "" (instance + (export "new" (func $new)) + (export "child-run" (func $child-run)) + )) )) - )) + + (func (export "run") async + (canon lift (core func $i "run"))) + ) + (instance $other-child (instantiate $other-child (with "child" (instance $child)))) - (func (export "run") async - (canon lift (core func $i "run"))) + (func (export "run") (alias export $other-child "run")) ) ;; We expect deadlock since the write end is leaked: @@ -200,27 +224,35 @@ ) (instance $child (instantiate $child)) - (type $future (future)) - (core func $new (canon future.new $future)) - (core func $child-run (canon lower (func $child "run"))) - - (core module $m - (import "" "new" (func $new (result i64))) - (import "" "child-run" (func $child-run (param i32))) - - (func (export "run") - (call $child-run (i32.wrap_i64 (call $new))) + (component $other-child + (type $future (future)) + (import "child" (instance $child + (export "run" (func (param "x" $future))) + )) + (core func $new (canon future.new $future)) + (core func $child-run (canon lower (func $child "run"))) + + (core module $m + (import "" "new" (func $new (result i64))) + (import "" "child-run" (func $child-run (param i32))) + + (func (export "run") + (call $child-run (i32.wrap_i64 (call $new))) + ) ) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "new" (func $new)) - (export "child-run" (func $child-run)) + (core instance $i (instantiate $m + (with "" (instance + (export "new" (func $new)) + (export "child-run" (func $child-run)) + )) )) - )) + + (func (export "run") async + (canon lift (core func $i "run"))) + ) + (instance $other-child (instantiate $other-child (with "child" (instance $child)))) - (func (export "run") async - (canon lift (core func $i "run"))) + (func (export "run") (alias export $other-child "run")) ) (assert_return (invoke "run")) diff --git a/tests/misc_testsuite/component-model/async/reenter-during-yield.wast b/tests/misc_testsuite/component-model/async/reenter-during-yield.wast new file mode 100644 index 000000000000..61fcb12ae107 --- /dev/null +++ b/tests/misc_testsuite/component-model/async/reenter-during-yield.wast @@ -0,0 +1,82 @@ +;;! component_model_async = true +;;! reference_types = true +;;! gc_types = true +;;! multi_memory = true + +(component + (component $a + (core module $a + (import "" "yield" (func $yield (result i32))) + + (func (export "yield-loop") (result i32) + ;; simulate `waitable-set.poll` with a yield loop + (loop + call $yield + drop + br 0 + ) + unreachable + ) + + ;; not reached + (func (export "callback") (param i32 i32 i32) (result i32) unreachable) + + (func (export "noop")) + ) + (core func $yield (canon thread.yield)) + (core instance $a (instantiate $a + (with "" (instance + (export "yield" (func $yield)) + )) + )) + (func (export "yield-loop") async + (canon lift + (core func $a "yield-loop") + async + (callback (func $a "callback")) + ) + ) + (func (export "noop") (canon lift (core func $a "noop"))) + ) + (instance $a (instantiate $a)) + + (component $b + (import "yield-loop" (func $yield-loop async)) + (import "noop" (func $noop)) + + (core func $yield-loop (canon lower (func $yield-loop) async)) + (core func $noop (canon lower (func $noop))) + + (core module $b + (import "" "yield-loop" (func $yield-loop (result i32))) + (import "" "noop" (func $noop)) + + (func (export "run") + ;; call `yield-loop`, double-check it's in the "started" state. + call $yield-loop + i32.const 0xf + i32.and + i32.const 1 + i32.ne + if unreachable end + + ;; now try to reenter the other component with some other function. + call $noop + ) + ) + (core instance $b (instantiate $b + (with "" (instance + (export "yield-loop" (func $yield-loop)) + (export "noop" (func $noop)) + )) + )) + (func (export "run") async (canon lift (core func $b "run"))) + ) + (instance $b (instantiate $b + (with "yield-loop" (func $a "yield-loop")) + (with "noop" (func $a "noop")) + )) + (export "run" (func $b "run")) +) + +(assert_return (invoke "run")) diff --git a/tests/misc_testsuite/component-model/async/wait-forever.wast b/tests/misc_testsuite/component-model/async/wait-forever.wast index 7f73f2ee995f..718fd3142d77 100644 --- a/tests/misc_testsuite/component-model/async/wait-forever.wast +++ b/tests/misc_testsuite/component-model/async/wait-forever.wast @@ -35,22 +35,30 @@ ) (instance $child (instantiate $child)) - (core func $child-run (canon lower (func $child "run"))) - - (core module $m - (import "" "child-run" (func $child-run)) - - (func (export "run") - (call $child-run)) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "child-run" (func $child-run)) + (component $other-child + (import "child" (instance $child + (export "run" (func async)) )) - )) + + (core func $child-run (canon lower (func $child "run"))) + (core module $m + (import "" "child-run" (func $child-run)) + + (func (export "run") + (call $child-run)) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "child-run" (func $child-run)) + )) + )) + + (func (export "run") async + (canon lift (core func $i "run"))) + ) + (instance $other-child (instantiate $other-child (with "child" (instance $child)))) - (func (export "run") async - (canon lift (core func $i "run"))) + (func (export "run") (alias export $other-child "run")) ) (assert_trap (invoke "run") "deadlock detected")