Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 97 additions & 52 deletions crates/wit-component/src/dummy.rs

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion crates/wit-component/src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
2 changes: 1 addition & 1 deletion crates/wit-component/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 6 additions & 1 deletion crates/wit-component/src/semver_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
20 changes: 11 additions & 9 deletions crates/wit-component/src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand All @@ -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 {
Expand All @@ -50,15 +52,15 @@ 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,
}
}

/// 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,
Expand All @@ -71,41 +73,41 @@ 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)),
)
}

/// 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,
}
}

/// 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()),
}
}

/// 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()
}

Expand Down
10 changes: 8 additions & 2 deletions fuzz/src/roundtrip_wit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
61 changes: 33 additions & 28 deletions src/bin/wasm-tools/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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<Mangling>,
dummy_names: Option<DummyNames>,

/// 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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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))?
};
Expand Down
17 changes: 17 additions & 0 deletions tests/cli/dummy-cm64-import-and-export.wit
Original file line number Diff line number Diff line change
@@ -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<r>);
}

world w {
import i;
export i;
}
36 changes: 36 additions & 0 deletions tests/cli/dummy-cm64.wit
Original file line number Diff line number Diff line change
@@ -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<r>, l: list<u8>);
}

f: func(a: string, b: option<string>, c: result<list<u64>, string>) -> tuple<string, u32>;
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<r>, imported: borrow<imported>);
}

f: func(a: string, b: option<string>) -> list<string>;
}

world w {
import imp;
import g: func(x: string) -> string;
export exp;
export g: func(x: string) -> option<string>;
}
67 changes: 67 additions & 0 deletions tests/cli/dummy-cm64.wit.embed.stdout
Original file line number Diff line number Diff line change
@@ -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))
)
1 change: 1 addition & 0 deletions tests/cli/help-component-embed-short.wat.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Options:
module as a placeholder
--dummy-names <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
Expand Down
3 changes: 2 additions & 1 deletion tests/cli/help-component-embed.wat.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading