Skip to content

Commit

Permalink
add component-model-async/lift.wast test
Browse files Browse the repository at this point in the history
This is another piece of #9582 which I'm splitting out to make review easier.

This test includes two components: one which exports a function using the
async-with-callback ABI, and another which uses the async-without-callback ABI.
It doesn't actually instantiate or run either component yet.

The rest of the changes fill in some TODOs to make the test pass.

Signed-off-by: Joel Dice <[email protected]>
  • Loading branch information
dicej committed Jan 24, 2025
1 parent 3948f66 commit 0eae83f
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 5 deletions.
3 changes: 3 additions & 0 deletions crates/fuzzing/src/generators/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ impl Config {
extended_const,
wide_arithmetic,
component_model_more_flags,
component_model_async,
simd,

hogs_memory: _,
Expand All @@ -151,6 +152,7 @@ impl Config {
self.module_config.function_references_enabled =
function_references.or(gc).unwrap_or(false);
self.module_config.component_model_more_flags = component_model_more_flags.unwrap_or(false);
self.module_config.component_model_async = component_model_async.unwrap_or(false);

// Enable/disable proposals that wasm-smith has knobs for which will be
// read when creating `wasmtime::Config`.
Expand Down Expand Up @@ -266,6 +268,7 @@ impl Config {
.wasm_wide_arithmetic(self.module_config.config.wide_arithmetic_enabled)
.wasm_extended_const(self.module_config.config.extended_const_enabled)
.wasm_component_model_more_flags(self.module_config.component_model_more_flags)
.wasm_component_model_async(self.module_config.component_model_async)
.native_unwind_info(cfg!(target_os = "windows") || self.wasmtime.native_unwind_info)
.cranelift_nan_canonicalization(self.wasmtime.canonicalize_nans)
.cranelift_opt_level(self.wasmtime.opt_level.to_wasmtime())
Expand Down
2 changes: 2 additions & 0 deletions crates/fuzzing/src/generators/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub struct ModuleConfig {
// config-to-`wasmtime::Config` translation.
pub function_references_enabled: bool,
pub component_model_more_flags: bool,
pub component_model_async: bool,
}

impl<'a> Arbitrary<'a> for ModuleConfig {
Expand Down Expand Up @@ -62,6 +63,7 @@ impl<'a> Arbitrary<'a> for ModuleConfig {

Ok(ModuleConfig {
component_model_more_flags: false,
component_model_async: false,
function_references_enabled: config.gc_enabled,
config,
})
Expand Down
2 changes: 1 addition & 1 deletion crates/misc/component-test-util/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ publish = false
env_logger = { workspace = true }
anyhow = { workspace = true }
arbitrary = { workspace = true, features = ["derive"] }
wasmtime = { workspace = true, features = ["component-model", "async"] }
wasmtime = { workspace = true, features = ["component-model", "async", "component-model-async"] }
wasmtime-environ = { workspace = true }
wasmtime-wast-util = { path = '../../wast-util' }
target-lexicon = { workspace = true }
3 changes: 3 additions & 0 deletions crates/misc/component-test-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ pub fn apply_test_config(config: &mut Config, test_config: &wasmtime_wast_util::
extended_const,
wide_arithmetic,
component_model_more_flags,
component_model_async,
nan_canonicalization,
simd,

Expand All @@ -184,6 +185,7 @@ pub fn apply_test_config(config: &mut Config, test_config: &wasmtime_wast_util::
let extended_const = extended_const.unwrap_or(false);
let wide_arithmetic = wide_arithmetic.unwrap_or(false);
let component_model_more_flags = component_model_more_flags.unwrap_or(false);
let component_model_async = component_model_async.unwrap_or(false);
let nan_canonicalization = nan_canonicalization.unwrap_or(false);
let relaxed_simd = relaxed_simd.unwrap_or(false);

Expand All @@ -210,5 +212,6 @@ pub fn apply_test_config(config: &mut Config, test_config: &wasmtime_wast_util::
.wasm_extended_const(extended_const)
.wasm_wide_arithmetic(wide_arithmetic)
.wasm_component_model_more_flags(component_model_more_flags)
.wasm_component_model_async(component_model_async)
.cranelift_nan_canonicalization(nan_canonicalization);
}
13 changes: 13 additions & 0 deletions crates/wasmtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,19 @@ impl Config {
self
}

/// Configures whether components support the async ABI [proposal] for
/// lifting and lowering functions, as well as `stream`, `future`, and
/// `error-context` types.
///
/// Please note that Wasmtime's support for this feature is _very_ incomplete.
///
/// [proposal]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md
#[cfg(feature = "component-model-async")]
pub fn wasm_component_model_async(&mut self, enable: bool) -> &mut Self {
self.wasm_feature(WasmFeatures::COMPONENT_MODEL_ASYNC, enable);
self
}

/// Configures which compilation strategy will be used for wasm modules.
///
/// This method can be used to configure which compiler is used for wasm
Expand Down
9 changes: 8 additions & 1 deletion crates/wasmtime/src/engine/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ struct WasmFeatures {
custom_page_sizes: bool,
component_model_more_flags: bool,
component_model_multiple_returns: bool,
component_model_async: bool,
gc_types: bool,
wide_arithmetic: bool,
}
Expand Down Expand Up @@ -253,7 +254,6 @@ impl Metadata<'_> {
assert!(!shared_everything_threads);
assert!(!legacy_exceptions);
assert!(!stack_switching);
assert!(!component_model_async);

Metadata {
target: engine.compiler().triple().to_string(),
Expand All @@ -278,6 +278,7 @@ impl Metadata<'_> {
custom_page_sizes,
component_model_more_flags,
component_model_multiple_returns,
component_model_async,
gc_types,
wide_arithmetic,
},
Expand Down Expand Up @@ -488,6 +489,7 @@ impl Metadata<'_> {
custom_page_sizes,
component_model_more_flags,
component_model_multiple_returns,
component_model_async,
gc_types,
wide_arithmetic,
} = self.features;
Expand Down Expand Up @@ -574,6 +576,11 @@ impl Metadata<'_> {
other.contains(F::COMPONENT_MODEL_MULTIPLE_RETURNS),
"WebAssembly component model support for multiple returns",
)?;
Self::check_bool(
component_model_async,
other.contains(F::COMPONENT_MODEL_ASYNC),
"WebAssembly component model support for async lifts/lowers, futures, streams, and errors",
)?;
Self::check_cfg_bool(
cfg!(feature = "gc"),
"gc",
Expand Down
13 changes: 11 additions & 2 deletions crates/wasmtime/src/runtime/component/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,8 +608,7 @@ impl<'a> Instantiator<'a> {
}

GlobalInitializer::ExtractCallback(callback) => {
_ = callback;
todo!()
self.extract_callback(store.0, callback)
}

GlobalInitializer::ExtractPostReturn(post_return) => {
Expand Down Expand Up @@ -659,6 +658,16 @@ impl<'a> Instantiator<'a> {
self.data.state.set_runtime_realloc(realloc.index, func_ref);
}

fn extract_callback(&mut self, store: &mut StoreOpaque, callback: &ExtractCallback) {
let func_ref = match self.data.lookup_def(store, &callback.def) {
crate::runtime::vm::Export::Function(f) => f.func_ref,
_ => unreachable!(),
};
self.data
.state
.set_runtime_callback(callback.index, func_ref);
}

fn extract_post_return(&mut self, store: &mut StoreOpaque, post_return: &ExtractPostReturn) {
let func_ref = match self.data.lookup_def(store, &post_return.def) {
crate::runtime::vm::Export::Function(f) => f.func_ref,
Expand Down
19 changes: 19 additions & 0 deletions crates/wasmtime/src/runtime/vm/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,15 @@ impl ComponentInstance {
}
}

/// Same as `set_runtime_memory` but for async callback function pointers.
pub fn set_runtime_callback(&mut self, idx: RuntimeCallbackIndex, ptr: NonNull<VMFuncRef>) {
unsafe {
let storage = self.vmctx_plus_offset_mut(self.offsets.runtime_callback(idx));
debug_assert!(*storage as usize == INVALID_PTR);
*storage = ptr.as_ptr();
}
}

/// Same as `set_runtime_memory` but for post-return function pointers.
pub fn set_runtime_post_return(
&mut self,
Expand Down Expand Up @@ -493,6 +502,11 @@ impl ComponentInstance {
let offset = self.offsets.runtime_realloc(i);
*self.vmctx_plus_offset_mut(offset) = INVALID_PTR;
}
for i in 0..self.offsets.num_runtime_callbacks {
let i = RuntimeCallbackIndex::from_u32(i);
let offset = self.offsets.runtime_callback(i);
*self.vmctx_plus_offset_mut(offset) = INVALID_PTR;
}
for i in 0..self.offsets.num_runtime_post_returns {
let i = RuntimePostReturnIndex::from_u32(i);
let offset = self.offsets.runtime_post_return(i);
Expand Down Expand Up @@ -734,6 +748,11 @@ impl OwnedComponentInstance {
unsafe { self.instance_mut().set_runtime_realloc(idx, ptr) }
}

/// See `ComponentInstance::set_runtime_callback`
pub fn set_runtime_callback(&mut self, idx: RuntimeCallbackIndex, ptr: NonNull<VMFuncRef>) {
unsafe { self.instance_mut().set_runtime_callback(idx, ptr) }
}

/// See `ComponentInstance::set_runtime_post_return`
pub fn set_runtime_post_return(
&mut self,
Expand Down
1 change: 1 addition & 0 deletions crates/wast-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ macro_rules! foreach_config_option {
hogs_memory
nan_canonicalization
component_model_more_flags
component_model_async
simd
gc_types
}
Expand Down
2 changes: 1 addition & 1 deletion crates/wast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ wast = { workspace = true }
log = { workspace = true }

[features]
component-model = ['wasmtime/component-model']
component-model = ['wasmtime/component-model', 'wasmtime/component-model-async']
26 changes: 26 additions & 0 deletions tests/misc_testsuite/component-model-async/lift.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
;;! component_model_async = true

;; async lift; no callback
(component
(core module $m
(func (export "foo") (param i32) unreachable)
)
(core instance $i (instantiate $m))

(func (export "foo") (param "p1" u32) (result u32)
(canon lift (core func $i "foo") async)
)
)

;; async lift; with callback
(component
(core module $m
(func (export "callback") (param i32 i32 i32 i32) (result i32) unreachable)
(func (export "foo") (param i32) (result i32) unreachable)
)
(core instance $i (instantiate $m))

(func (export "foo") (param "p1" u32) (result u32)
(canon lift (core func $i "foo") async (callback (func $i "callback")))
)
)

0 comments on commit 0eae83f

Please sign in to comment.