diff --git a/crates/wit-component/src/dummy.rs b/crates/wit-component/src/dummy.rs index e0ace3b1b4..f32e51b79a 100644 --- a/crates/wit-component/src/dummy.rs +++ b/crates/wit-component/src/dummy.rs @@ -1,3 +1,4 @@ +use crate::validation::IndexType; use wit_parser::abi::WasmType; use wit_parser::{ Function, FutureIntrinsic, LiftLowerAbi, ManglingAndAbi, Resolve, ResourceIntrinsic, @@ -6,18 +7,42 @@ use wit_parser::{ }; /// Generate a dummy implementation core Wasm module for a given WIT document -pub fn dummy_module(resolve: &Resolve, world_id: WorldId, mangling: ManglingAndAbi) -> Vec { +/// +/// The `index_type` argument is the index type of the generated module's +/// linear memory. +pub fn dummy_module( + resolve: &Resolve, + world_id: WorldId, + mangling: ManglingAndAbi, + index_type: IndexType, +) -> Vec { + let ptr = index_type; + + // Usage of `resolve.wasm_signature` requires a world with nominal type IDs + // to correctly handle the `rep` of `borrow`, so ensure that's done here. + let mut resolve = resolve.clone(); + resolve.generate_nominal_type_ids(world_id); + let resolve = &resolve; + let world = &resolve.worlds[world_id]; let mut wat = String::new(); wat.push_str("(module\n"); for (name, import) in world.imports.iter() { match import { WorldItem::Function(func) => { - push_imported_func(&mut wat, resolve, world_id, None, func, mangling); + push_imported_func(&mut wat, resolve, world_id, None, func, mangling, ptr); } WorldItem::Interface { id: import, .. } => { for (_, func) in resolve.interfaces[*import].functions.iter() { - push_imported_func(&mut wat, resolve, world_id, Some(name), func, mangling); + push_imported_func( + &mut wat, + resolve, + world_id, + Some(name), + func, + mangling, + ptr, + ); } for (_, ty) in resolve.interfaces[*import].types.iter() { push_imported_type_intrinsics(&mut wat, resolve, Some(name), *ty, mangling); @@ -30,7 +55,7 @@ pub fn dummy_module(resolve: &Resolve, world_id: WorldId, mangling: ManglingAndA } if mangling.is_async() { - push_root_async_intrinsics(&mut wat); + push_root_async_intrinsics(&mut wat, ptr); } // Append any intrinsics which are imported but used in exported items @@ -38,7 +63,9 @@ pub fn dummy_module(resolve: &Resolve, world_id: WorldId, mangling: ManglingAndA for (name, export) in world.exports.iter() { match export { WorldItem::Function(func) => { - push_exported_func_intrinsics(&mut wat, resolve, world_id, None, func, mangling); + push_exported_func_intrinsics( + &mut wat, resolve, world_id, None, func, mangling, ptr, + ); } WorldItem::Interface { id: export, .. } => { for (_, func) in resolve.interfaces[*export].functions.iter() { @@ -49,10 +76,18 @@ pub fn dummy_module(resolve: &Resolve, world_id: WorldId, mangling: ManglingAndA Some(name), func, mangling, + ptr, ); } for (_, ty) in resolve.interfaces[*export].types.iter() { - push_exported_type_intrinsics(&mut wat, resolve, Some(name), *ty, mangling); + push_exported_type_intrinsics( + &mut wat, + resolve, + Some(name), + *ty, + mangling, + ptr, + ); } } WorldItem::Type { .. } => {} @@ -62,14 +97,14 @@ pub fn dummy_module(resolve: &Resolve, world_id: WorldId, mangling: ManglingAndA for (name, export) in world.exports.iter() { match export { WorldItem::Function(func) => { - push_func_export(&mut wat, resolve, world_id, None, func, mangling); + push_func_export(&mut wat, resolve, world_id, None, func, mangling, ptr); } WorldItem::Interface { id: export, .. } => { for (_, func) in resolve.interfaces[*export].functions.iter() { - push_func_export(&mut wat, resolve, world_id, Some(name), func, mangling); + push_func_export(&mut wat, resolve, world_id, Some(name), func, mangling, ptr); } for (_, ty) in resolve.interfaces[*export].types.iter() { - push_exported_resource_functions(&mut wat, resolve, name, *ty, mangling); + push_exported_resource_functions(&mut wat, resolve, name, *ty, mangling, ptr); } } WorldItem::Type { .. } => {} @@ -77,10 +112,10 @@ pub fn dummy_module(resolve: &Resolve, world_id: WorldId, mangling: ManglingAndA } let memory = resolve.wasm_export_name(mangling, WasmExport::Memory); - wat.push_str(&format!("(memory (export {memory:?}) 0)\n")); + wat.push_str(&format!("(memory (export {memory:?}) {ptr} 0)\n")); let realloc = resolve.wasm_export_name(mangling, WasmExport::Realloc); wat.push_str(&format!( - "(func (export {realloc:?}) (param i32 i32 i32 i32) (result i32) unreachable)\n" + "(func (export {realloc:?}) (param {ptr} {ptr} {ptr} {ptr}) (result {ptr}) unreachable)\n" )); let initialize = resolve.wasm_export_name(mangling, WasmExport::Initialize); @@ -97,18 +132,21 @@ fn push_imported_func( interface: Option<&WorldKey>, func: &Function, mangling: ManglingAndAbi, + ptr: IndexType, ) { let mangling = mangling.for_func(func); let sig = resolve.wasm_signature(world, mangling.import_variant(), func); let (module, name) = resolve.wasm_import_name(mangling, WasmImport::Func { interface, func }); wat.push_str(&format!("(import {module:?} {name:?} (func")); - push_tys(wat, "param", &sig.params); - push_tys(wat, "result", &sig.results); + push_tys(wat, "param", &sig.params, ptr); + push_tys(wat, "result", &sig.results, ptr); wat.push_str("))\n"); if mangling.is_async() { - push_imported_future_and_stream_intrinsics(wat, resolve, mangling, false, interface, func); + push_imported_future_and_stream_intrinsics( + wat, resolve, mangling, false, interface, func, ptr, + ); } } @@ -155,6 +193,7 @@ fn push_exported_func_intrinsics( interface: Option<&WorldKey>, func: &Function, mangling: ManglingAndAbi, + ptr: IndexType, ) { if !mangling.is_async() { return; @@ -164,11 +203,11 @@ fn push_exported_func_intrinsics( let (module, name, sig) = func.task_return_import(resolve, world, interface, mangling.mangling()); wat.push_str(&format!("(import {module:?} {name:?} (func")); - push_tys(wat, "param", &sig.params); - push_tys(wat, "result", &sig.results); + push_tys(wat, "param", &sig.params, ptr); + push_tys(wat, "result", &sig.results, ptr); wat.push_str("))\n"); - push_imported_future_and_stream_intrinsics(wat, resolve, mangling, true, interface, func); + push_imported_future_and_stream_intrinsics(wat, resolve, mangling, true, interface, func, ptr); } fn push_imported_future_and_stream_intrinsics( @@ -178,6 +217,7 @@ fn push_imported_future_and_stream_intrinsics( exported: bool, interface: Option<&WorldKey>, func: &Function, + ptr: IndexType, ) { for id in func.find_futures_and_streams(resolve).into_iter() { match &resolve.types[id].kind { @@ -225,12 +265,12 @@ fn push_imported_future_and_stream_intrinsics( (import {module:?} {drop_readable:?} (func (param i32))) (import {module:?} {drop_writable:?} (func (param i32))) (import {module:?} {forward:?} (func (param i32 i32))) -(import {module:?} {async_read:?} (func (param i32 i32) (result i32))) -(import {module:?} {async_write:?} (func (param i32 i32) (result i32))) +(import {module:?} {async_read:?} (func (param i32 {ptr}) (result i32))) +(import {module:?} {async_write:?} (func (param i32 {ptr}) (result i32))) ;; deferred behind ๐Ÿš -;;(import {module:?} {read:?} (func (param i32 i32) (result i32))) -;;(import {module:?} {write:?} (func (param i32 i32) (result i32))) +;;(import {module:?} {read:?} (func (param i32 {ptr}) (result i32))) +;;(import {module:?} {write:?} (func (param i32 {ptr}) (result i32))) ;;(import {module:?} {async_cancel_read:?} (func (param i32) (result i32))) ;;(import {module:?} {async_cancel_write:?} (func (param i32) (result i32))) "# @@ -280,12 +320,12 @@ fn push_imported_future_and_stream_intrinsics( (import {module:?} {drop_readable:?} (func (param i32))) (import {module:?} {drop_writable:?} (func (param i32))) (import {module:?} {forward:?} (func (param i32 i32))) -(import {module:?} {async_read:?} (func (param i32 i32 i32) (result i32))) -(import {module:?} {async_write:?} (func (param i32 i32 i32) (result i32))) +(import {module:?} {async_read:?} (func (param i32 {ptr} {ptr}) (result {ptr}))) +(import {module:?} {async_write:?} (func (param i32 {ptr} {ptr}) (result {ptr}))) ;; deferred behind ๐Ÿš -;;(import {module:?} {read:?} (func (param i32 i32 i32) (result i32))) -;;(import {module:?} {write:?} (func (param i32 i32 i32) (result i32))) +;;(import {module:?} {read:?} (func (param i32 {ptr} {ptr}) (result {ptr}))) +;;(import {module:?} {write:?} (func (param i32 {ptr} {ptr}) (result {ptr}))) ;;(import {module:?} {async_cancel_read:?} (func (param i32) (result i32))) ;;(import {module:?} {async_cancel_write:?} (func (param i32) (result i32))) "# @@ -302,19 +342,23 @@ fn push_exported_type_intrinsics( interface: Option<&WorldKey>, resource: TypeId, mangling: ManglingAndAbi, + ptr: IndexType, ) { let ty = &resolve.types[resource]; match ty.kind { TypeDefKind::Resource => { let intrinsics = [ - (ResourceIntrinsic::ExportedDrop, "(func (param i32))"), + ( + ResourceIntrinsic::ExportedDrop, + "(func (param i32))".to_string(), + ), ( ResourceIntrinsic::ExportedNew, - "(func (param i32) (result i32))", + format!("(func (param {ptr}) (result i32))"), ), ( ResourceIntrinsic::ExportedRep, - "(func (param i32) (result i32))", + format!("(func (param i32) (result {ptr}))"), ), ]; for (intrinsic, sig) in intrinsics { @@ -342,6 +386,7 @@ fn push_exported_resource_functions( interface: &WorldKey, resource: TypeId, mangling: ManglingAndAbi, + ptr: IndexType, ) { let ty = &resolve.types[resource]; match ty.kind { @@ -357,7 +402,7 @@ fn push_exported_resource_functions( resource, }, ); - wat.push_str(&format!("(func (export {name:?}) (param i32))")); + wat.push_str(&format!("(func (export {name:?}) (param {ptr}))")); } fn push_func_export( @@ -367,6 +412,7 @@ fn push_func_export( interface: Option<&WorldKey>, func: &Function, mangling: ManglingAndAbi, + ptr: IndexType, ) { let mangling = mangling.for_func(func); let sig = resolve.wasm_signature(world, mangling.export_variant(), func); @@ -379,8 +425,8 @@ fn push_func_export( }, ); wat.push_str(&format!("(func (export \"{name}\")")); - push_tys(wat, "param", &sig.params); - push_tys(wat, "result", &sig.results); + push_tys(wat, "param", &sig.params, ptr); + push_tys(wat, "result", &sig.results, ptr); wat.push_str(" unreachable)\n"); match mangling { @@ -394,7 +440,7 @@ fn push_func_export( }, ); wat.push_str(&format!("(func (export \"{name}\")")); - push_tys(wat, "param", &sig.results); + push_tys(wat, "param", &sig.results, ptr); wat.push_str(")\n"); } ManglingAndAbi::Legacy(LiftLowerAbi::AsyncCallback) => { @@ -414,7 +460,7 @@ fn push_func_export( } } -fn push_tys(dst: &mut String, desc: &str, params: &[WasmType]) { +fn push_tys(dst: &mut String, desc: &str, params: &[WasmType], ptr: IndexType) { if params.is_empty() { return; } @@ -427,46 +473,45 @@ fn push_tys(dst: &mut String, desc: &str, params: &[WasmType]) { WasmType::I64 => dst.push_str("i64"), WasmType::F32 => dst.push_str("f32"), WasmType::F64 => dst.push_str("f64"), - WasmType::Pointer => dst.push_str("i32"), + WasmType::Pointer | WasmType::Length => dst.push_str(&ptr.to_string()), WasmType::PointerOrI64 => dst.push_str("i64"), - WasmType::Length => dst.push_str("i32"), } } dst.push(')'); } -fn push_root_async_intrinsics(dst: &mut String) { - dst.push_str( +fn push_root_async_intrinsics(dst: &mut String, ptr: IndexType) { + dst.push_str(&format!( r#" (import "[export]$root" "[task-cancel]" (func)) (import "$root" "[backpressure-inc]" (func)) (import "$root" "[backpressure-dec]" (func)) (import "$root" "[waitable-set-new]" (func (result i32))) -(import "$root" "[waitable-set-wait]" (func (param i32 i32) (result i32))) -(import "$root" "[waitable-set-poll]" (func (param i32 i32) (result i32))) +(import "$root" "[waitable-set-wait]" (func (param i32 {ptr}) (result i32))) +(import "$root" "[waitable-set-poll]" (func (param i32 {ptr}) (result i32))) (import "$root" "[waitable-set-drop]" (func (param i32))) (import "$root" "[waitable-join]" (func (param i32 i32))) (import "$root" "[thread-yield]" (func (result i32))) (import "$root" "[subtask-drop]" (func (param i32))) (import "$root" "[subtask-cancel]" (func (param i32) (result i32))) -(import "$root" "[context-get-0]" (func (result i32))) -(import "$root" "[context-set-0]" (func (param i32))) +(import "$root" "[context-get-0]" (func (result {ptr}))) +(import "$root" "[context-set-0]" (func (param {ptr}))) ;; deferred behind ๐Ÿงต upstream -;;(import "$root" "[cancellable][waitable-set-wait]" (func (param i32 i32) (result i32))) -;;(import "$root" "[cancellable][waitable-set-poll]" (func (param i32 i32) (result i32))) +;;(import "$root" "[cancellable][waitable-set-wait]" (func (param i32 {ptr}) (result i32))) +;;(import "$root" "[cancellable][waitable-set-poll]" (func (param i32 {ptr}) (result i32))) ;;(import "$root" "[cancellable][thread-yield]" (func (result i32))) -;;(import "$root" "[context-get-1]" (func (result i32))) -;;(import "$root" "[context-set-1]" (func (param i32))) +;;(import "$root" "[context-get-1]" (func (result {ptr}))) +;;(import "$root" "[context-set-1]" (func (param {ptr}))) ;; deferred behind ๐Ÿ“ upstream -;;(import "$root" "[error-context-new-utf8]" (func (param i32 i32) (result i32))) -;;(import "$root" "[error-context-new-utf16]" (func (param i32 i32) (result i32))) -;;(import "$root" "[error-context-new-latin1+utf16]" (func (param i32 i32) (result i32))) -;;(import "$root" "[error-context-debug-message-utf8]" (func (param i32 i32))) -;;(import "$root" "[error-context-debug-message-utf16]" (func (param i32 i32))) -;;(import "$root" "[error-context-debug-message-latin1+utf16]" (func (param i32 i32))) +;;(import "$root" "[error-context-new-utf8]" (func (param {ptr} {ptr}) (result i32))) +;;(import "$root" "[error-context-new-utf16]" (func (param {ptr} {ptr}) (result i32))) +;;(import "$root" "[error-context-new-latin1+utf16]" (func (param {ptr} {ptr}) (result i32))) +;;(import "$root" "[error-context-debug-message-utf8]" (func (param i32 {ptr}))) +;;(import "$root" "[error-context-debug-message-utf16]" (func (param i32 {ptr}))) +;;(import "$root" "[error-context-debug-message-latin1+utf16]" (func (param i32 {ptr}))) ;;(import "$root" "[error-context-drop]" (func (param i32))) "#, - ); + )); } diff --git a/crates/wit-component/src/encoding.rs b/crates/wit-component/src/encoding.rs index fdda932dfc..cf21f3df90 100644 --- a/crates/wit-component/src/encoding.rs +++ b/crates/wit-component/src/encoding.rs @@ -3764,7 +3764,12 @@ world test { .unwrap(); let world = resolve.select_world(&[pkg], None).unwrap(); - let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32); + let mut module = dummy_module( + &resolve, + world, + ManglingAndAbi::Standard32, + crate::IndexType::I32, + ); embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8, true).unwrap(); diff --git a/crates/wit-component/src/lib.rs b/crates/wit-component/src/lib.rs index 464c43ac86..7cf31ec403 100644 --- a/crates/wit-component/src/lib.rs +++ b/crates/wit-component/src/lib.rs @@ -21,7 +21,7 @@ pub use encoding::{ComponentEncoder, LibraryInfo, encode}; pub use linking::Linker; pub use printing::*; pub use targets::*; -pub use validation::AdapterModuleDidNotExport; +pub use validation::{AdapterModuleDidNotExport, IndexType}; pub use wit_parser::decoding::{DecodedWasm, decode, decode_reader}; pub mod metadata; diff --git a/crates/wit-component/src/semver_check.rs b/crates/wit-component/src/semver_check.rs index c4ed41695a..f5eb5cb9d7 100644 --- a/crates/wit-component/src/semver_check.rs +++ b/crates/wit-component/src/semver_check.rs @@ -65,7 +65,12 @@ pub fn semver_check(mut resolve: Resolve, prev: WorldId, new: WorldId) -> Result let mut root_component = ComponentBuilder::default(); // (1) above - create a dummy component which has the shape of `prev`. - let mut prev_as_module = dummy_module(&resolve, prev, ManglingAndAbi::Standard32); + let mut prev_as_module = dummy_module( + &resolve, + prev, + ManglingAndAbi::Standard32, + crate::IndexType::I32, + ); embed_component_metadata( &mut prev_as_module, &resolve, diff --git a/crates/wit-component/src/validation.rs b/crates/wit-component/src/validation.rs index bf7b13d043..fa6a1b2f12 100644 --- a/crates/wit-component/src/validation.rs +++ b/crates/wit-component/src/validation.rs @@ -24,8 +24,10 @@ use wit_parser::{ /// index type corresponds to the component model's 64-bit (`cm64`) feature. #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] pub enum IndexType { + /// A 32-bit linear memory, where pointers and lengths are `i32`. #[default] I32, + /// A 64-bit linear memory, where pointers and lengths are `i64`. I64, } @@ -41,7 +43,7 @@ impl fmt::Display for IndexType { impl IndexType { /// Returns the index type used for canonical ABI pointers by the memory /// `ty`. - pub fn of_memory(ty: &MemoryType) -> IndexType { + pub(crate) fn of_memory(ty: &MemoryType) -> IndexType { if ty.memory64 { IndexType::I64 } else { @@ -50,7 +52,7 @@ impl IndexType { } /// Returns the core wasm type of pointers and lengths. - pub fn ptr(&self) -> ValType { + pub(crate) fn ptr(&self) -> ValType { match self { IndexType::I32 => ValType::I32, IndexType::I64 => ValType::I64, @@ -58,7 +60,7 @@ impl IndexType { } /// Returns the core wasm type that `ty` maps to with this index type. - pub fn val_type(&self, ty: &WasmType) -> ValType { + pub(crate) fn val_type(&self, ty: &WasmType) -> ValType { match ty { WasmType::I32 => ValType::I32, WasmType::I64 => ValType::I64, @@ -71,7 +73,7 @@ impl IndexType { /// Returns the core wasm function type that `signature` maps to with this /// index type. - pub fn func_type(&self, signature: &WasmSignature) -> FuncType { + pub(crate) fn func_type(&self, signature: &WasmSignature) -> FuncType { FuncType::new( signature.params.iter().map(|ty| self.val_type(ty)), signature.results.iter().map(|ty| self.val_type(ty)), @@ -79,7 +81,7 @@ impl IndexType { } /// Returns the size, in bytes, of a pointer. - pub fn ptr_size(&self) -> u32 { + pub(crate) fn ptr_size(&self) -> u32 { match self { IndexType::I32 => 4, IndexType::I64 => 8, @@ -87,12 +89,12 @@ impl IndexType { } /// Returns the log2 of the natural alignment of a pointer. - pub fn ptr_align_log2(&self) -> u32 { + pub(crate) fn ptr_align_log2(&self) -> u32 { self.ptr_size().trailing_zeros() } /// Returns a constant expression of this pointer type with the value `a`. - pub fn const_expr(&self, a: u32) -> wasm_encoder::ConstExpr { + pub(crate) fn const_expr(&self, a: u32) -> wasm_encoder::ConstExpr { match self { IndexType::I32 => wasm_encoder::ConstExpr::i32_const(a as i32), IndexType::I64 => wasm_encoder::ConstExpr::i64_const(a.into()), @@ -100,12 +102,12 @@ impl IndexType { } /// Same as [`IndexType::ptr`], but for `wasm-encoder`. - pub fn encoder_ptr(&self) -> wasm_encoder::ValType { + pub(crate) fn encoder_ptr(&self) -> wasm_encoder::ValType { self.ptr().try_into().unwrap() } /// Same as [`IndexType::val_type`], but for `wasm-encoder`. - pub fn encoder_val_type(&self, ty: &WasmType) -> wasm_encoder::ValType { + pub(crate) fn encoder_val_type(&self, ty: &WasmType) -> wasm_encoder::ValType { self.val_type(ty).try_into().unwrap() } diff --git a/fuzz/src/roundtrip_wit.rs b/fuzz/src/roundtrip_wit.rs index 855cc54bed..f09e4c8d23 100644 --- a/fuzz/src/roundtrip_wit.rs +++ b/fuzz/src/roundtrip_wit.rs @@ -47,11 +47,17 @@ pub fn run(u: &mut Unstructured<'_>) -> Result<()> { 3 => ManglingAndAbi::Standard32, _ => unreachable!(), }; + // 64-bit memories are only supported with legacy names at this time. + let index_type = match mangling { + ManglingAndAbi::Legacy(_) if u.arbitrary()? => IndexType::I64, + _ => IndexType::I32, + }; log::debug!( - "embedding world {} as in a dummy module with abi {mangling:?}", + "embedding world {} as in a dummy module with abi {mangling:?} \ + and index type {index_type}", world.name ); - let mut dummy = wit_component::dummy_module(&resolve, id, mangling); + let mut dummy = wit_component::dummy_module(&resolve, id, mangling, index_type); if u.arbitrary()? { let mut dst = Module::default(); let mut reencode = RemoveImports { diff --git a/src/bin/wasm-tools/component.rs b/src/bin/wasm-tools/component.rs index 39a5f1ddc5..476e4a9297 100644 --- a/src/bin/wasm-tools/component.rs +++ b/src/bin/wasm-tools/component.rs @@ -14,10 +14,10 @@ use wasmparser::types::{CoreTypeId, EntityType, Types}; use wasmparser::{Payload, ValidPayload, WasmFeatures}; use wat::Detect; use wit_component::{ - ComponentEncoder, DecodedWasm, Linker, StringEncoding, WitPrinter, embed_component_metadata, - metadata, + ComponentEncoder, DecodedWasm, IndexType, Linker, StringEncoding, WitPrinter, + embed_component_metadata, metadata, }; -use wit_parser::{LiftLowerAbi, Mangling, ManglingAndAbi, WorldItem, WorldKey}; +use wit_parser::{LiftLowerAbi, ManglingAndAbi, WorldItem, WorldKey}; /// WebAssembly wit-based component tooling. #[derive(Parser)] @@ -422,10 +422,9 @@ pub struct EmbedOpts { /// /// This flag is the same as `--dummy` where if specified a core wasm module /// is not read but is instead generated. The value of the option here is - /// the name mangling scheme to use for core wasm names generated. Current - /// options are `legacy|standard32`. + /// the name mangling scheme to use for core wasm names generated. #[clap(long, conflicts_with = "dummy")] - dummy_names: Option, + dummy_names: Option, /// With `--dummy-names legacy`, this will generate a core module such that /// all the imports are lowered using the async ABI and the exports are @@ -461,6 +460,13 @@ pub struct EmbedOpts { only_custom: bool, } +#[derive(clap::ValueEnum, Debug, Copy, Clone, PartialEq, Eq)] +enum DummyNames { + Standard32, + Legacy, + Legacy64, +} + impl EmbedOpts { fn general_opts(&self) -> &wasm_tools::GeneralOpts { self.io.general_opts() @@ -493,29 +499,28 @@ impl EmbedOpts { if self.async_callback || self.async_stackful { bail!("non-legacy mangling not yet supported when generating async dummy modules"); } - wit_component::dummy_module(&resolve, world, ManglingAndAbi::Standard32) - } else if let Some(mangling) = self.dummy_names { - wit_component::dummy_module( - &resolve, - world, - match mangling { - Mangling::Standard32 => { - if self.async_callback || self.async_stackful { - bail!( - "non-legacy mangling not yet supported when generating async dummy modules" - ); - } - ManglingAndAbi::Standard32 + wit_component::dummy_module(&resolve, world, ManglingAndAbi::Standard32, IndexType::I32) + } else if let Some(names) = self.dummy_names { + let legacy = ManglingAndAbi::Legacy(if self.async_callback { + LiftLowerAbi::AsyncCallback + } else if self.async_stackful { + LiftLowerAbi::AsyncStackful + } else { + LiftLowerAbi::Sync + }); + let (mangling, index_type) = match names { + DummyNames::Standard32 => { + if self.async_callback || self.async_stackful { + bail!( + "non-legacy mangling not yet supported when generating async dummy modules" + ); } - Mangling::Legacy => ManglingAndAbi::Legacy(if self.async_callback { - LiftLowerAbi::AsyncCallback - } else if self.async_stackful { - LiftLowerAbi::AsyncStackful - } else { - LiftLowerAbi::Sync - }), - }, - ) + (ManglingAndAbi::Standard32, IndexType::I32) + } + DummyNames::Legacy => (legacy, IndexType::I32), + DummyNames::Legacy64 => (legacy, IndexType::I64), + }; + wit_component::dummy_module(&resolve, world, mangling, index_type) } else { self.io.get_input_wasm(Some(&self.generate_dwarf))? }; diff --git a/tests/cli/dummy-cm64-import-and-export.wit b/tests/cli/dummy-cm64-import-and-export.wit new file mode 100644 index 0000000000..fe6b5ca723 --- /dev/null +++ b/tests/cli/dummy-cm64-import-and-export.wit @@ -0,0 +1,17 @@ +// RUN: component embed --dummy-names legacy64 % | \ +// component new | \ +// validate -f cm64 + +package a:b; + +interface i { + resource r { + name: func(); + } + f: func(x: borrow); +} + +world w { + import i; + export i; +} diff --git a/tests/cli/dummy-cm64.wit b/tests/cli/dummy-cm64.wit new file mode 100644 index 0000000000..859ed46d8d --- /dev/null +++ b/tests/cli/dummy-cm64.wit @@ -0,0 +1,36 @@ +// RUN[embed]: component embed -t --dummy-names legacy64 % | strip -t +// RUN[new]: component embed --dummy-names legacy64 % | \ +// component new | \ +// validate -f cm64 + +package a:b; + +interface imp { + resource r { + constructor(name: string); + name: func() -> string; + take: func(other: borrow, l: list); + } + + f: func(a: string, b: option, c: result, string>) -> tuple; + many: func(a: u32, b: u32, c: u32, d: u32, e: u32, f: u32, g: u32, h: u32, i: u32, j: u32, k: u32, l: u32, m: u32, n: u32, o: u32, p: u32, q: u32, r: u32); +} + +interface exp { + use imp.{r as imported}; + + resource r { + constructor(name: string); + name: func() -> string; + merge: func(other: borrow, imported: borrow); + } + + f: func(a: string, b: option) -> list; +} + +world w { + import imp; + import g: func(x: string) -> string; + export exp; + export g: func(x: string) -> option; +} diff --git a/tests/cli/dummy-cm64.wit.embed.stdout b/tests/cli/dummy-cm64.wit.embed.stdout new file mode 100644 index 0000000000..ff08b0e9ad --- /dev/null +++ b/tests/cli/dummy-cm64.wit.embed.stdout @@ -0,0 +1,67 @@ +(module + (type (;0;) (func (param i64 i64) (result i32))) + (type (;1;) (func (param i32 i64))) + (type (;2;) (func (param i32 i32 i64 i64))) + (type (;3;) (func (param i64 i64 i32 i64 i64 i32 i64 i64 i64))) + (type (;4;) (func (param i64))) + (type (;5;) (func (param i32))) + (type (;6;) (func (param i64 i64 i64))) + (type (;7;) (func (param i64) (result i32))) + (type (;8;) (func (param i32) (result i64))) + (type (;9;) (func (param i64 i64) (result i64))) + (type (;10;) (func (param i64) (result i64))) + (type (;11;) (func (param i64 i64 i32))) + (type (;12;) (func)) + (type (;13;) (func (param i64 i64 i32 i64 i64) (result i64))) + (type (;14;) (func (param i64 i64 i64 i64) (result i64))) + (import "a:b/imp" "[constructor]r" (func (;0;) (type 0) (param i64 i64) (result i32))) + (import "a:b/imp" "[method]r.name" (func (;1;) (type 1) (param i32 i64))) + (import "a:b/imp" "[method]r.take" (func (;2;) (type 2) (param i32 i32 i64 i64))) + (import "a:b/imp" "f" (func (;3;) (type 3) (param i64 i64 i32 i64 i64 i32 i64 i64 i64))) + (import "a:b/imp" "many" (func (;4;) (type 4) (param i64))) + (import "a:b/imp" "[resource-drop]r" (func (;5;) (type 5) (param i32))) + (import "$root" "g" (func (;6;) (type 6) (param i64 i64 i64))) + (import "[export]a:b/exp" "[resource-drop]r" (func (;7;) (type 5) (param i32))) + (import "[export]a:b/exp" "[resource-new]r" (func (;8;) (type 7) (param i64) (result i32))) + (import "[export]a:b/exp" "[resource-rep]r" (func (;9;) (type 8) (param i32) (result i64))) + (memory (;0;) i64 0) + (export "g" (func 10)) + (export "cabi_post_g" (func 11)) + (export "a:b/exp#[constructor]r" (func 12)) + (export "cabi_post_a:b/exp#[constructor]r" (func 13)) + (export "a:b/exp#[method]r.name" (func 14)) + (export "cabi_post_a:b/exp#[method]r.name" (func 15)) + (export "a:b/exp#[method]r.merge" (func 16)) + (export "cabi_post_a:b/exp#[method]r.merge" (func 17)) + (export "a:b/exp#f" (func 18)) + (export "cabi_post_a:b/exp#f" (func 19)) + (export "a:b/exp#[dtor]r" (func 20)) + (export "memory" (memory 0)) + (export "cabi_realloc" (func 21)) + (export "_initialize" (func 22)) + (func (;10;) (type 9) (param i64 i64) (result i64) + unreachable + ) + (func (;11;) (type 4) (param i64)) + (func (;12;) (type 0) (param i64 i64) (result i32) + unreachable + ) + (func (;13;) (type 5) (param i32)) + (func (;14;) (type 10) (param i64) (result i64) + unreachable + ) + (func (;15;) (type 4) (param i64)) + (func (;16;) (type 11) (param i64 i64 i32) + unreachable + ) + (func (;17;) (type 12)) + (func (;18;) (type 13) (param i64 i64 i32 i64 i64) (result i64) + unreachable + ) + (func (;19;) (type 4) (param i64)) + (func (;20;) (type 4) (param i64)) + (func (;21;) (type 14) (param i64 i64 i64 i64) (result i64) + unreachable + ) + (func (;22;) (type 12)) +) diff --git a/tests/cli/help-component-embed-short.wat.stdout b/tests/cli/help-component-embed-short.wat.stdout index 221c799409..0a2533c455 100644 --- a/tests/cli/help-component-embed-short.wat.stdout +++ b/tests/cli/help-component-embed-short.wat.stdout @@ -34,6 +34,7 @@ Options: module as a placeholder --dummy-names Same as `--dummy`, but the style of core wasm names is specified + [possible values: standard32, legacy, legacy64] --async-callback With `--dummy-names legacy`, this will generate a core module such that all the imports are lowered using the async ABI and the exports diff --git a/tests/cli/help-component-embed.wat.stdout b/tests/cli/help-component-embed.wat.stdout index e110e77a39..555696c313 100644 --- a/tests/cli/help-component-embed.wat.stdout +++ b/tests/cli/help-component-embed.wat.stdout @@ -119,7 +119,8 @@ Options: This flag is the same as `--dummy` where if specified a core wasm module is not read but is instead generated. The value of the option here is the name mangling scheme to use for core wasm names generated. - Current options are `legacy|standard32`. + + [possible values: standard32, legacy, legacy64] --async-callback With `--dummy-names legacy`, this will generate a core module such