From 3368973bc963e21d594819e6f47794bba779abd6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 28 Sep 2024 07:52:37 -0700 Subject: [PATCH] Update `embed --dummy` with new ABI names This commit updates the `wasm-tools component embed` subcommand, specifically the `--dummy` flag. This flag now uses the new "standard32" names for the core module that is generated. Additionally a new `--dummy-names $FOO` option has been added to enable generating the old names as well as the new names. Utilities have also been added to `Resolve` for bindings generators to avoid hardcoding ABI names and instead use the add categories of imports/exports to name items. --- crates/wit-component/src/dummy.rs | 148 ++++++++--- crates/wit-component/src/encoding.rs | 3 +- crates/wit-component/src/semver_check.rs | 4 +- crates/wit-parser/src/lib.rs | 21 +- crates/wit-parser/src/resolve.rs | 237 +++++++++++++++++- fuzz/src/roundtrip_wit.rs | 9 +- src/bin/wasm-tools/component.rs | 28 ++- tests/cli/embed-dummy.wit | 13 + tests/cli/embed-dummy.wit.legacy.stdout | 21 ++ tests/cli/embed-dummy.wit.standard32.stdout | 21 ++ tests/cli/semver-check-add-export.wit.stderr | 2 +- .../cli/semver-check-remove-import.wit.stderr | 2 +- 12 files changed, 453 insertions(+), 56 deletions(-) create mode 100644 tests/cli/embed-dummy.wit create mode 100644 tests/cli/embed-dummy.wit.legacy.stdout create mode 100644 tests/cli/embed-dummy.wit.standard32.stdout diff --git a/crates/wit-component/src/dummy.rs b/crates/wit-component/src/dummy.rs index 50c217a8e9..78980e73d1 100644 --- a/crates/wit-component/src/dummy.rs +++ b/crates/wit-component/src/dummy.rs @@ -1,8 +1,11 @@ use wit_parser::abi::{AbiVariant, WasmType}; -use wit_parser::{Function, Resolve, TypeDefKind, TypeId, WorldId, WorldItem}; +use wit_parser::{ + Function, Mangling, Resolve, ResourceIntrinsic, TypeDefKind, TypeId, WasmExport, WasmImport, + WorldId, WorldItem, WorldKey, +}; /// Generate a dummy implementation core Wasm module for a given WIT document -pub fn dummy_module(resolve: &Resolve, world: WorldId) -> Vec { +pub fn dummy_module(resolve: &Resolve, world: WorldId, mangling: Mangling) -> Vec { let world = &resolve.worlds[world]; let mut wat = String::new(); wat.push_str("(module\n"); @@ -11,27 +14,41 @@ pub fn dummy_module(resolve: &Resolve, world: WorldId) -> Vec { WorldItem::Function(func) => { let sig = resolve.wasm_signature(AbiVariant::GuestImport, func); - wat.push_str(&format!("(import \"$root\" \"{}\" (func", func.name)); + let (module, name) = resolve.wasm_import_name( + mangling, + WasmImport::Func { + interface: None, + func, + }, + ); + + wat.push_str(&format!("(import {module:?} {name:?} (func")); push_tys(&mut wat, "param", &sig.params); push_tys(&mut wat, "result", &sig.results); wat.push_str("))\n"); } WorldItem::Interface { id: import, .. } => { - let name = resolve.name_world_key(name); for (_, func) in resolve.interfaces[*import].functions.iter() { let sig = resolve.wasm_signature(AbiVariant::GuestImport, func); - wat.push_str(&format!("(import \"{name}\" \"{}\" (func", func.name)); + let (module, name) = resolve.wasm_import_name( + mangling, + WasmImport::Func { + interface: Some(name), + func, + }, + ); + wat.push_str(&format!("(import {module:?} {name:?} (func")); push_tys(&mut wat, "param", &sig.params); push_tys(&mut wat, "result", &sig.results); wat.push_str("))\n"); } for (_, ty) in resolve.interfaces[*import].types.iter() { - push_resource_func_imports(&mut wat, resolve, &name, *ty); + push_resource_func_imports(&mut wat, resolve, Some(name), *ty, mangling); } } WorldItem::Type(id) => { - push_resource_func_imports(&mut wat, resolve, "$root", *id); + push_resource_func_imports(&mut wat, resolve, None, *id, mangling); } } } @@ -42,77 +59,136 @@ pub fn dummy_module(resolve: &Resolve, world: WorldId) -> Vec { WorldItem::Interface { id, .. } => *id, _ => continue, }; - let module = format!("[export]{}", resolve.name_world_key(name)); - for (name, ty) in resolve.interfaces[export].types.iter() { - let ty = &resolve.types[*ty]; + for resource in resolve.interfaces[export].types.values().copied() { + let ty = &resolve.types[resource]; match ty.kind { TypeDefKind::Resource => {} _ => continue, } - wat.push_str(&format!( - "\ -(import \"{module}\" \"[resource-drop]{name}\" (func (param i32))) -(import \"{module}\" \"[resource-new]{name}\" (func (param i32) (result i32))) -(import \"{module}\" \"[resource-rep]{name}\" (func (param i32) (result i32))) - " - )); + let intrinsics = [ + (ResourceIntrinsic::ExportedDrop, "(func (param i32))"), + ( + ResourceIntrinsic::ExportedNew, + "(func (param i32) (result i32))", + ), + ( + ResourceIntrinsic::ExportedRep, + "(func (param i32) (result i32))", + ), + ]; + for (intrinsic, sig) in intrinsics { + let (module, name) = resolve.wasm_import_name( + mangling, + WasmImport::ResourceIntrinsic { + interface: Some(name), + resource, + intrinsic, + }, + ); + wat.push_str(&format!("(import {module:?} {name:?} {sig})\n")); + } } } for (name, export) in world.exports.iter() { match export { WorldItem::Function(func) => { - push_func(&mut wat, &func.name, resolve, func); + push_func_export(&mut wat, resolve, None, func, mangling); } WorldItem::Interface { id: export, .. } => { - let name = resolve.name_world_key(name); for (_, func) in resolve.interfaces[*export].functions.iter() { - let name = func.legacy_core_export_name(Some(&name)); - push_func(&mut wat, &name, resolve, func); + push_func_export(&mut wat, resolve, Some(name), func, mangling); } // Feign destructors for any resource that this interface // exports - for (resource_name, ty) in resolve.interfaces[*export].types.iter() { - let ty = &resolve.types[*ty]; + for resource in resolve.interfaces[*export].types.values().copied() { + let ty = &resolve.types[resource]; match ty.kind { TypeDefKind::Resource => {} _ => continue, } - wat.push_str(&format!( - "(func (export \"{name}#[dtor]{resource_name}\") (param i32))" - )); + let name = resolve.wasm_export_name( + mangling, + WasmExport::ResourceDtor { + interface: name, + resource, + }, + ); + wat.push_str(&format!("(func (export {name:?}) (param i32))")); } } WorldItem::Type(_) => {} } } - wat.push_str("(memory (export \"memory\") 0)\n"); - wat.push_str( - "(func (export \"cabi_realloc\") (param i32 i32 i32 i32) (result i32) unreachable)\n", - ); + let memory = resolve.wasm_export_name(mangling, WasmExport::Memory); + wat.push_str(&format!("(memory (export {memory:?}) 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" + )); + let initialize = resolve.wasm_export_name(mangling, WasmExport::Initialize); + wat.push_str(&format!("(func (export {initialize:?}))")); wat.push_str(")\n"); return wat::parse_str(&wat).unwrap(); - fn push_resource_func_imports(wat: &mut String, resolve: &Resolve, module: &str, ty: TypeId) { - let ty = &resolve.types[ty]; + fn push_resource_func_imports( + wat: &mut String, + resolve: &Resolve, + interface: Option<&WorldKey>, + resource: TypeId, + mangling: Mangling, + ) { + let ty = &resolve.types[resource]; match ty.kind { TypeDefKind::Resource => {} _ => return, } - let name = ty.name.as_ref().unwrap(); - wat.push_str(&format!("(import \"{module}\" \"[resource-drop]{name}\"")); - wat.push_str(" (func (param i32)))\n"); + let (module, name) = resolve.wasm_import_name( + mangling, + WasmImport::ResourceIntrinsic { + interface, + resource, + intrinsic: ResourceIntrinsic::ImportedDrop, + }, + ); + wat.push_str(&format!("(import {module:?} {name:?} (func (param i32)))")); } - fn push_func(wat: &mut String, name: &str, resolve: &Resolve, func: &Function) { + fn push_func_export( + wat: &mut String, + resolve: &Resolve, + interface: Option<&WorldKey>, + func: &Function, + mangling: Mangling, + ) { let sig = resolve.wasm_signature(AbiVariant::GuestExport, func); + let name = resolve.wasm_export_name( + mangling, + WasmExport::Func { + interface, + func, + post_return: false, + }, + ); wat.push_str(&format!("(func (export \"{name}\")")); push_tys(wat, "param", &sig.params); push_tys(wat, "result", &sig.results); wat.push_str(" unreachable)\n"); + + let name = resolve.wasm_export_name( + mangling, + WasmExport::Func { + interface, + func, + post_return: true, + }, + ); + wat.push_str(&format!("(func (export \"{name}\")")); + push_tys(wat, "param", &sig.results); + wat.push_str(")\n"); } fn push_tys(dst: &mut String, desc: &str, params: &[WasmType]) { diff --git a/crates/wit-component/src/encoding.rs b/crates/wit-component/src/encoding.rs index 5843a7e338..faf0c0723f 100644 --- a/crates/wit-component/src/encoding.rs +++ b/crates/wit-component/src/encoding.rs @@ -2158,6 +2158,7 @@ impl ComponentWorld<'_> { mod test { use super::*; use crate::{dummy_module, embed_component_metadata}; + use wit_parser::Mangling; #[test] fn it_renames_imports() { @@ -2183,7 +2184,7 @@ world test { .unwrap(); let world = resolve.select_world(pkg, None).unwrap(); - let mut module = dummy_module(&resolve, world); + let mut module = dummy_module(&resolve, world, Mangling::Standard32); embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap(); diff --git a/crates/wit-component/src/semver_check.rs b/crates/wit-component/src/semver_check.rs index d6f4c6c145..1c4a9f4f5e 100644 --- a/crates/wit-component/src/semver_check.rs +++ b/crates/wit-component/src/semver_check.rs @@ -5,7 +5,7 @@ use crate::{ use anyhow::{bail, Context, Result}; use wasm_encoder::{ComponentBuilder, ComponentExportKind, ComponentTypeRef}; use wasmparser::Validator; -use wit_parser::{Resolve, WorldId}; +use wit_parser::{Mangling, Resolve, WorldId}; /// Tests whether `new` is a semver-compatible upgrade from the world `prev`. /// @@ -63,7 +63,7 @@ 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); + let mut prev_as_module = dummy_module(&resolve, prev, Mangling::Standard32); embed_component_metadata(&mut prev_as_module, &resolve, prev, StringEncoding::UTF8) .context("failed to embed component metadata")?; let prev_as_component = ComponentEncoder::default() diff --git a/crates/wit-parser/src/lib.rs b/crates/wit-parser/src/lib.rs index 638dd6e96b..906f6a7a13 100644 --- a/crates/wit-parser/src/lib.rs +++ b/crates/wit-parser/src/lib.rs @@ -1,4 +1,4 @@ -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; use id_arena::{Arena, Id}; use indexmap::IndexMap; use semver::Version; @@ -21,7 +21,7 @@ pub use ast::{parse_use_path, ParsedUsePath}; mod sizealign; pub use sizealign::*; mod resolve; -pub use resolve::{InvalidTransitiveDependency, Package, PackageId, Remap, Resolve}; +pub use resolve::*; mod live; pub use live::{LiveTypes, TypeIdVisitor}; @@ -881,6 +881,23 @@ pub enum Mangling { Legacy, } +impl std::str::FromStr for Mangling { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + match s { + "legacy" => Ok(Mangling::Legacy), + "standard32" => Ok(Mangling::Standard32), + _ => { + bail!( + "unknown name mangling `{s}`, \ + supported values are `legacy` or `standard32`" + ) + } + } + } +} + impl Function { pub fn item_name(&self) -> &str { match &self.kind { diff --git a/crates/wit-parser/src/resolve.rs b/crates/wit-parser/src/resolve.rs index d5a62739c3..02efb93867 100644 --- a/crates/wit-parser/src/resolve.rs +++ b/crates/wit-parser/src/resolve.rs @@ -18,9 +18,9 @@ use crate::ast::{parse_use_path, ParsedUsePath}; use crate::serde_::{serialize_arena, serialize_id_map}; use crate::{ AstItem, Docs, Error, Function, FunctionKind, Handle, IncludeName, Interface, InterfaceId, - InterfaceSpan, PackageName, Results, SourceMap, Stability, Type, TypeDef, TypeDefKind, TypeId, - TypeIdVisitor, TypeOwner, UnresolvedPackage, UnresolvedPackageGroup, World, WorldId, WorldItem, - WorldKey, WorldSpan, + InterfaceSpan, Mangling, PackageName, Results, SourceMap, Stability, Type, TypeDef, + TypeDefKind, TypeId, TypeIdVisitor, TypeOwner, UnresolvedPackage, UnresolvedPackageGroup, + World, WorldId, WorldItem, WorldKey, WorldSpan, }; mod clone; @@ -1308,6 +1308,17 @@ package {name} is defined in two different locations:\n\ } } + /// Same as [`Resolve::name_world_key`] except that `WorldKey::Interfaces` + /// uses [`Resolve::canonicalized_id_of`]. + pub fn name_canonicalized_world_key(&self, key: &WorldKey) -> String { + match key { + WorldKey::Name(s) => s.to_string(), + WorldKey::Interface(i) => self + .canonicalized_id_of(*i) + .expect("unexpected anonymous interface"), + } + } + /// Returns the interface that `id` uses a type from, if it uses a type from /// a different interface than `id` is defined within. /// @@ -2203,6 +2214,226 @@ package {name} is defined in two different locations:\n\ let replacement_id = self.interfaces[*replace_with].types[name]; self.types[ty].kind = TypeDefKind::Type(Type::Id(replacement_id)); } + + /// Returns the core wasm module/field names for the specified `import`. + /// + /// This function will return the core wasm module/field that can be used to + /// use `import` with the name `mangling` scheme specified as well. This can + /// be useful for bindings generators, for example, and these names are + /// recognized by `wit-component` and `wasm-tools component new`. + pub fn wasm_import_name(&self, mangling: Mangling, import: WasmImport<'_>) -> (String, String) { + match mangling { + Mangling::Standard32 => match import { + WasmImport::Func { interface, func } => { + let module = match interface { + Some(key) => format!("cm32p2|{}", self.name_canonicalized_world_key(key)), + None => format!("cm32p2"), + }; + (module, func.name.clone()) + } + WasmImport::ResourceIntrinsic { + interface, + resource, + intrinsic, + } => { + let name = self.types[resource].name.as_ref().unwrap(); + let (prefix, name) = match intrinsic { + ResourceIntrinsic::ImportedDrop => ("", format!("{name}_drop")), + ResourceIntrinsic::ExportedDrop => ("_ex_", format!("{name}_drop")), + ResourceIntrinsic::ExportedNew => ("_ex_", format!("{name}_new")), + ResourceIntrinsic::ExportedRep => ("_ex_", format!("{name}_rep")), + }; + let module = match interface { + Some(key) => { + format!("cm32p2|{prefix}{}", self.name_canonicalized_world_key(key)) + } + None => { + assert_eq!(prefix, ""); + format!("cm32p2") + } + }; + (module, name) + } + }, + Mangling::Legacy => match import { + WasmImport::Func { interface, func } => { + let module = match interface { + Some(key) => self.name_world_key(key), + None => format!("$root"), + }; + (module, func.name.clone()) + } + WasmImport::ResourceIntrinsic { + interface, + resource, + intrinsic, + } => { + let name = self.types[resource].name.as_ref().unwrap(); + let (prefix, name) = match intrinsic { + ResourceIntrinsic::ImportedDrop => ("", format!("[resource-drop]{name}")), + ResourceIntrinsic::ExportedDrop => { + ("[export]", format!("[resource-drop]{name}")) + } + ResourceIntrinsic::ExportedNew => { + ("[export]", format!("[resource-new]{name}")) + } + ResourceIntrinsic::ExportedRep => { + ("[export]", format!("[resource-rep]{name}")) + } + }; + let module = match interface { + Some(key) => format!("{prefix}{}", self.name_world_key(key)), + None => { + assert_eq!(prefix, ""); + format!("$root") + } + }; + (module, name) + } + }, + } + } + + /// Returns the core wasm export name for the specified `import`. + /// + /// This is the same as [`Resovle::wasm_import_name`], except for exports. + pub fn wasm_export_name(&self, mangling: Mangling, import: WasmExport<'_>) -> String { + match mangling { + Mangling::Standard32 => match import { + WasmExport::Func { + interface, + func, + post_return, + } => { + let mut name = String::from("cm32p2|"); + if let Some(interface) = interface { + let s = self.name_canonicalized_world_key(interface); + name.push_str(&s); + } + name.push_str("|"); + name.push_str(&func.name); + if post_return { + name.push_str("_post"); + } + name + } + WasmExport::ResourceDtor { + interface, + resource, + } => { + let name = self.types[resource].name.as_ref().unwrap(); + let interface = self.name_canonicalized_world_key(interface); + format!("cm32p2|{interface}|{name}_dtor") + } + WasmExport::Memory => "cm32p2_memory".to_string(), + WasmExport::Initialize => "cm32p2_initialize".to_string(), + WasmExport::Realloc => "cm32p2_realloc".to_string(), + }, + Mangling::Legacy => match import { + WasmExport::Func { + interface, + func, + post_return, + } => { + let mut name = String::new(); + if post_return { + name.push_str("cabi_post_"); + } + if let Some(interface) = interface { + let s = self.name_world_key(interface); + name.push_str(&s); + name.push_str("#"); + } + name.push_str(&func.name); + name + } + WasmExport::ResourceDtor { + interface, + resource, + } => { + let name = self.types[resource].name.as_ref().unwrap(); + let interface = self.name_world_key(interface); + format!("{interface}#[dtor]{name}") + } + WasmExport::Memory => "memory".to_string(), + WasmExport::Initialize => "_initialize".to_string(), + WasmExport::Realloc => "cabi_realloc".to_string(), + }, + } + } +} + +/// Possible imports that can be passed to [`Resolve::wasm_import_name`]. +#[derive(Debug)] +pub enum WasmImport<'a> { + /// A WIT function is being imported. Optionally from an interface. + Func { + /// The name of the interface that the function is being imported from. + /// + /// If the function is imported directly from the world then this is + /// `Noen`. + interface: Option<&'a WorldKey>, + + /// The function being imported. + func: &'a Function, + }, + + /// A resource-related intrinsic is being imported. + ResourceIntrinsic { + /// The optional interface to import from, same as `WasmImport::Func`. + interface: Option<&'a WorldKey>, + + /// The resource that's being operated on. + resource: TypeId, + + /// The intrinsic that's being imported. + intrinsic: ResourceIntrinsic, + }, +} + +/// Intrinsic definitions to go with [`WasmImport::ResourceIntrinsic`] which +/// also goes with [`Resolve::wasm_import_name`]. +#[derive(Debug)] +pub enum ResourceIntrinsic { + ImportedDrop, + ExportedDrop, + ExportedNew, + ExportedRep, +} + +/// Different kinds of exports that can be passed to +/// [`Resolve::wasm_export_name`] to export from core wasm modules. +#[derive(Debug)] +pub enum WasmExport<'a> { + /// A WIT function is being exported, optionally from an interface. + Func { + /// An optional interface which owns `func`. Use `None` for top-level + /// world function. + interface: Option<&'a WorldKey>, + + /// The function being exported. + func: &'a Function, + + /// Whether or not this is a post-return function or not. + post_return: bool, + }, + + /// A destructor for a resource exported from this module. + ResourceDtor { + /// The interface that owns the resource. + interface: &'a WorldKey, + /// The resource itself that the destructor is for. + resource: TypeId, + }, + + /// Linear memory, the one that the canonical ABI uses. + Memory, + + /// An initialization function (not the core wasm `start`). + Initialize, + + /// The general-purpose realloc hook. + Realloc, } /// Structure returned by [`Resolve::merge`] which contains mappings from diff --git a/fuzz/src/roundtrip_wit.rs b/fuzz/src/roundtrip_wit.rs index ed6961608e..f94d52dd2c 100644 --- a/fuzz/src/roundtrip_wit.rs +++ b/fuzz/src/roundtrip_wit.rs @@ -1,7 +1,7 @@ use arbitrary::{Result, Unstructured}; use std::path::Path; use wit_component::*; -use wit_parser::{PackageId, Resolve}; +use wit_parser::{Mangling, PackageId, Resolve}; pub fn run(u: &mut Unstructured<'_>) -> Result<()> { let wasm = u.arbitrary().and_then(|config| { @@ -36,7 +36,12 @@ pub fn run(u: &mut Unstructured<'_>) -> Result<()> { let mut decoded_bindgens = Vec::new(); for (id, world) in resolve.worlds.iter().take(20) { log::debug!("embedding world {} as in a dummy module", world.name); - let mut dummy = wit_component::dummy_module(&resolve, id); + let mangling = match u.int_in_range(0..=1)? { + 0 => Mangling::Legacy, + 1 => Mangling::Standard32, + _ => unreachable!(), + }; + let mut dummy = wit_component::dummy_module(&resolve, id, mangling); wit_component::embed_component_metadata(&mut dummy, &resolve, id, StringEncoding::UTF8) .unwrap(); write_file("dummy.wasm", &dummy); diff --git a/src/bin/wasm-tools/component.rs b/src/bin/wasm-tools/component.rs index 9c95f14dc5..de0d290ef2 100644 --- a/src/bin/wasm-tools/component.rs +++ b/src/bin/wasm-tools/component.rs @@ -15,7 +15,7 @@ use wat::Detect; use wit_component::{ embed_component_metadata, ComponentEncoder, DecodedWasm, Linker, StringEncoding, WitPrinter, }; -use wit_parser::{PackageId, Resolve}; +use wit_parser::{Mangling, PackageId, Resolve}; /// WebAssembly wit-based component tooling. #[derive(Parser)] @@ -278,9 +278,20 @@ pub struct EmbedOpts { /// imports/exports and the right signatures for the component model. This /// can be useful to, perhaps, inspect a template module and what it looks /// like to work with an interface in the component model. - #[clap(long)] + /// + /// This option is equivalent to `--dummy-names standard32` + #[clap(long, conflicts_with = "dummy_names")] dummy: bool, + /// Same as `--dummy`, but the style of core wasm names is specified. + /// + /// 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`. + #[clap(long, conflicts_with = "dummy")] + dummy_names: Option, + /// Print the output in the WebAssembly text format instead of binary. #[clap(long, short = 't')] wat: bool, @@ -293,14 +304,15 @@ impl EmbedOpts { /// Executes the application. fn run(self) -> Result<()> { - let wasm = if self.dummy { - None - } else { - Some(self.io.parse_input_wasm()?) - }; let (resolve, pkg_id) = self.resolve.load()?; let world = resolve.select_world(pkg_id, self.world.as_deref())?; - let mut wasm = wasm.unwrap_or_else(|| wit_component::dummy_module(&resolve, world)); + let mut wasm = if self.dummy { + wit_component::dummy_module(&resolve, world, Mangling::Standard32) + } else if let Some(mangling) = self.dummy_names { + wit_component::dummy_module(&resolve, world, mangling) + } else { + self.io.parse_input_wasm()? + }; embed_component_metadata( &mut wasm, diff --git a/tests/cli/embed-dummy.wit b/tests/cli/embed-dummy.wit new file mode 100644 index 0000000000..ff256eff07 --- /dev/null +++ b/tests/cli/embed-dummy.wit @@ -0,0 +1,13 @@ +// RUN[legacy]: component embed -t --dummy-names legacy % | strip -t +// RUN[standard32]: component embed -t --dummy-names standard32 % | strip -t + +package a:b; + +interface x { + y: func() -> string; +} + +world w { + import x; + export x; +} diff --git a/tests/cli/embed-dummy.wit.legacy.stdout b/tests/cli/embed-dummy.wit.legacy.stdout new file mode 100644 index 0000000000..43af3e09eb --- /dev/null +++ b/tests/cli/embed-dummy.wit.legacy.stdout @@ -0,0 +1,21 @@ +(module + (type (;0;) (func (param i32))) + (type (;1;) (func (result i32))) + (type (;2;) (func (param i32 i32 i32 i32) (result i32))) + (type (;3;) (func)) + (import "a:b/x" "y" (func (;0;) (type 0))) + (memory (;0;) 0) + (export "a:b/x#y" (func 1)) + (export "cabi_post_a:b/x#y" (func 2)) + (export "memory" (memory 0)) + (export "cabi_realloc" (func 3)) + (export "_initialize" (func 4)) + (func (;1;) (type 1) (result i32) + unreachable + ) + (func (;2;) (type 0) (param i32)) + (func (;3;) (type 2) (param i32 i32 i32 i32) (result i32) + unreachable + ) + (func (;4;) (type 3)) +) diff --git a/tests/cli/embed-dummy.wit.standard32.stdout b/tests/cli/embed-dummy.wit.standard32.stdout new file mode 100644 index 0000000000..7b874d823a --- /dev/null +++ b/tests/cli/embed-dummy.wit.standard32.stdout @@ -0,0 +1,21 @@ +(module + (type (;0;) (func (param i32))) + (type (;1;) (func (result i32))) + (type (;2;) (func (param i32 i32 i32 i32) (result i32))) + (type (;3;) (func)) + (import "cm32p2|a:b/x" "y" (func (;0;) (type 0))) + (memory (;0;) 0) + (export "cm32p2|a:b/x|y" (func 1)) + (export "cm32p2|a:b/x|y_post" (func 2)) + (export "cm32p2_memory" (memory 0)) + (export "cm32p2_realloc" (func 3)) + (export "cm32p2_initialize" (func 4)) + (func (;1;) (type 1) (result i32) + unreachable + ) + (func (;2;) (type 0) (param i32)) + (func (;3;) (type 2) (param i32 i32 i32 i32) (result i32) + unreachable + ) + (func (;4;) (type 3)) +) diff --git a/tests/cli/semver-check-add-export.wit.stderr b/tests/cli/semver-check-add-export.wit.stderr index e7391d9617..76f4a07ff0 100644 --- a/tests/cli/semver-check-add-export.wit.stderr +++ b/tests/cli/semver-check-add-export.wit.stderr @@ -2,4 +2,4 @@ error: new world is not semver-compatible with the previous world Caused by: 0: type mismatch for import `new` - missing export named `a` (at offset 0xf0) + missing export named `a` (at offset 0x15a) diff --git a/tests/cli/semver-check-remove-import.wit.stderr b/tests/cli/semver-check-remove-import.wit.stderr index 339e755284..8e588913e1 100644 --- a/tests/cli/semver-check-remove-import.wit.stderr +++ b/tests/cli/semver-check-remove-import.wit.stderr @@ -2,4 +2,4 @@ error: new world is not semver-compatible with the previous world Caused by: 0: type mismatch for import `new` - missing import named `a` (at offset 0x119) + missing import named `a` (at offset 0x182)