Update wasm-tools crates (#4246)
This commit updates the wasm-tools family of crates, notably pulling in the refactorings and updates from bytecodealliance/wasm-tools#621 for the latest iteration of the component model. This commit additionally updates all support for the component model for these changes, notably: * Many bits and pieces of type information was refactored. Many `FooTypeIndex` namings are now `TypeFooIndex`. Additionally there is now `TypeIndex` as well as `ComponentTypeIndex` for the two type index spaces in a component. * A number of new sections are now processed to handle the core and component variants. * Internal maps were split such as the `funcs` map into `component_funcs` and `funcs` (same for `instances`). * Canonical options are now processed individually instead of one bulk `into` definition. Overall this was not a major update to the internals of handling the component model in Wasmtime. Instead this was mostly a surface-level refactoring to make sure that everything lines up with the new binary format for components. * All text syntax used in tests was updated to the new syntax.
This commit is contained in:
@@ -14,7 +14,7 @@ edition = "2021"
|
||||
anyhow = "1.0"
|
||||
cranelift-entity = { path = "../../cranelift/entity", version = "0.86.0" }
|
||||
wasmtime-types = { path = "../types", version = "0.39.0" }
|
||||
wasmparser = "0.85.0"
|
||||
wasmparser = "0.86.0"
|
||||
indexmap = { version = "1.0.2", features = ["serde-1"] }
|
||||
thiserror = "1.0.4"
|
||||
serde = { version = "1.0.94", features = ["derive"] }
|
||||
|
||||
@@ -291,7 +291,7 @@ pub enum Export {
|
||||
/// function.
|
||||
LiftedFunction {
|
||||
/// The component function type of the function being created.
|
||||
ty: FuncTypeIndex,
|
||||
ty: TypeFuncIndex,
|
||||
/// Which core WebAssembly export is being lifted.
|
||||
func: CoreExport<FuncIndex>,
|
||||
/// Any options, if present, associated with this lifting.
|
||||
|
||||
@@ -41,14 +41,20 @@ pub struct Translation<'data> {
|
||||
/// Modules and how they're defined (either closed-over or imported)
|
||||
modules: PrimaryMap<ModuleIndex, ModuleDef>,
|
||||
|
||||
/// Instances and how they're defined, either as instantiations of modules
|
||||
/// or "synthetically created" as a bag of named items from our other index
|
||||
/// spaces.
|
||||
instances: PrimaryMap<InstanceIndex, InstanceDef<'data>>,
|
||||
/// Instances of components, either direct instantiations or "bundles of
|
||||
/// exports".
|
||||
component_instances: PrimaryMap<ComponentInstanceIndex, ComponentInstanceDef<'data>>,
|
||||
|
||||
/// Both core wasm and component functions, and how they're defined.
|
||||
/// Instances of core wasm modules, either direct instantiations or
|
||||
/// "bundles of exports".
|
||||
module_instances: PrimaryMap<ModuleInstanceIndex, ModuleInstanceDef<'data>>,
|
||||
|
||||
/// The core wasm function index space.
|
||||
funcs: PrimaryMap<FuncIndex, Func<'data>>,
|
||||
|
||||
/// The component function index space.
|
||||
component_funcs: PrimaryMap<ComponentFuncIndex, ComponentFunc<'data>>,
|
||||
|
||||
/// Core wasm globals, always sourced from a previously module instance.
|
||||
globals: PrimaryMap<GlobalIndex, CoreSource<'data>>,
|
||||
|
||||
@@ -100,17 +106,17 @@ enum ModuleDef {
|
||||
/// nothing is known about it except for its type. The `import_index`
|
||||
/// provided here indexes into the `Component`'s import list.
|
||||
Import {
|
||||
ty: ModuleTypeIndex,
|
||||
ty: TypeModuleIndex,
|
||||
import: RuntimeImport,
|
||||
},
|
||||
}
|
||||
|
||||
/// How instances are defined within a component.
|
||||
/// Forms of creation of a core wasm module instance.
|
||||
#[derive(Debug, Clone)]
|
||||
enum InstanceDef<'data> {
|
||||
enum ModuleInstanceDef<'data> {
|
||||
/// A module instance created through the instantiation of a previous
|
||||
/// module.
|
||||
Module {
|
||||
Instantiated {
|
||||
/// The runtime index associated with this instance.
|
||||
///
|
||||
/// Not to be confused with `InstanceIndex` which counts "synthetic"
|
||||
@@ -123,41 +129,27 @@ enum InstanceDef<'data> {
|
||||
|
||||
/// A "synthetic" module created as a bag of exports from other items
|
||||
/// already defined within this component.
|
||||
ModuleSynthetic(HashMap<&'data str, EntityIndex>),
|
||||
Synthetic(HashMap<&'data str, EntityIndex>),
|
||||
}
|
||||
|
||||
/// Forms of creation of a component instance.
|
||||
#[derive(Debug, Clone)]
|
||||
enum ComponentInstanceDef<'data> {
|
||||
/// An instance which was imported from the host.
|
||||
Import {
|
||||
/// The type of the imported instance
|
||||
ty: ComponentInstanceTypeIndex,
|
||||
ty: TypeComponentInstanceIndex,
|
||||
/// The description of where this import came from.
|
||||
import: RuntimeImport,
|
||||
},
|
||||
|
||||
/// Same as `ModuleSynthetic` except for component items.
|
||||
ComponentSynthetic(HashMap<&'data str, ComponentItem>),
|
||||
/// Same as `ModuleInstanceDef::Synthetic` except for component items.
|
||||
Synthetic(HashMap<&'data str, ComponentItem>),
|
||||
}
|
||||
|
||||
/// Description of the function index space and how functions are defined.
|
||||
#[derive(Clone)]
|
||||
enum Func<'data> {
|
||||
// component functions
|
||||
//
|
||||
/// A component function that is imported from the host.
|
||||
Import(RuntimeImport),
|
||||
|
||||
/// A component function that is lifted from core wasm function.
|
||||
Lifted {
|
||||
/// The resulting type of the lifted function
|
||||
ty: FuncTypeIndex,
|
||||
/// Which core wasm function is lifted, currently required to be an
|
||||
/// instance export as opposed to a lowered import.
|
||||
func: CoreSource<'data>,
|
||||
/// The options specified when the function was lifted.
|
||||
options: CanonicalOptions,
|
||||
},
|
||||
|
||||
// core function
|
||||
//
|
||||
/// A core wasm function that's extracted from a core wasm instance.
|
||||
Core(CoreSource<'data>),
|
||||
/// A core wasm function created by lowering an imported host function.
|
||||
@@ -167,6 +159,24 @@ enum Func<'data> {
|
||||
Lowered(LoweredIndex),
|
||||
}
|
||||
|
||||
/// Description of the function index space and how functions are defined.
|
||||
#[derive(Clone)]
|
||||
enum ComponentFunc<'data> {
|
||||
/// A component function that is imported from the host.
|
||||
Import(RuntimeImport),
|
||||
|
||||
/// A component function that is lifted from core wasm function.
|
||||
Lifted {
|
||||
/// The resulting type of the lifted function
|
||||
ty: TypeFuncIndex,
|
||||
/// Which core wasm function is lifted, currently required to be an
|
||||
/// instance export as opposed to a lowered import.
|
||||
func: CoreSource<'data>,
|
||||
/// The options specified when the function was lifted.
|
||||
options: CanonicalOptions,
|
||||
},
|
||||
}
|
||||
|
||||
/// Source of truth for where a core wasm item comes from.
|
||||
#[derive(Clone)]
|
||||
enum CoreSource<'data> {
|
||||
@@ -278,7 +288,7 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
|
||||
// Push a new scope for component types so outer aliases know
|
||||
// that the 0th level is this new component.
|
||||
self.types.push_component_types_scope();
|
||||
self.types.push_type_scope();
|
||||
}
|
||||
|
||||
Payload::End(offset) => {
|
||||
@@ -304,7 +314,7 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
// When leaving a module be sure to pop the types scope to
|
||||
// ensure that when we go back to the previous module outer
|
||||
// type alias indices work correctly again.
|
||||
self.types.pop_component_types_scope();
|
||||
self.types.pop_type_scope();
|
||||
|
||||
match self.parsers.pop() {
|
||||
Some(p) => self.parser = p,
|
||||
@@ -323,17 +333,23 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
Payload::ComponentTypeSection(s) => {
|
||||
self.validator.component_type_section(&s)?;
|
||||
for ty in s {
|
||||
let ty = self.types.component_type_def(&ty?)?;
|
||||
let ty = self.types.intern_component_type(&ty?)?;
|
||||
self.types.push_component_typedef(ty);
|
||||
}
|
||||
}
|
||||
Payload::CoreTypeSection(s) => {
|
||||
self.validator.core_type_section(&s)?;
|
||||
for ty in s {
|
||||
let ty = self.types.intern_core_type(&ty?)?;
|
||||
self.types.push_core_typedef(ty);
|
||||
}
|
||||
}
|
||||
|
||||
Payload::ComponentImportSection(s) => {
|
||||
self.validator.component_import_section(&s)?;
|
||||
for import in s {
|
||||
let import = import?;
|
||||
let ty = TypeIndex::from_u32(import.ty);
|
||||
let ty = self.types.component_outer_type(0, ty);
|
||||
let ty = self.types.component_type_ref(&import.ty);
|
||||
// Record the `ImportIndex` to be associated with this
|
||||
// import and create the `RuntimeImport` representing the
|
||||
// "root" where it has no extra `exports`
|
||||
@@ -352,11 +368,13 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
}
|
||||
TypeDef::ComponentInstance(ty) => {
|
||||
self.result
|
||||
.instances
|
||||
.push(InstanceDef::Import { ty, import });
|
||||
.component_instances
|
||||
.push(ComponentInstanceDef::Import { ty, import });
|
||||
}
|
||||
TypeDef::Func(_ty) => {
|
||||
self.result.funcs.push(Func::Import(import));
|
||||
TypeDef::ComponentFunc(_ty) => {
|
||||
self.result
|
||||
.component_funcs
|
||||
.push(ComponentFunc::Import(import));
|
||||
}
|
||||
TypeDef::Component(_) => {
|
||||
unimplemented!("imports of components");
|
||||
@@ -364,32 +382,36 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
TypeDef::Interface(_) => {
|
||||
unimplemented!("imports of types");
|
||||
}
|
||||
|
||||
// not possible with a valid component
|
||||
TypeDef::CoreFunc(_ty) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Payload::ComponentFunctionSection(s) => {
|
||||
self.validator.component_function_section(&s)?;
|
||||
Payload::ComponentCanonicalSection(s) => {
|
||||
self.validator.component_canonical_section(&s)?;
|
||||
for func in s {
|
||||
let func = match func? {
|
||||
wasmparser::ComponentFunction::Lift {
|
||||
match func? {
|
||||
wasmparser::CanonicalFunction::Lift {
|
||||
type_index,
|
||||
core_func_index,
|
||||
options,
|
||||
} => {
|
||||
let ty = ComponentTypeIndex::from_u32(type_index);
|
||||
let func = FuncIndex::from_u32(core_func_index);
|
||||
let func = self.lift_function(ty, func, &options);
|
||||
self.result.component_funcs.push(func);
|
||||
}
|
||||
wasmparser::CanonicalFunction::Lower {
|
||||
func_index,
|
||||
options,
|
||||
} => {
|
||||
let ty = TypeIndex::from_u32(type_index);
|
||||
let func = FuncIndex::from_u32(func_index);
|
||||
self.lift_function(ty, func, &options)
|
||||
let func = ComponentFuncIndex::from_u32(func_index);
|
||||
let func = self.lower_function(func, &options);
|
||||
self.result.funcs.push(func);
|
||||
}
|
||||
wasmparser::ComponentFunction::Lower {
|
||||
func_index,
|
||||
options,
|
||||
} => {
|
||||
let func = FuncIndex::from_u32(func_index);
|
||||
self.lower_function(func, &options)
|
||||
}
|
||||
};
|
||||
self.result.funcs.push(func);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,21 +447,33 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
self.validator.instance_section(&s)?;
|
||||
for instance in s {
|
||||
let instance = match instance? {
|
||||
wasmparser::Instance::Module { index, args } => {
|
||||
self.module_instance(ModuleIndex::from_u32(index), &args)
|
||||
wasmparser::Instance::Instantiate { module_index, args } => {
|
||||
self.instantiate_module(ModuleIndex::from_u32(module_index), &args)
|
||||
}
|
||||
wasmparser::Instance::ModuleFromExports(exports) => {
|
||||
self.module_instance_from_exports(&exports)
|
||||
wasmparser::Instance::FromExports(exports) => {
|
||||
self.instantiate_module_from_exports(&exports)
|
||||
}
|
||||
wasmparser::Instance::Component { index, args } => {
|
||||
};
|
||||
self.result.module_instances.push(instance);
|
||||
}
|
||||
}
|
||||
Payload::ComponentInstanceSection(s) => {
|
||||
self.validator.component_instance_section(&s)?;
|
||||
for instance in s {
|
||||
let instance = match instance? {
|
||||
wasmparser::ComponentInstance::Instantiate {
|
||||
component_index,
|
||||
args,
|
||||
} => {
|
||||
let index = ComponentIndex::from_u32(component_index);
|
||||
drop((index, args));
|
||||
unimplemented!("instantiating a component");
|
||||
}
|
||||
wasmparser::Instance::ComponentFromExports(exports) => {
|
||||
self.component_instance_from_exports(&exports)
|
||||
wasmparser::ComponentInstance::FromExports(exports) => {
|
||||
self.instantiate_component_from_exports(&exports)
|
||||
}
|
||||
};
|
||||
self.result.instances.push(instance);
|
||||
self.result.component_instances.push(instance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,7 +492,35 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
Payload::AliasSection(s) => {
|
||||
self.validator.alias_section(&s)?;
|
||||
for alias in s {
|
||||
self.alias(&alias?);
|
||||
match alias? {
|
||||
wasmparser::Alias::InstanceExport {
|
||||
kind,
|
||||
instance_index,
|
||||
name,
|
||||
} => {
|
||||
let instance = ModuleInstanceIndex::from_u32(instance_index);
|
||||
self.alias_module_instance_export(kind, instance, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Payload::ComponentAliasSection(s) => {
|
||||
self.validator.component_alias_section(&s)?;
|
||||
for alias in s {
|
||||
match alias? {
|
||||
wasmparser::ComponentAlias::InstanceExport {
|
||||
kind,
|
||||
instance_index,
|
||||
name,
|
||||
} => {
|
||||
let instance = ComponentInstanceIndex::from_u32(instance_index);
|
||||
self.alias_component_instance_export(kind, instance, name);
|
||||
}
|
||||
wasmparser::ComponentAlias::Outer { kind, count, index } => {
|
||||
self.alias_component_outer(kind, count, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,17 +544,18 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
Ok(Action::KeepGoing)
|
||||
}
|
||||
|
||||
fn module_instance(
|
||||
fn instantiate_module(
|
||||
&mut self,
|
||||
module: ModuleIndex,
|
||||
args: &[wasmparser::ModuleArg<'data>],
|
||||
) -> InstanceDef<'data> {
|
||||
args: &[wasmparser::InstantiationArg<'data>],
|
||||
) -> ModuleInstanceDef<'data> {
|
||||
// Map the flat list of `args` to instead a name-to-instance index.
|
||||
let mut instance_by_name = HashMap::new();
|
||||
for arg in args {
|
||||
match arg.kind {
|
||||
wasmparser::ModuleArgKind::Instance(idx) => {
|
||||
instance_by_name.insert(arg.name, InstanceIndex::from_u32(idx));
|
||||
wasmparser::InstantiationArgKind::Instance => {
|
||||
let idx = ModuleInstanceIndex::from_u32(arg.index);
|
||||
instance_by_name.insert(arg.name, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -544,7 +607,7 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
|
||||
let instance = RuntimeInstanceIndex::from_u32(self.result.component.num_runtime_instances);
|
||||
self.result.component.num_runtime_instances += 1;
|
||||
InstanceDef::Module { instance, module }
|
||||
ModuleInstanceDef::Instantiated { instance, module }
|
||||
}
|
||||
|
||||
/// Calculate the `CoreDef`, a definition of a core wasm item, corresponding
|
||||
@@ -555,28 +618,22 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
/// we know the module), one that must be referred to by name since the
|
||||
/// module isn't known, or it's a synthesized lowering or adapter of a
|
||||
/// component function.
|
||||
fn lookup_core_def(&mut self, instance: InstanceIndex, name: &str) -> CoreDef {
|
||||
match &self.result.instances[instance] {
|
||||
InstanceDef::Module { module, instance } => {
|
||||
fn lookup_core_def(&mut self, instance: ModuleInstanceIndex, name: &str) -> CoreDef {
|
||||
match &self.result.module_instances[instance] {
|
||||
ModuleInstanceDef::Instantiated { module, instance } => {
|
||||
let (src, _ty) = self.lookup_core_source_in_module(*instance, *module, name);
|
||||
src.to_core_def()
|
||||
}
|
||||
|
||||
InstanceDef::ModuleSynthetic(defs) => match defs[&name] {
|
||||
ModuleInstanceDef::Synthetic(defs) => match defs[&name] {
|
||||
EntityIndex::Function(f) => match self.result.funcs[f].clone() {
|
||||
Func::Core(c) => c.to_core_def(),
|
||||
Func::Lowered(i) => CoreDef::Lowered(i),
|
||||
|
||||
// should not be possible to hit with a valid component
|
||||
Func::Lifted { .. } | Func::Import { .. } => unreachable!(),
|
||||
},
|
||||
EntityIndex::Global(g) => self.result.globals[g].to_core_def(),
|
||||
EntityIndex::Table(t) => self.result.tables[t].to_core_def(),
|
||||
EntityIndex::Memory(m) => self.result.memories[m].to_core_def(),
|
||||
},
|
||||
|
||||
// should not be possible to hit with a valid component
|
||||
InstanceDef::Import { .. } | InstanceDef::ComponentSynthetic(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,10 +673,10 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
|
||||
/// Creates a synthetic module from the list of items currently in the
|
||||
/// module and their given names.
|
||||
fn module_instance_from_exports(
|
||||
fn instantiate_module_from_exports(
|
||||
&mut self,
|
||||
exports: &[wasmparser::Export<'data>],
|
||||
) -> InstanceDef<'data> {
|
||||
) -> ModuleInstanceDef<'data> {
|
||||
let mut map = HashMap::with_capacity(exports.len());
|
||||
for export in exports {
|
||||
let idx = match export.kind {
|
||||
@@ -645,51 +702,51 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
};
|
||||
map.insert(export.name, idx);
|
||||
}
|
||||
InstanceDef::ModuleSynthetic(map)
|
||||
ModuleInstanceDef::Synthetic(map)
|
||||
}
|
||||
|
||||
/// Creates a synthetic module from the list of items currently in the
|
||||
/// module and their given names.
|
||||
fn component_instance_from_exports(
|
||||
fn instantiate_component_from_exports(
|
||||
&mut self,
|
||||
exports: &[wasmparser::ComponentExport<'data>],
|
||||
) -> InstanceDef<'data> {
|
||||
) -> ComponentInstanceDef<'data> {
|
||||
let mut map = HashMap::with_capacity(exports.len());
|
||||
for export in exports {
|
||||
let idx = match &export.kind {
|
||||
wasmparser::ComponentArgKind::Function(i) => {
|
||||
let index = FuncIndex::from_u32(*i);
|
||||
wasmparser::ComponentExternalKind::Func => {
|
||||
let index = FuncIndex::from_u32(export.index);
|
||||
ComponentItem::Func(index)
|
||||
}
|
||||
wasmparser::ComponentArgKind::Module(i) => {
|
||||
let index = ModuleIndex::from_u32(*i);
|
||||
wasmparser::ComponentExternalKind::Module => {
|
||||
let index = ModuleIndex::from_u32(export.index);
|
||||
ComponentItem::Module(index)
|
||||
}
|
||||
wasmparser::ComponentArgKind::Instance(i) => {
|
||||
let index = InstanceIndex::from_u32(*i);
|
||||
ComponentItem::Instance(index)
|
||||
wasmparser::ComponentExternalKind::Instance => {
|
||||
let index = ComponentInstanceIndex::from_u32(export.index);
|
||||
ComponentItem::ComponentInstance(index)
|
||||
}
|
||||
wasmparser::ComponentArgKind::Component(i) => {
|
||||
let index = ComponentIndex::from_u32(*i);
|
||||
wasmparser::ComponentExternalKind::Component => {
|
||||
let index = ComponentIndex::from_u32(export.index);
|
||||
ComponentItem::Component(index)
|
||||
}
|
||||
wasmparser::ComponentArgKind::Value(_) => {
|
||||
wasmparser::ComponentExternalKind::Value => {
|
||||
unimplemented!("component values");
|
||||
}
|
||||
wasmparser::ComponentArgKind::Type(_) => {
|
||||
wasmparser::ComponentExternalKind::Type => {
|
||||
unimplemented!("component type export");
|
||||
}
|
||||
};
|
||||
map.insert(export.name, idx);
|
||||
}
|
||||
InstanceDef::ComponentSynthetic(map)
|
||||
ComponentInstanceDef::Synthetic(map)
|
||||
}
|
||||
|
||||
fn export(&mut self, export: &wasmparser::ComponentExport<'data>) {
|
||||
let name = export.name;
|
||||
let export = match export.kind {
|
||||
wasmparser::ComponentExportKind::Module(i) => {
|
||||
let idx = ModuleIndex::from_u32(i);
|
||||
wasmparser::ComponentExternalKind::Module => {
|
||||
let idx = ModuleIndex::from_u32(export.index);
|
||||
let init = match self.result.modules[idx].clone() {
|
||||
ModuleDef::Upvar(idx) => Initializer::SaveModuleUpvar(idx),
|
||||
ModuleDef::Import { import, .. } => {
|
||||
@@ -702,20 +759,20 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
self.result.component.num_runtime_modules += 1;
|
||||
Export::Module(runtime_index)
|
||||
}
|
||||
wasmparser::ComponentExportKind::Component(i) => {
|
||||
let idx = ComponentIndex::from_u32(i);
|
||||
wasmparser::ComponentExternalKind::Component => {
|
||||
let idx = ComponentIndex::from_u32(export.index);
|
||||
drop(idx);
|
||||
unimplemented!("exporting a component");
|
||||
}
|
||||
wasmparser::ComponentExportKind::Instance(i) => {
|
||||
let idx = InstanceIndex::from_u32(i);
|
||||
wasmparser::ComponentExternalKind::Instance => {
|
||||
let idx = ComponentInstanceIndex::from_u32(export.index);
|
||||
drop(idx);
|
||||
unimplemented!("exporting an instance");
|
||||
}
|
||||
wasmparser::ComponentExportKind::Function(i) => {
|
||||
let idx = FuncIndex::from_u32(i);
|
||||
match self.result.funcs[idx].clone() {
|
||||
Func::Lifted { ty, func, options } => Export::LiftedFunction {
|
||||
wasmparser::ComponentExternalKind::Func => {
|
||||
let idx = ComponentFuncIndex::from_u32(export.index);
|
||||
match self.result.component_funcs[idx].clone() {
|
||||
ComponentFunc::Lifted { ty, func, options } => Export::LiftedFunction {
|
||||
ty,
|
||||
func: func.to_core_export(|i| match i {
|
||||
EntityIndex::Function(i) => i,
|
||||
@@ -741,17 +798,14 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
// Nevertheless this shouldn't panic, eventually when the
|
||||
// component model implementation is finished this should do
|
||||
// something reasonable.
|
||||
Func::Import { .. } => unimplemented!("exporting an import"),
|
||||
|
||||
// should not be possible to hit with a valid module.
|
||||
Func::Core(_) | Func::Lowered(_) => unreachable!(),
|
||||
ComponentFunc::Import { .. } => unimplemented!("exporting an import"),
|
||||
}
|
||||
}
|
||||
wasmparser::ComponentExportKind::Value(_) => {
|
||||
wasmparser::ComponentExternalKind::Value => {
|
||||
unimplemented!("exporting a value");
|
||||
}
|
||||
wasmparser::ComponentExportKind::Type(i) => {
|
||||
let idx = TypeIndex::from_u32(i);
|
||||
wasmparser::ComponentExternalKind::Type => {
|
||||
let idx = TypeIndex::from_u32(export.index);
|
||||
drop(idx);
|
||||
unimplemented!("exporting a type");
|
||||
}
|
||||
@@ -762,23 +816,132 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
.insert(name.to_string(), export);
|
||||
}
|
||||
|
||||
fn alias(&mut self, alias: &wasmparser::Alias<'data>) {
|
||||
match alias {
|
||||
wasmparser::Alias::InstanceExport {
|
||||
kind,
|
||||
instance,
|
||||
name,
|
||||
} => {
|
||||
let instance = InstanceIndex::from_u32(*instance);
|
||||
self.alias_instance_export(*kind, instance, name);
|
||||
}
|
||||
wasmparser::Alias::OuterModule { .. } => {
|
||||
unimplemented!("alias outer module");
|
||||
}
|
||||
wasmparser::Alias::OuterComponent { .. } => {
|
||||
unimplemented!("alias outer component");
|
||||
fn alias_module_instance_export(
|
||||
&mut self,
|
||||
kind: wasmparser::ExternalKind,
|
||||
instance: ModuleInstanceIndex,
|
||||
name: &'data str,
|
||||
) {
|
||||
match &self.result.module_instances[instance] {
|
||||
// The `instance` points to an instantiated module, meaning we can
|
||||
// lookup the `CoreSource` associated with it and use the type
|
||||
// information to insert it into the appropriate namespace.
|
||||
ModuleInstanceDef::Instantiated { instance, module } => {
|
||||
let (src, ty) = self.lookup_core_source_in_module(*instance, *module, name);
|
||||
match ty {
|
||||
EntityType::Function(_) => {
|
||||
assert_eq!(kind, wasmparser::ExternalKind::Func);
|
||||
self.result.funcs.push(Func::Core(src));
|
||||
}
|
||||
EntityType::Global(_) => {
|
||||
assert_eq!(kind, wasmparser::ExternalKind::Global);
|
||||
self.result.globals.push(src);
|
||||
}
|
||||
EntityType::Memory(_) => {
|
||||
assert_eq!(kind, wasmparser::ExternalKind::Memory);
|
||||
self.result.memories.push(src);
|
||||
}
|
||||
EntityType::Table(_) => {
|
||||
assert_eq!(kind, wasmparser::ExternalKind::Table);
|
||||
self.result.tables.push(src);
|
||||
}
|
||||
EntityType::Tag(_) => unimplemented!("wasm exceptions"),
|
||||
}
|
||||
}
|
||||
|
||||
// ... and like above for synthetic components aliasing exports from
|
||||
// synthetic modules is also just copying around the identifying
|
||||
// information.
|
||||
ModuleInstanceDef::Synthetic(exports) => match exports[&name] {
|
||||
EntityIndex::Function(i) => {
|
||||
assert_eq!(kind, wasmparser::ExternalKind::Func);
|
||||
self.result.funcs.push(self.result.funcs[i].clone());
|
||||
}
|
||||
EntityIndex::Global(i) => {
|
||||
assert_eq!(kind, wasmparser::ExternalKind::Global);
|
||||
self.result.globals.push(self.result.globals[i].clone());
|
||||
}
|
||||
EntityIndex::Table(i) => {
|
||||
assert_eq!(kind, wasmparser::ExternalKind::Table);
|
||||
self.result.tables.push(self.result.tables[i].clone());
|
||||
}
|
||||
EntityIndex::Memory(i) => {
|
||||
assert_eq!(kind, wasmparser::ExternalKind::Memory);
|
||||
self.result.memories.push(self.result.memories[i].clone());
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn alias_component_instance_export(
|
||||
&mut self,
|
||||
kind: wasmparser::ComponentExternalKind,
|
||||
instance: ComponentInstanceIndex,
|
||||
name: &'data str,
|
||||
) {
|
||||
match &self.result.component_instances[instance] {
|
||||
// The `instance` points to an imported component instance, meaning
|
||||
// that the item we're pushing into our index spaces is effectively
|
||||
// another form of import. The `name` is appended to the `import`
|
||||
// found here and then the appropriate namespace of an import is
|
||||
// recorded as well.
|
||||
ComponentInstanceDef::Import { import, ty } => {
|
||||
let import = import.append(name);
|
||||
match self.types[*ty].exports[name] {
|
||||
TypeDef::Module(ty) => {
|
||||
assert_eq!(kind, wasmparser::ComponentExternalKind::Module);
|
||||
self.result.modules.push(ModuleDef::Import { import, ty });
|
||||
}
|
||||
TypeDef::ComponentInstance(ty) => {
|
||||
assert_eq!(kind, wasmparser::ComponentExternalKind::Instance);
|
||||
self.result
|
||||
.component_instances
|
||||
.push(ComponentInstanceDef::Import { import, ty });
|
||||
}
|
||||
TypeDef::ComponentFunc(_ty) => {
|
||||
assert_eq!(kind, wasmparser::ComponentExternalKind::Func);
|
||||
self.result
|
||||
.component_funcs
|
||||
.push(ComponentFunc::Import(import));
|
||||
}
|
||||
TypeDef::Interface(_) => unimplemented!("alias type export"),
|
||||
TypeDef::Component(_) => unimplemented!("alias component export"),
|
||||
|
||||
// not possible with valid components
|
||||
TypeDef::CoreFunc(_ty) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
// For synthetic component/module instances we can just copy the
|
||||
// definition of the original item into a new slot as well to record
|
||||
// that the index describes the same item.
|
||||
ComponentInstanceDef::Synthetic(exports) => match exports[&name] {
|
||||
ComponentItem::Func(i) => {
|
||||
assert_eq!(kind, wasmparser::ComponentExternalKind::Func);
|
||||
self.result.funcs.push(self.result.funcs[i].clone());
|
||||
}
|
||||
ComponentItem::Module(i) => {
|
||||
assert_eq!(kind, wasmparser::ComponentExternalKind::Module);
|
||||
self.result.modules.push(self.result.modules[i].clone());
|
||||
}
|
||||
ComponentItem::ComponentInstance(i) => {
|
||||
assert_eq!(kind, wasmparser::ComponentExternalKind::Instance);
|
||||
self.result
|
||||
.component_instances
|
||||
.push(self.result.component_instances[i].clone());
|
||||
}
|
||||
ComponentItem::Component(_) => unimplemented!("aliasing a component export"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn alias_component_outer(
|
||||
&mut self,
|
||||
kind: wasmparser::ComponentOuterAliasKind,
|
||||
count: u32,
|
||||
index: u32,
|
||||
) {
|
||||
match kind {
|
||||
// When aliasing a type the `ComponentTypesBuilder` is used to
|
||||
// resolve the outer `count` plus the index, and then once it's
|
||||
// resolved we push the type information into our local index
|
||||
@@ -787,125 +950,34 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
// Note that this is just copying indices around as all type
|
||||
// information is basically a pointer back into the `TypesBuilder`
|
||||
// structure (and the eventual `TypeTables` that it produces).
|
||||
wasmparser::Alias::OuterType { count, index } => {
|
||||
let index = TypeIndex::from_u32(*index);
|
||||
let ty = self.types.component_outer_type(*count, index);
|
||||
wasmparser::ComponentOuterAliasKind::CoreType => {
|
||||
let index = TypeIndex::from_u32(index);
|
||||
let ty = self.types.core_outer_type(count, index);
|
||||
self.types.push_core_typedef(ty);
|
||||
}
|
||||
wasmparser::ComponentOuterAliasKind::Type => {
|
||||
let index = ComponentTypeIndex::from_u32(index);
|
||||
let ty = self.types.component_outer_type(count, index);
|
||||
self.types.push_component_typedef(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn alias_instance_export(
|
||||
&mut self,
|
||||
kind: wasmparser::AliasKind,
|
||||
instance: InstanceIndex,
|
||||
name: &'data str,
|
||||
) {
|
||||
match &self.result.instances[instance] {
|
||||
// The `instance` points to an imported component instance, meaning
|
||||
// that the item we're pushing into our index spaces is effectively
|
||||
// another form of import. The `name` is appended to the `import`
|
||||
// found here and then the appropriate namespace of an import is
|
||||
// recorded as well.
|
||||
InstanceDef::Import { import, ty } => {
|
||||
let import = import.append(name);
|
||||
match self.types[*ty].exports[name] {
|
||||
TypeDef::Module(ty) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Module);
|
||||
self.result.modules.push(ModuleDef::Import { import, ty });
|
||||
}
|
||||
TypeDef::ComponentInstance(ty) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Instance);
|
||||
self.result
|
||||
.instances
|
||||
.push(InstanceDef::Import { import, ty });
|
||||
}
|
||||
TypeDef::Func(_ty) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::ComponentFunc);
|
||||
self.result.funcs.push(Func::Import(import));
|
||||
}
|
||||
TypeDef::Interface(_) => unimplemented!("alias type export"),
|
||||
TypeDef::Component(_) => unimplemented!("alias component export"),
|
||||
}
|
||||
wasmparser::ComponentOuterAliasKind::CoreModule => {
|
||||
unimplemented!("outer alias to module");
|
||||
}
|
||||
|
||||
// The `instance` points to an instantiated module, meaning we can
|
||||
// lookup the `CoreSource` associated with it and use the type
|
||||
// information to insert it into the appropriate namespace.
|
||||
InstanceDef::Module { instance, module } => {
|
||||
let (src, ty) = self.lookup_core_source_in_module(*instance, *module, name);
|
||||
match ty {
|
||||
EntityType::Function(_) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Func);
|
||||
self.result.funcs.push(Func::Core(src));
|
||||
}
|
||||
EntityType::Global(_) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Global);
|
||||
self.result.globals.push(src);
|
||||
}
|
||||
EntityType::Memory(_) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Memory);
|
||||
self.result.memories.push(src);
|
||||
}
|
||||
EntityType::Table(_) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Table);
|
||||
self.result.tables.push(src);
|
||||
}
|
||||
EntityType::Tag(_) => unimplemented!("wasm exceptions"),
|
||||
}
|
||||
wasmparser::ComponentOuterAliasKind::Component => {
|
||||
unimplemented!("outer alias to component");
|
||||
}
|
||||
|
||||
// For synthetic component/module instances we can just copy the
|
||||
// definition of the original item into a new slot as well to record
|
||||
// that the index describes the same item.
|
||||
InstanceDef::ComponentSynthetic(exports) => match exports[&name] {
|
||||
ComponentItem::Func(i) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::ComponentFunc);
|
||||
self.result.funcs.push(self.result.funcs[i].clone());
|
||||
}
|
||||
ComponentItem::Module(i) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Module);
|
||||
self.result.modules.push(self.result.modules[i].clone());
|
||||
}
|
||||
ComponentItem::Instance(i) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Instance);
|
||||
self.result.instances.push(self.result.instances[i].clone());
|
||||
}
|
||||
ComponentItem::Component(_) => unimplemented!("aliasing a component export"),
|
||||
},
|
||||
|
||||
// ... and like above for synthetic components aliasing exports from
|
||||
// synthetic modules is also just copying around the identifying
|
||||
// information.
|
||||
InstanceDef::ModuleSynthetic(exports) => match exports[&name] {
|
||||
EntityIndex::Function(i) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Func);
|
||||
self.result.funcs.push(self.result.funcs[i].clone());
|
||||
}
|
||||
EntityIndex::Global(i) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Global);
|
||||
self.result.globals.push(self.result.globals[i].clone());
|
||||
}
|
||||
EntityIndex::Table(i) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Table);
|
||||
self.result.tables.push(self.result.tables[i].clone());
|
||||
}
|
||||
EntityIndex::Memory(i) => {
|
||||
assert_eq!(kind, wasmparser::AliasKind::Memory);
|
||||
self.result.memories.push(self.result.memories[i].clone());
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn lift_function(
|
||||
&mut self,
|
||||
ty: TypeIndex,
|
||||
ty: ComponentTypeIndex,
|
||||
func: FuncIndex,
|
||||
options: &[wasmparser::CanonicalOption],
|
||||
) -> Func<'data> {
|
||||
) -> ComponentFunc<'data> {
|
||||
let ty = match self.types.component_outer_type(0, ty) {
|
||||
TypeDef::Func(ty) => ty,
|
||||
TypeDef::ComponentFunc(ty) => ty,
|
||||
// should not be possible after validation
|
||||
_ => unreachable!(),
|
||||
};
|
||||
@@ -919,22 +991,19 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
// memory into core wasm (since nothing is around to call
|
||||
// deallocation/free functions).
|
||||
Func::Lowered(_) => unimplemented!("lifting a lowered function"),
|
||||
|
||||
// should not be possible after validation
|
||||
Func::Lifted { .. } | Func::Import { .. } => unreachable!(),
|
||||
};
|
||||
let options = self.canonical_options(options);
|
||||
Func::Lifted { ty, func, options }
|
||||
ComponentFunc::Lifted { ty, func, options }
|
||||
}
|
||||
|
||||
fn lower_function(
|
||||
&mut self,
|
||||
func: FuncIndex,
|
||||
func: ComponentFuncIndex,
|
||||
options: &[wasmparser::CanonicalOption],
|
||||
) -> Func<'data> {
|
||||
let options = self.canonical_options(options);
|
||||
match self.result.funcs[func].clone() {
|
||||
Func::Import(import) => {
|
||||
match self.result.component_funcs[func].clone() {
|
||||
ComponentFunc::Import(import) => {
|
||||
let import = self.runtime_import_index(import);
|
||||
let index = LoweredIndex::from_u32(self.result.component.num_lowerings);
|
||||
self.result.component.num_lowerings += 1;
|
||||
@@ -961,10 +1030,7 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
// function that lifts the arguments and then afterwards
|
||||
// unconditionally traps. That would mean that this validates the
|
||||
// arguments within the context of `options` and then traps.
|
||||
Func::Lifted { .. } => unimplemented!("lower a lifted function"),
|
||||
|
||||
// should not be possible after validation
|
||||
Func::Core(_) | Func::Lowered(_) => unreachable!(),
|
||||
ComponentFunc::Lifted { .. } => unimplemented!("lower a lifted function"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -981,24 +1047,24 @@ impl<'a, 'data> Translator<'a, 'data> {
|
||||
wasmparser::CanonicalOption::CompactUTF16 => {
|
||||
ret.string_encoding = StringEncoding::CompactUtf16;
|
||||
}
|
||||
wasmparser::CanonicalOption::Into(instance) => {
|
||||
let instance = InstanceIndex::from_u32(*instance);
|
||||
|
||||
// Note that the `unreachable!()` should not happen for
|
||||
// components which have passed validation.
|
||||
let memory =
|
||||
self.lookup_core_def(instance, "memory")
|
||||
.unwrap_export(|i| match i {
|
||||
EntityIndex::Memory(i) => i,
|
||||
_ => unreachable!(),
|
||||
});
|
||||
wasmparser::CanonicalOption::Memory(idx) => {
|
||||
let idx = MemoryIndex::from_u32(*idx);
|
||||
let memory = self.result.memories[idx].to_core_export(|i| match i {
|
||||
EntityIndex::Memory(i) => i,
|
||||
_ => unreachable!(),
|
||||
});
|
||||
let memory = self.runtime_memory(memory);
|
||||
ret.memory = Some(memory);
|
||||
|
||||
let realloc = self.lookup_core_def(instance, "canonical_abi_realloc");
|
||||
}
|
||||
wasmparser::CanonicalOption::Realloc(idx) => {
|
||||
let idx = FuncIndex::from_u32(*idx);
|
||||
let realloc = self.result.funcs[idx].to_core_def();
|
||||
let realloc = self.runtime_realloc(realloc);
|
||||
ret.realloc = Some(realloc);
|
||||
}
|
||||
wasmparser::CanonicalOption::PostReturn(_) => {
|
||||
unimplemented!("post-return");
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@@ -1065,22 +1131,11 @@ impl CoreSource<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl CoreDef {
|
||||
fn unwrap_export<T>(self, get_index: impl FnOnce(EntityIndex) -> T) -> CoreExport<T> {
|
||||
let export = match self {
|
||||
CoreDef::Export(export) => export,
|
||||
CoreDef::Lowered(_) => unreachable!(),
|
||||
};
|
||||
let instance = export.instance;
|
||||
match export.item {
|
||||
ExportItem::Index(idx) => CoreExport {
|
||||
instance,
|
||||
item: ExportItem::Index(get_index(idx)),
|
||||
},
|
||||
ExportItem::Name(name) => CoreExport {
|
||||
instance,
|
||||
item: ExportItem::Name(name),
|
||||
},
|
||||
impl Func<'_> {
|
||||
fn to_core_def(&self) -> CoreDef {
|
||||
match self {
|
||||
Func::Core(src) => src.to_core_def(),
|
||||
Func::Lowered(idx) => CoreDef::Lowered(*idx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use std::ops::Index;
|
||||
use wasmparser::{
|
||||
ComponentAlias, ComponentOuterAliasKind, ComponentTypeDeclaration, InstanceTypeDeclaration,
|
||||
};
|
||||
|
||||
macro_rules! indices {
|
||||
($(
|
||||
@@ -31,14 +34,23 @@ indices! {
|
||||
// compile phase to when we're actually working with the component at
|
||||
// runtime.
|
||||
|
||||
/// Index within a component's component type index space.
|
||||
pub struct ComponentTypeIndex(u32);
|
||||
|
||||
/// Index within a component's module index space.
|
||||
pub struct ModuleIndex(u32);
|
||||
|
||||
/// Index within a component's component index space.
|
||||
pub struct ComponentIndex(u32);
|
||||
|
||||
/// Index within a component's instance index space.
|
||||
pub struct InstanceIndex(u32);
|
||||
/// Index within a component's module instance index space.
|
||||
pub struct ModuleInstanceIndex(u32);
|
||||
|
||||
/// Index within a component's component instance index space.
|
||||
pub struct ComponentInstanceIndex(u32);
|
||||
|
||||
/// Index within a component's component function index space.
|
||||
pub struct ComponentFuncIndex(u32);
|
||||
|
||||
// ========================================================================
|
||||
// These indices are used to lookup type information within a `TypeTables`
|
||||
@@ -47,39 +59,39 @@ indices! {
|
||||
|
||||
/// Index pointing to a component's type (exports/imports with
|
||||
/// component-model types)
|
||||
pub struct ComponentTypeIndex(u32);
|
||||
pub struct TypeComponentIndex(u32);
|
||||
|
||||
/// Index pointing to a component instance's type (exports with
|
||||
/// component-model types, no imports)
|
||||
pub struct ComponentInstanceTypeIndex(u32);
|
||||
pub struct TypeComponentInstanceIndex(u32);
|
||||
|
||||
/// Index pointing to a core wasm module's type (exports/imports with
|
||||
/// core wasm types)
|
||||
pub struct ModuleTypeIndex(u32);
|
||||
pub struct TypeModuleIndex(u32);
|
||||
|
||||
/// Index pointing to a component model function type with arguments/result
|
||||
/// as interface types.
|
||||
pub struct FuncTypeIndex(u32);
|
||||
pub struct TypeFuncIndex(u32);
|
||||
|
||||
/// Index pointing to an interface type, used for recursive types such as
|
||||
/// `List<T>`.
|
||||
pub struct InterfaceTypeIndex(u32);
|
||||
pub struct TypeInterfaceIndex(u32);
|
||||
|
||||
/// Index pointing to a record type in the component model (aka a struct).
|
||||
pub struct RecordTypeIndex(u32);
|
||||
pub struct TypeRecordIndex(u32);
|
||||
/// Index pointing to a variant type in the component model (aka an enum).
|
||||
pub struct VariantTypeIndex(u32);
|
||||
pub struct TypeVariantIndex(u32);
|
||||
/// Index pointing to a tuple type in the component model.
|
||||
pub struct TupleTypeIndex(u32);
|
||||
pub struct TypeTupleIndex(u32);
|
||||
/// Index pointing to a flags type in the component model.
|
||||
pub struct FlagsTypeIndex(u32);
|
||||
pub struct TypeFlagsIndex(u32);
|
||||
/// Index pointing to an enum type in the component model.
|
||||
pub struct EnumTypeIndex(u32);
|
||||
pub struct TypeEnumIndex(u32);
|
||||
/// Index pointing to a union type in the component model.
|
||||
pub struct UnionTypeIndex(u32);
|
||||
pub struct TypeUnionIndex(u32);
|
||||
/// Index pointing to an expected type in the component model (aka a
|
||||
/// `Result<T, E>`)
|
||||
pub struct ExpectedTypeIndex(u32);
|
||||
pub struct TypeExpectedIndex(u32);
|
||||
|
||||
// ========================================================================
|
||||
// These indices are actually used at runtime when managing a component at
|
||||
@@ -147,8 +159,8 @@ pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex, TypeIndex};
|
||||
pub enum ComponentItem {
|
||||
Func(FuncIndex),
|
||||
Module(ModuleIndex),
|
||||
Instance(InstanceIndex),
|
||||
Component(ComponentIndex),
|
||||
ComponentInstance(ComponentInstanceIndex),
|
||||
}
|
||||
|
||||
/// Runtime information about the type information contained within a component.
|
||||
@@ -158,18 +170,18 @@ pub enum ComponentItem {
|
||||
/// will have a pointer to this value as well.
|
||||
#[derive(Default, Serialize, Deserialize)]
|
||||
pub struct ComponentTypes {
|
||||
modules: PrimaryMap<ModuleTypeIndex, ModuleType>,
|
||||
components: PrimaryMap<ComponentTypeIndex, ComponentType>,
|
||||
component_instances: PrimaryMap<ComponentInstanceTypeIndex, ComponentInstanceType>,
|
||||
functions: PrimaryMap<FuncTypeIndex, FuncType>,
|
||||
interface_types: PrimaryMap<InterfaceTypeIndex, InterfaceType>,
|
||||
records: PrimaryMap<RecordTypeIndex, RecordType>,
|
||||
variants: PrimaryMap<VariantTypeIndex, VariantType>,
|
||||
tuples: PrimaryMap<TupleTypeIndex, TupleType>,
|
||||
enums: PrimaryMap<EnumTypeIndex, EnumType>,
|
||||
flags: PrimaryMap<FlagsTypeIndex, FlagsType>,
|
||||
unions: PrimaryMap<UnionTypeIndex, UnionType>,
|
||||
expecteds: PrimaryMap<ExpectedTypeIndex, ExpectedType>,
|
||||
modules: PrimaryMap<TypeModuleIndex, TypeModule>,
|
||||
components: PrimaryMap<TypeComponentIndex, TypeComponent>,
|
||||
component_instances: PrimaryMap<TypeComponentInstanceIndex, TypeComponentInstance>,
|
||||
functions: PrimaryMap<TypeFuncIndex, TypeFunc>,
|
||||
interface_types: PrimaryMap<TypeInterfaceIndex, InterfaceType>,
|
||||
records: PrimaryMap<TypeRecordIndex, TypeRecord>,
|
||||
variants: PrimaryMap<TypeVariantIndex, TypeVariant>,
|
||||
tuples: PrimaryMap<TypeTupleIndex, TypeTuple>,
|
||||
enums: PrimaryMap<TypeEnumIndex, TypeEnum>,
|
||||
flags: PrimaryMap<TypeFlagsIndex, TypeFlags>,
|
||||
unions: PrimaryMap<TypeUnionIndex, TypeUnion>,
|
||||
expecteds: PrimaryMap<TypeExpectedIndex, TypeExpected>,
|
||||
|
||||
module_types: ModuleTypes,
|
||||
}
|
||||
@@ -193,18 +205,18 @@ macro_rules! impl_index {
|
||||
}
|
||||
|
||||
impl_index! {
|
||||
impl Index<ModuleTypeIndex> for ComponentTypes { ModuleType => modules }
|
||||
impl Index<ComponentTypeIndex> for ComponentTypes { ComponentType => components }
|
||||
impl Index<ComponentInstanceTypeIndex> for ComponentTypes { ComponentInstanceType => component_instances }
|
||||
impl Index<FuncTypeIndex> for ComponentTypes { FuncType => functions }
|
||||
impl Index<InterfaceTypeIndex> for ComponentTypes { InterfaceType => interface_types }
|
||||
impl Index<RecordTypeIndex> for ComponentTypes { RecordType => records }
|
||||
impl Index<VariantTypeIndex> for ComponentTypes { VariantType => variants }
|
||||
impl Index<TupleTypeIndex> for ComponentTypes { TupleType => tuples }
|
||||
impl Index<EnumTypeIndex> for ComponentTypes { EnumType => enums }
|
||||
impl Index<FlagsTypeIndex> for ComponentTypes { FlagsType => flags }
|
||||
impl Index<UnionTypeIndex> for ComponentTypes { UnionType => unions }
|
||||
impl Index<ExpectedTypeIndex> for ComponentTypes { ExpectedType => expecteds }
|
||||
impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
|
||||
impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
|
||||
impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
|
||||
impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
|
||||
impl Index<TypeInterfaceIndex> for ComponentTypes { InterfaceType => interface_types }
|
||||
impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
|
||||
impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
|
||||
impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
|
||||
impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
|
||||
impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
|
||||
impl Index<TypeUnionIndex> for ComponentTypes { TypeUnion => unions }
|
||||
impl Index<TypeExpectedIndex> for ComponentTypes { TypeExpected => expecteds }
|
||||
}
|
||||
|
||||
// Additionally forward anything that can index `ModuleTypes` to `ModuleTypes`
|
||||
@@ -225,21 +237,27 @@ where
|
||||
/// managing building up core wasm [`ModuleTypes`] as well.
|
||||
#[derive(Default)]
|
||||
pub struct ComponentTypesBuilder {
|
||||
type_scopes: Vec<PrimaryMap<TypeIndex, TypeDef>>,
|
||||
functions: HashMap<FuncType, FuncTypeIndex>,
|
||||
interface_types: HashMap<InterfaceType, InterfaceTypeIndex>,
|
||||
records: HashMap<RecordType, RecordTypeIndex>,
|
||||
variants: HashMap<VariantType, VariantTypeIndex>,
|
||||
tuples: HashMap<TupleType, TupleTypeIndex>,
|
||||
enums: HashMap<EnumType, EnumTypeIndex>,
|
||||
flags: HashMap<FlagsType, FlagsTypeIndex>,
|
||||
unions: HashMap<UnionType, UnionTypeIndex>,
|
||||
expecteds: HashMap<ExpectedType, ExpectedTypeIndex>,
|
||||
type_scopes: Vec<TypeScope>,
|
||||
functions: HashMap<TypeFunc, TypeFuncIndex>,
|
||||
interface_types: HashMap<InterfaceType, TypeInterfaceIndex>,
|
||||
records: HashMap<TypeRecord, TypeRecordIndex>,
|
||||
variants: HashMap<TypeVariant, TypeVariantIndex>,
|
||||
tuples: HashMap<TypeTuple, TypeTupleIndex>,
|
||||
enums: HashMap<TypeEnum, TypeEnumIndex>,
|
||||
flags: HashMap<TypeFlags, TypeFlagsIndex>,
|
||||
unions: HashMap<TypeUnion, TypeUnionIndex>,
|
||||
expecteds: HashMap<TypeExpected, TypeExpectedIndex>,
|
||||
|
||||
component_types: ComponentTypes,
|
||||
module_types: ModuleTypesBuilder,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TypeScope {
|
||||
core: PrimaryMap<TypeIndex, TypeDef>,
|
||||
component: PrimaryMap<ComponentTypeIndex, TypeDef>,
|
||||
}
|
||||
|
||||
impl ComponentTypesBuilder {
|
||||
/// Finishes this list of component types and returns the finished
|
||||
/// structure.
|
||||
@@ -261,20 +279,36 @@ impl ComponentTypesBuilder {
|
||||
///
|
||||
/// This happens when a component is recursed into or a module/instance
|
||||
/// type is recursed into.
|
||||
pub fn push_component_types_scope(&mut self) {
|
||||
self.type_scopes.push(PrimaryMap::new());
|
||||
pub fn push_type_scope(&mut self) {
|
||||
self.type_scopes.push(Default::default());
|
||||
}
|
||||
|
||||
/// Adds a new `TypeDef` definition within the current component types
|
||||
/// scope.
|
||||
///
|
||||
/// Returns the `TypeIndex` associated with the type being pushed..
|
||||
/// Returns the `ComponentTypeIndex` associated with the type being pushed.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Requires that `push_component_types_scope` was called previously.
|
||||
pub fn push_component_typedef(&mut self, ty: TypeDef) -> TypeIndex {
|
||||
self.type_scopes.last_mut().unwrap().push(ty)
|
||||
/// Requires that `push_type_scope` was called previously.
|
||||
pub fn push_component_typedef(&mut self, ty: TypeDef) -> ComponentTypeIndex {
|
||||
debug_assert!(!matches!(ty, TypeDef::Module(_) | TypeDef::CoreFunc(_)));
|
||||
self.type_scopes.last_mut().unwrap().component.push(ty)
|
||||
}
|
||||
|
||||
/// Adds a new `TypeDef` definition within the current core types
|
||||
/// scope.
|
||||
///
|
||||
/// Returns the `TypeIndex` associated with the type being pushed. Note that
|
||||
/// this should only be used with core-wasm-related `TypeDef` instances such
|
||||
/// as `TypeDef::Module` and `TypeDef::CoreFunc`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Requires that `push_type_scope` was called previously.
|
||||
pub fn push_core_typedef(&mut self, ty: TypeDef) -> TypeIndex {
|
||||
debug_assert!(matches!(ty, TypeDef::Module(_) | TypeDef::CoreFunc(_)));
|
||||
self.type_scopes.last_mut().unwrap().core.push(ty)
|
||||
}
|
||||
|
||||
/// Looks up an "outer" type in this builder to handle outer aliases.
|
||||
@@ -285,52 +319,89 @@ impl ComponentTypesBuilder {
|
||||
/// # Panics
|
||||
///
|
||||
/// Assumes that `count` and `ty` are valid.
|
||||
pub fn component_outer_type(&self, count: u32, ty: TypeIndex) -> TypeDef {
|
||||
pub fn component_outer_type(&self, count: u32, ty: ComponentTypeIndex) -> TypeDef {
|
||||
// Reverse the index and 0 means the "current scope"
|
||||
let idx = self.type_scopes.len() - (count as usize) - 1;
|
||||
self.type_scopes[idx][ty]
|
||||
self.type_scopes[idx].component[ty]
|
||||
}
|
||||
|
||||
/// Pops a scope pushed by `push_component_types_scope`.
|
||||
pub fn pop_component_types_scope(&mut self) {
|
||||
/// Same as `component_outer_type` but for core wasm types instead.
|
||||
pub fn core_outer_type(&self, count: u32, ty: TypeIndex) -> TypeDef {
|
||||
// Reverse the index and 0 means the "current scope"
|
||||
let idx = self.type_scopes.len() - (count as usize) - 1;
|
||||
self.type_scopes[idx].core[ty]
|
||||
}
|
||||
|
||||
/// Pops a scope pushed by `push_type_scope`.
|
||||
pub fn pop_type_scope(&mut self) {
|
||||
self.type_scopes.pop().unwrap();
|
||||
}
|
||||
|
||||
/// Translates a wasmparser `ComponentTypeDef` into a Wasmtime `TypeDef`,
|
||||
/// Translates a wasmparser `TypeComponent` into a Wasmtime `TypeDef`,
|
||||
/// interning types along the way.
|
||||
pub fn component_type_def(&mut self, ty: &wasmparser::ComponentTypeDef<'_>) -> Result<TypeDef> {
|
||||
pub fn intern_component_type(&mut self, ty: &wasmparser::ComponentType<'_>) -> Result<TypeDef> {
|
||||
Ok(match ty {
|
||||
wasmparser::ComponentTypeDef::Module(ty) => TypeDef::Module(self.module_type(ty)?),
|
||||
wasmparser::ComponentTypeDef::Component(ty) => {
|
||||
wasmparser::ComponentType::Defined(ty) => TypeDef::Interface(self.defined_type(ty)),
|
||||
wasmparser::ComponentType::Func(ty) => TypeDef::ComponentFunc(self.func_type(ty)),
|
||||
wasmparser::ComponentType::Component(ty) => {
|
||||
TypeDef::Component(self.component_type(ty)?)
|
||||
}
|
||||
wasmparser::ComponentTypeDef::Instance(ty) => {
|
||||
wasmparser::ComponentType::Instance(ty) => {
|
||||
TypeDef::ComponentInstance(self.component_instance_type(ty)?)
|
||||
}
|
||||
wasmparser::ComponentTypeDef::Function(ty) => TypeDef::Func(self.func_type(ty)),
|
||||
wasmparser::ComponentTypeDef::Value(_ty) => unimplemented!("value types"),
|
||||
wasmparser::ComponentTypeDef::Interface(ty) => {
|
||||
TypeDef::Interface(self.interface_type(ty))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn module_type(&mut self, ty: &[wasmparser::ModuleType<'_>]) -> Result<ModuleTypeIndex> {
|
||||
let mut result = ModuleType::default();
|
||||
/// Translates a wasmparser `CoreType` into a Wasmtime `TypeDef`,
|
||||
/// interning types along the way.
|
||||
pub fn intern_core_type(&mut self, ty: &wasmparser::CoreType<'_>) -> Result<TypeDef> {
|
||||
Ok(match ty {
|
||||
wasmparser::CoreType::Func(ty) => {
|
||||
TypeDef::CoreFunc(self.module_types.wasm_func_type(ty.clone().try_into()?))
|
||||
}
|
||||
wasmparser::CoreType::Module(ty) => TypeDef::Module(self.module_type(ty)?),
|
||||
})
|
||||
}
|
||||
|
||||
/// Translates a wasmparser `ComponentTypeRef` into a Wasmtime `TypeDef`.
|
||||
pub fn component_type_ref(&self, ty: &wasmparser::ComponentTypeRef) -> TypeDef {
|
||||
match ty {
|
||||
wasmparser::ComponentTypeRef::Module(ty) => {
|
||||
self.core_outer_type(0, TypeIndex::from_u32(*ty))
|
||||
}
|
||||
wasmparser::ComponentTypeRef::Func(ty)
|
||||
| wasmparser::ComponentTypeRef::Instance(ty)
|
||||
| wasmparser::ComponentTypeRef::Component(ty) => {
|
||||
self.component_outer_type(0, ComponentTypeIndex::from_u32(*ty))
|
||||
}
|
||||
wasmparser::ComponentTypeRef::Value(..) => {
|
||||
unimplemented!("references to value types");
|
||||
}
|
||||
wasmparser::ComponentTypeRef::Type(..) => {
|
||||
unimplemented!("references to types");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn module_type(
|
||||
&mut self,
|
||||
ty: &[wasmparser::ModuleTypeDeclaration<'_>],
|
||||
) -> Result<TypeModuleIndex> {
|
||||
let mut result = TypeModule::default();
|
||||
let mut functypes: PrimaryMap<TypeIndex, SignatureIndex> = PrimaryMap::default();
|
||||
|
||||
for item in ty {
|
||||
match item {
|
||||
wasmparser::ModuleType::Type(wasmparser::TypeDef::Func(f)) => {
|
||||
wasmparser::ModuleTypeDeclaration::Type(wasmparser::Type::Func(f)) => {
|
||||
functypes.push(self.module_types.wasm_func_type(f.clone().try_into()?));
|
||||
}
|
||||
wasmparser::ModuleType::Export { name, ty } => {
|
||||
wasmparser::ModuleTypeDeclaration::Export { name, ty } => {
|
||||
let prev = result
|
||||
.exports
|
||||
.insert(name.to_string(), type_ref(ty, &functypes)?);
|
||||
assert!(prev.is_none());
|
||||
}
|
||||
wasmparser::ModuleType::Import(import) => {
|
||||
wasmparser::ModuleTypeDeclaration::Import(import) => {
|
||||
let prev = result.imports.insert(
|
||||
(import.module.to_string(), import.name.to_string()),
|
||||
type_ref(&import.ty, &functypes)?,
|
||||
@@ -362,112 +433,135 @@ impl ComponentTypesBuilder {
|
||||
|
||||
fn component_type(
|
||||
&mut self,
|
||||
ty: &[wasmparser::ComponentType<'_>],
|
||||
) -> Result<ComponentTypeIndex> {
|
||||
let mut result = ComponentType::default();
|
||||
self.push_component_types_scope();
|
||||
ty: &[ComponentTypeDeclaration<'_>],
|
||||
) -> Result<TypeComponentIndex> {
|
||||
let mut result = TypeComponent::default();
|
||||
self.push_type_scope();
|
||||
|
||||
for item in ty {
|
||||
match item {
|
||||
wasmparser::ComponentType::Type(ty) => {
|
||||
let ty = self.component_type_def(ty)?;
|
||||
self.push_component_typedef(ty);
|
||||
ComponentTypeDeclaration::Type(ty) => self.type_declaration_type(ty)?,
|
||||
ComponentTypeDeclaration::CoreType(ty) => self.type_declaration_core_type(ty)?,
|
||||
ComponentTypeDeclaration::Alias(alias) => self.type_declaration_alias(alias)?,
|
||||
ComponentTypeDeclaration::Export { name, ty } => {
|
||||
let ty = self.component_type_ref(ty);
|
||||
result.exports.insert(name.to_string(), ty);
|
||||
}
|
||||
wasmparser::ComponentType::OuterType { count, index } => {
|
||||
let ty = self.component_outer_type(*count, TypeIndex::from_u32(*index));
|
||||
self.push_component_typedef(ty);
|
||||
}
|
||||
wasmparser::ComponentType::Export { name, ty } => {
|
||||
result.exports.insert(
|
||||
name.to_string(),
|
||||
self.component_outer_type(0, TypeIndex::from_u32(*ty)),
|
||||
);
|
||||
}
|
||||
wasmparser::ComponentType::Import(import) => {
|
||||
result.imports.insert(
|
||||
import.name.to_string(),
|
||||
self.component_outer_type(0, TypeIndex::from_u32(import.ty)),
|
||||
);
|
||||
ComponentTypeDeclaration::Import(import) => {
|
||||
let ty = self.component_type_ref(&import.ty);
|
||||
result.imports.insert(import.name.to_string(), ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.pop_component_types_scope();
|
||||
self.pop_type_scope();
|
||||
|
||||
Ok(self.component_types.components.push(result))
|
||||
}
|
||||
|
||||
fn component_instance_type(
|
||||
&mut self,
|
||||
ty: &[wasmparser::InstanceType<'_>],
|
||||
) -> Result<ComponentInstanceTypeIndex> {
|
||||
let mut result = ComponentInstanceType::default();
|
||||
self.push_component_types_scope();
|
||||
ty: &[InstanceTypeDeclaration<'_>],
|
||||
) -> Result<TypeComponentInstanceIndex> {
|
||||
let mut result = TypeComponentInstance::default();
|
||||
self.push_type_scope();
|
||||
|
||||
for item in ty {
|
||||
match item {
|
||||
wasmparser::InstanceType::Type(ty) => {
|
||||
let ty = self.component_type_def(ty)?;
|
||||
self.push_component_typedef(ty);
|
||||
}
|
||||
wasmparser::InstanceType::OuterType { count, index } => {
|
||||
let ty = self.component_outer_type(*count, TypeIndex::from_u32(*index));
|
||||
self.push_component_typedef(ty);
|
||||
}
|
||||
wasmparser::InstanceType::Export { name, ty } => {
|
||||
result.exports.insert(
|
||||
name.to_string(),
|
||||
self.component_outer_type(0, TypeIndex::from_u32(*ty)),
|
||||
);
|
||||
InstanceTypeDeclaration::Type(ty) => self.type_declaration_type(ty)?,
|
||||
InstanceTypeDeclaration::CoreType(ty) => self.type_declaration_core_type(ty)?,
|
||||
InstanceTypeDeclaration::Alias(alias) => self.type_declaration_alias(alias)?,
|
||||
InstanceTypeDeclaration::Export { name, ty } => {
|
||||
let ty = self.component_type_ref(ty);
|
||||
result.exports.insert(name.to_string(), ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.pop_component_types_scope();
|
||||
self.pop_type_scope();
|
||||
|
||||
Ok(self.component_types.component_instances.push(result))
|
||||
}
|
||||
|
||||
fn func_type(&mut self, ty: &wasmparser::ComponentFuncType<'_>) -> FuncTypeIndex {
|
||||
let ty = FuncType {
|
||||
fn type_declaration_type(&mut self, ty: &wasmparser::ComponentType<'_>) -> Result<()> {
|
||||
let ty = self.intern_component_type(ty)?;
|
||||
self.push_component_typedef(ty);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn type_declaration_core_type(&mut self, ty: &wasmparser::CoreType<'_>) -> Result<()> {
|
||||
let ty = self.intern_core_type(ty)?;
|
||||
self.push_core_typedef(ty);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn type_declaration_alias(&mut self, alias: &wasmparser::ComponentAlias<'_>) -> Result<()> {
|
||||
match alias {
|
||||
ComponentAlias::Outer {
|
||||
kind: ComponentOuterAliasKind::CoreType,
|
||||
count,
|
||||
index,
|
||||
} => {
|
||||
let ty = self.core_outer_type(*count, TypeIndex::from_u32(*index));
|
||||
self.push_core_typedef(ty);
|
||||
}
|
||||
ComponentAlias::Outer {
|
||||
kind: ComponentOuterAliasKind::Type,
|
||||
count,
|
||||
index,
|
||||
} => {
|
||||
let ty = self.component_outer_type(*count, ComponentTypeIndex::from_u32(*index));
|
||||
self.push_component_typedef(ty);
|
||||
}
|
||||
a => unreachable!("invalid alias {a:?}"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn func_type(&mut self, ty: &wasmparser::ComponentFuncType<'_>) -> TypeFuncIndex {
|
||||
let ty = TypeFunc {
|
||||
params: ty
|
||||
.params
|
||||
.iter()
|
||||
.map(|(name, ty)| (name.map(|s| s.to_string()), self.interface_type_ref(ty)))
|
||||
.map(|(name, ty)| (name.map(|s| s.to_string()), self.valtype(ty)))
|
||||
.collect(),
|
||||
result: self.interface_type_ref(&ty.result),
|
||||
result: self.valtype(&ty.result),
|
||||
};
|
||||
intern(&mut self.functions, &mut self.component_types.functions, ty)
|
||||
}
|
||||
|
||||
fn interface_type(&mut self, ty: &wasmparser::InterfaceType<'_>) -> InterfaceType {
|
||||
fn defined_type(&mut self, ty: &wasmparser::ComponentDefinedType<'_>) -> InterfaceType {
|
||||
match ty {
|
||||
wasmparser::InterfaceType::Primitive(ty) => ty.into(),
|
||||
wasmparser::InterfaceType::Record(e) => InterfaceType::Record(self.record_type(e)),
|
||||
wasmparser::InterfaceType::Variant(e) => InterfaceType::Variant(self.variant_type(e)),
|
||||
wasmparser::InterfaceType::List(e) => {
|
||||
let ty = self.interface_type_ref(e);
|
||||
wasmparser::ComponentDefinedType::Primitive(ty) => ty.into(),
|
||||
wasmparser::ComponentDefinedType::Record(e) => {
|
||||
InterfaceType::Record(self.record_type(e))
|
||||
}
|
||||
wasmparser::ComponentDefinedType::Variant(e) => {
|
||||
InterfaceType::Variant(self.variant_type(e))
|
||||
}
|
||||
wasmparser::ComponentDefinedType::List(e) => {
|
||||
let ty = self.valtype(e);
|
||||
InterfaceType::List(self.intern_interface_type(ty))
|
||||
}
|
||||
wasmparser::InterfaceType::Tuple(e) => InterfaceType::Tuple(self.tuple_type(e)),
|
||||
wasmparser::InterfaceType::Flags(e) => InterfaceType::Flags(self.flags_type(e)),
|
||||
wasmparser::InterfaceType::Enum(e) => InterfaceType::Enum(self.enum_type(e)),
|
||||
wasmparser::InterfaceType::Union(e) => InterfaceType::Union(self.union_type(e)),
|
||||
wasmparser::InterfaceType::Option(e) => {
|
||||
let ty = self.interface_type_ref(e);
|
||||
wasmparser::ComponentDefinedType::Tuple(e) => InterfaceType::Tuple(self.tuple_type(e)),
|
||||
wasmparser::ComponentDefinedType::Flags(e) => InterfaceType::Flags(self.flags_type(e)),
|
||||
wasmparser::ComponentDefinedType::Enum(e) => InterfaceType::Enum(self.enum_type(e)),
|
||||
wasmparser::ComponentDefinedType::Union(e) => InterfaceType::Union(self.union_type(e)),
|
||||
wasmparser::ComponentDefinedType::Option(e) => {
|
||||
let ty = self.valtype(e);
|
||||
InterfaceType::Option(self.intern_interface_type(ty))
|
||||
}
|
||||
wasmparser::InterfaceType::Expected { ok, error } => {
|
||||
wasmparser::ComponentDefinedType::Expected { ok, error } => {
|
||||
InterfaceType::Expected(self.expected_type(ok, error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn interface_type_ref(&mut self, ty: &wasmparser::InterfaceTypeRef) -> InterfaceType {
|
||||
fn valtype(&mut self, ty: &wasmparser::ComponentValType) -> InterfaceType {
|
||||
match ty {
|
||||
wasmparser::InterfaceTypeRef::Primitive(p) => p.into(),
|
||||
wasmparser::InterfaceTypeRef::Type(idx) => {
|
||||
let idx = TypeIndex::from_u32(*idx);
|
||||
wasmparser::ComponentValType::Primitive(p) => p.into(),
|
||||
wasmparser::ComponentValType::Type(idx) => {
|
||||
let idx = ComponentTypeIndex::from_u32(*idx);
|
||||
match self.component_outer_type(0, idx) {
|
||||
TypeDef::Interface(ty) => ty,
|
||||
// this should not be possible if the module validated
|
||||
@@ -477,7 +571,7 @@ impl ComponentTypesBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
fn intern_interface_type(&mut self, ty: InterfaceType) -> InterfaceTypeIndex {
|
||||
fn intern_interface_type(&mut self, ty: InterfaceType) -> TypeInterfaceIndex {
|
||||
intern(
|
||||
&mut self.interface_types,
|
||||
&mut self.component_types.interface_types,
|
||||
@@ -485,30 +579,30 @@ impl ComponentTypesBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
fn record_type(&mut self, record: &[(&str, wasmparser::InterfaceTypeRef)]) -> RecordTypeIndex {
|
||||
let record = RecordType {
|
||||
fn record_type(&mut self, record: &[(&str, wasmparser::ComponentValType)]) -> TypeRecordIndex {
|
||||
let record = TypeRecord {
|
||||
fields: record
|
||||
.iter()
|
||||
.map(|(name, ty)| RecordField {
|
||||
name: name.to_string(),
|
||||
ty: self.interface_type_ref(ty),
|
||||
ty: self.valtype(ty),
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
intern(&mut self.records, &mut self.component_types.records, record)
|
||||
}
|
||||
|
||||
fn variant_type(&mut self, cases: &[wasmparser::VariantCase<'_>]) -> VariantTypeIndex {
|
||||
let variant = VariantType {
|
||||
fn variant_type(&mut self, cases: &[wasmparser::VariantCase<'_>]) -> TypeVariantIndex {
|
||||
let variant = TypeVariant {
|
||||
cases: cases
|
||||
.iter()
|
||||
.map(|case| {
|
||||
// FIXME: need to implement `default_to`, not sure what that
|
||||
// FIXME: need to implement `refines`, not sure what that
|
||||
// is at this time.
|
||||
assert!(case.default_to.is_none());
|
||||
assert!(case.refines.is_none());
|
||||
VariantCase {
|
||||
name: case.name.to_string(),
|
||||
ty: self.interface_type_ref(&case.ty),
|
||||
ty: self.valtype(&case.ty),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
@@ -520,42 +614,42 @@ impl ComponentTypesBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
fn tuple_type(&mut self, types: &[wasmparser::InterfaceTypeRef]) -> TupleTypeIndex {
|
||||
let tuple = TupleType {
|
||||
types: types.iter().map(|ty| self.interface_type_ref(ty)).collect(),
|
||||
fn tuple_type(&mut self, types: &[wasmparser::ComponentValType]) -> TypeTupleIndex {
|
||||
let tuple = TypeTuple {
|
||||
types: types.iter().map(|ty| self.valtype(ty)).collect(),
|
||||
};
|
||||
intern(&mut self.tuples, &mut self.component_types.tuples, tuple)
|
||||
}
|
||||
|
||||
fn flags_type(&mut self, flags: &[&str]) -> FlagsTypeIndex {
|
||||
let flags = FlagsType {
|
||||
fn flags_type(&mut self, flags: &[&str]) -> TypeFlagsIndex {
|
||||
let flags = TypeFlags {
|
||||
names: flags.iter().map(|s| s.to_string()).collect(),
|
||||
};
|
||||
intern(&mut self.flags, &mut self.component_types.flags, flags)
|
||||
}
|
||||
|
||||
fn enum_type(&mut self, variants: &[&str]) -> EnumTypeIndex {
|
||||
let e = EnumType {
|
||||
fn enum_type(&mut self, variants: &[&str]) -> TypeEnumIndex {
|
||||
let e = TypeEnum {
|
||||
names: variants.iter().map(|s| s.to_string()).collect(),
|
||||
};
|
||||
intern(&mut self.enums, &mut self.component_types.enums, e)
|
||||
}
|
||||
|
||||
fn union_type(&mut self, types: &[wasmparser::InterfaceTypeRef]) -> UnionTypeIndex {
|
||||
let union = UnionType {
|
||||
types: types.iter().map(|ty| self.interface_type_ref(ty)).collect(),
|
||||
fn union_type(&mut self, types: &[wasmparser::ComponentValType]) -> TypeUnionIndex {
|
||||
let union = TypeUnion {
|
||||
types: types.iter().map(|ty| self.valtype(ty)).collect(),
|
||||
};
|
||||
intern(&mut self.unions, &mut self.component_types.unions, union)
|
||||
}
|
||||
|
||||
fn expected_type(
|
||||
&mut self,
|
||||
ok: &wasmparser::InterfaceTypeRef,
|
||||
err: &wasmparser::InterfaceTypeRef,
|
||||
) -> ExpectedTypeIndex {
|
||||
let expected = ExpectedType {
|
||||
ok: self.interface_type_ref(ok),
|
||||
err: self.interface_type_ref(err),
|
||||
ok: &wasmparser::ComponentValType,
|
||||
err: &wasmparser::ComponentValType,
|
||||
) -> TypeExpectedIndex {
|
||||
let expected = TypeExpected {
|
||||
ok: self.valtype(ok),
|
||||
err: self.valtype(err),
|
||||
};
|
||||
intern(
|
||||
&mut self.expecteds,
|
||||
@@ -597,16 +691,18 @@ where
|
||||
/// through a sibling `ComponentTypes` structure.
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum TypeDef {
|
||||
/// A core wasm module and its type.
|
||||
Module(ModuleTypeIndex),
|
||||
/// A component and its type.
|
||||
Component(ComponentTypeIndex),
|
||||
Component(TypeComponentIndex),
|
||||
/// An instance of a component.
|
||||
ComponentInstance(ComponentInstanceTypeIndex),
|
||||
ComponentInstance(TypeComponentInstanceIndex),
|
||||
/// A component function, not to be confused with a core wasm function.
|
||||
Func(FuncTypeIndex),
|
||||
ComponentFunc(TypeFuncIndex),
|
||||
/// An interface type.
|
||||
Interface(InterfaceType),
|
||||
/// A core wasm module and its type.
|
||||
Module(TypeModuleIndex),
|
||||
/// A core wasm function using only core wasm types.
|
||||
CoreFunc(SignatureIndex),
|
||||
}
|
||||
|
||||
// NB: Note that maps below are stored as an `IndexMap` now but the order
|
||||
@@ -616,10 +712,10 @@ pub enum TypeDef {
|
||||
|
||||
/// The type of a module in the component model.
|
||||
///
|
||||
/// Note that this is not to be confused with `ComponentType` below. This is
|
||||
/// Note that this is not to be confused with `TypeComponent` below. This is
|
||||
/// intended only for core wasm modules, not for components.
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
pub struct ModuleType {
|
||||
pub struct TypeModule {
|
||||
/// The values that this module imports.
|
||||
///
|
||||
/// Note that the value of this map is a core wasm `EntityType`, not a
|
||||
@@ -638,7 +734,7 @@ pub struct ModuleType {
|
||||
|
||||
/// The type of a component in the component model.
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
pub struct ComponentType {
|
||||
pub struct TypeComponent {
|
||||
/// The named values that this component imports.
|
||||
pub imports: IndexMap<String, TypeDef>,
|
||||
/// The named values that this component exports.
|
||||
@@ -650,14 +746,14 @@ pub struct ComponentType {
|
||||
///
|
||||
/// Component instances only have exports of types in the component model.
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
pub struct ComponentInstanceType {
|
||||
pub struct TypeComponentInstance {
|
||||
/// The list of exports that this component has along with their types.
|
||||
pub exports: IndexMap<String, TypeDef>,
|
||||
}
|
||||
|
||||
/// A component function type in the component model.
|
||||
#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub struct FuncType {
|
||||
pub struct TypeFunc {
|
||||
/// The list of optionally named parameters for this function, and their
|
||||
/// types.
|
||||
pub params: Box<[(Option<String>, InterfaceType)]>,
|
||||
@@ -688,34 +784,34 @@ pub enum InterfaceType {
|
||||
Float64,
|
||||
Char,
|
||||
String,
|
||||
Record(RecordTypeIndex),
|
||||
Variant(VariantTypeIndex),
|
||||
List(InterfaceTypeIndex),
|
||||
Tuple(TupleTypeIndex),
|
||||
Flags(FlagsTypeIndex),
|
||||
Enum(EnumTypeIndex),
|
||||
Union(UnionTypeIndex),
|
||||
Option(InterfaceTypeIndex),
|
||||
Expected(ExpectedTypeIndex),
|
||||
Record(TypeRecordIndex),
|
||||
Variant(TypeVariantIndex),
|
||||
List(TypeInterfaceIndex),
|
||||
Tuple(TypeTupleIndex),
|
||||
Flags(TypeFlagsIndex),
|
||||
Enum(TypeEnumIndex),
|
||||
Union(TypeUnionIndex),
|
||||
Option(TypeInterfaceIndex),
|
||||
Expected(TypeExpectedIndex),
|
||||
}
|
||||
|
||||
impl From<&wasmparser::PrimitiveInterfaceType> for InterfaceType {
|
||||
fn from(ty: &wasmparser::PrimitiveInterfaceType) -> InterfaceType {
|
||||
impl From<&wasmparser::PrimitiveValType> for InterfaceType {
|
||||
fn from(ty: &wasmparser::PrimitiveValType) -> InterfaceType {
|
||||
match ty {
|
||||
wasmparser::PrimitiveInterfaceType::Unit => InterfaceType::Unit,
|
||||
wasmparser::PrimitiveInterfaceType::Bool => InterfaceType::Bool,
|
||||
wasmparser::PrimitiveInterfaceType::S8 => InterfaceType::S8,
|
||||
wasmparser::PrimitiveInterfaceType::U8 => InterfaceType::U8,
|
||||
wasmparser::PrimitiveInterfaceType::S16 => InterfaceType::S16,
|
||||
wasmparser::PrimitiveInterfaceType::U16 => InterfaceType::U16,
|
||||
wasmparser::PrimitiveInterfaceType::S32 => InterfaceType::S32,
|
||||
wasmparser::PrimitiveInterfaceType::U32 => InterfaceType::U32,
|
||||
wasmparser::PrimitiveInterfaceType::S64 => InterfaceType::S64,
|
||||
wasmparser::PrimitiveInterfaceType::U64 => InterfaceType::U64,
|
||||
wasmparser::PrimitiveInterfaceType::Float32 => InterfaceType::Float32,
|
||||
wasmparser::PrimitiveInterfaceType::Float64 => InterfaceType::Float64,
|
||||
wasmparser::PrimitiveInterfaceType::Char => InterfaceType::Char,
|
||||
wasmparser::PrimitiveInterfaceType::String => InterfaceType::String,
|
||||
wasmparser::PrimitiveValType::Unit => InterfaceType::Unit,
|
||||
wasmparser::PrimitiveValType::Bool => InterfaceType::Bool,
|
||||
wasmparser::PrimitiveValType::S8 => InterfaceType::S8,
|
||||
wasmparser::PrimitiveValType::U8 => InterfaceType::U8,
|
||||
wasmparser::PrimitiveValType::S16 => InterfaceType::S16,
|
||||
wasmparser::PrimitiveValType::U16 => InterfaceType::U16,
|
||||
wasmparser::PrimitiveValType::S32 => InterfaceType::S32,
|
||||
wasmparser::PrimitiveValType::U32 => InterfaceType::U32,
|
||||
wasmparser::PrimitiveValType::S64 => InterfaceType::S64,
|
||||
wasmparser::PrimitiveValType::U64 => InterfaceType::U64,
|
||||
wasmparser::PrimitiveValType::Float32 => InterfaceType::Float32,
|
||||
wasmparser::PrimitiveValType::Float64 => InterfaceType::Float64,
|
||||
wasmparser::PrimitiveValType::Char => InterfaceType::Char,
|
||||
wasmparser::PrimitiveValType::String => InterfaceType::String,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -724,7 +820,7 @@ impl From<&wasmparser::PrimitiveInterfaceType> for InterfaceType {
|
||||
///
|
||||
/// This is equivalent to a `struct` in Rust.
|
||||
#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub struct RecordType {
|
||||
pub struct TypeRecord {
|
||||
/// The fields that are contained within this struct type.
|
||||
pub fields: Box<[RecordField]>,
|
||||
}
|
||||
@@ -744,7 +840,7 @@ pub struct RecordField {
|
||||
/// cases and each case has a unique name and an optional payload associated
|
||||
/// with it.
|
||||
#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub struct VariantType {
|
||||
pub struct TypeVariant {
|
||||
/// The list of cases that this variant can take.
|
||||
pub cases: Box<[VariantCase]>,
|
||||
}
|
||||
@@ -764,7 +860,7 @@ pub struct VariantCase {
|
||||
/// This is largely the same as a tuple in Rust, basically a record with
|
||||
/// unnamed fields.
|
||||
#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub struct TupleType {
|
||||
pub struct TypeTuple {
|
||||
/// The types that are contained within this tuple.
|
||||
pub types: Box<[InterfaceType]>,
|
||||
}
|
||||
@@ -774,7 +870,7 @@ pub struct TupleType {
|
||||
/// This can be thought of as a record-of-bools, although the representation is
|
||||
/// more efficient as bitflags.
|
||||
#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub struct FlagsType {
|
||||
pub struct TypeFlags {
|
||||
/// The names of all flags, all of which are unique.
|
||||
pub names: Box<[String]>,
|
||||
}
|
||||
@@ -785,7 +881,7 @@ pub struct FlagsType {
|
||||
/// In interface types enums are simply a bag of names, and can be seen as a
|
||||
/// variant where all payloads are `Unit`.
|
||||
#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub struct EnumType {
|
||||
pub struct TypeEnum {
|
||||
/// The names of this enum, all of which are unique.
|
||||
pub names: Box<[String]>,
|
||||
}
|
||||
@@ -796,14 +892,14 @@ pub struct EnumType {
|
||||
/// type where each type here has a name that's numbered. This is still a
|
||||
/// tagged union.
|
||||
#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub struct UnionType {
|
||||
pub struct TypeUnion {
|
||||
/// The list of types this is a union over.
|
||||
pub types: Box<[InterfaceType]>,
|
||||
}
|
||||
|
||||
/// Shape of an "expected" interface type.
|
||||
#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub struct ExpectedType {
|
||||
pub struct TypeExpected {
|
||||
/// The `T` in `Result<T, E>`
|
||||
pub ok: InterfaceType,
|
||||
/// The `E` in `Result<T, E>`
|
||||
|
||||
@@ -15,8 +15,8 @@ use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use wasmparser::{
|
||||
CustomSectionReader, DataKind, ElementItem, ElementKind, Encoding, ExternalKind, FuncValidator,
|
||||
FunctionBody, NameSectionReader, Naming, Operator, Parser, Payload, TypeDef, TypeRef,
|
||||
Validator, ValidatorResources,
|
||||
FunctionBody, NameSectionReader, Naming, Operator, Parser, Payload, Type, TypeRef, Validator,
|
||||
ValidatorResources,
|
||||
};
|
||||
|
||||
/// Object containing the standalone environment information.
|
||||
@@ -130,8 +130,8 @@ pub struct WasmFileInfo {
|
||||
#[derive(Debug)]
|
||||
#[allow(missing_docs)]
|
||||
pub struct FunctionMetadata {
|
||||
pub params: Box<[wasmparser::Type]>,
|
||||
pub locals: Box<[(u32, wasmparser::Type)]>,
|
||||
pub params: Box<[wasmparser::ValType]>,
|
||||
pub locals: Box<[(u32, wasmparser::ValType)]>,
|
||||
}
|
||||
|
||||
impl<'a, 'data> ModuleEnvironment<'a, 'data> {
|
||||
@@ -216,7 +216,7 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
|
||||
|
||||
for ty in types {
|
||||
match ty? {
|
||||
TypeDef::Func(wasm_func_ty) => {
|
||||
Type::Func(wasm_func_ty) => {
|
||||
self.declare_type_func(wasm_func_ty.try_into()?)?;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user