Remove the module linking implementation in Wasmtime (#3958)
* Remove the module linking implementation in Wasmtime This commit removes the experimental implementation of the module linking WebAssembly proposal from Wasmtime. The module linking is no longer intended for core WebAssembly but is instead incorporated into the component model now at this point. This means that very large parts of Wasmtime's implementation of module linking are no longer applicable and would change greatly with an implementation of the component model. The main purpose of this is to remove Wasmtime's reliance on the support for module-linking in `wasmparser` and tooling crates. With this reliance removed we can move over to the `component-model` branch of `wasmparser` and use the updated support for the component model. Additionally given the trajectory of the component model proposal the embedding API of Wasmtime will not look like what it looks like today for WebAssembly. For example the core wasm `Instance` will not change and instead a `Component` is likely to be added instead. Some more rationale for this is in #3941, but the basic idea is that I feel that it's not going to be viable to develop support for the component model on a non-`main` branch of Wasmtime. Additionaly I don't think it's viable, for the same reasons as `wasm-tools`, to support the old module linking proposal and the new component model at the same time. This commit takes a moment to not only delete the existing module linking implementation but some abstractions are also simplified. For example module serialization is a bit simpler that there's only one module. Additionally instantiation is much simpler since the only initializer we have to deal with are imports and nothing else. Closes #3941 * Fix doc link * Update comments
This commit is contained in:
@@ -6,5 +6,5 @@ mod spec;
|
||||
|
||||
pub use crate::environ::dummy::DummyEnvironment;
|
||||
pub use crate::environ::spec::{
|
||||
Alias, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment,
|
||||
FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment,
|
||||
};
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
use crate::state::FuncTranslationState;
|
||||
use crate::{
|
||||
DataIndex, ElemIndex, EntityIndex, EntityType, FuncIndex, Global, GlobalIndex, InstanceIndex,
|
||||
InstanceTypeIndex, Memory, MemoryIndex, ModuleIndex, ModuleTypeIndex, SignatureIndex, Table,
|
||||
TableIndex, Tag, TagIndex, TypeIndex, WasmError, WasmFuncType, WasmResult, WasmType,
|
||||
DataIndex, ElemIndex, EntityType, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex,
|
||||
SignatureIndex, Table, TableIndex, Tag, TagIndex, TypeIndex, WasmError, WasmFuncType,
|
||||
WasmResult, WasmType,
|
||||
};
|
||||
use core::convert::From;
|
||||
use cranelift_codegen::cursor::FuncCursor;
|
||||
@@ -20,7 +20,6 @@ use cranelift_codegen::isa::TargetFrontendConfig;
|
||||
use cranelift_frontend::FunctionBuilder;
|
||||
use std::boxed::Box;
|
||||
use std::string::ToString;
|
||||
use std::vec::Vec;
|
||||
use wasmparser::{FuncValidator, FunctionBody, Operator, ValidatorResources, WasmFeatures};
|
||||
|
||||
/// The value of a WebAssembly global variable.
|
||||
@@ -52,39 +51,6 @@ pub enum ReturnMode {
|
||||
FallthroughReturn,
|
||||
}
|
||||
|
||||
/// An entry in the alias section of a wasm module (from the module linking
|
||||
/// proposal)
|
||||
pub enum Alias<'a> {
|
||||
/// An outer module's module is being aliased into our own index space.
|
||||
OuterModule {
|
||||
/// The number of modules above us that we're referencing.
|
||||
relative_depth: u32,
|
||||
/// The module index in the outer module's index space we're referencing.
|
||||
index: ModuleIndex,
|
||||
},
|
||||
|
||||
/// An outer module's type is being aliased into our own index space
|
||||
///
|
||||
/// Note that the index here is in the outer module's index space, not our
|
||||
/// own.
|
||||
OuterType {
|
||||
/// The number of modules above us that we're referencing.
|
||||
relative_depth: u32,
|
||||
/// The type index in the outer module's index space we're referencing.
|
||||
index: TypeIndex,
|
||||
},
|
||||
|
||||
/// A previously created instance is having one of its exports aliased into
|
||||
/// our index space.
|
||||
InstanceExport {
|
||||
/// The index we're aliasing.
|
||||
instance: InstanceIndex,
|
||||
/// The nth export that we're inserting into our own index space
|
||||
/// locally.
|
||||
export: &'a str,
|
||||
},
|
||||
}
|
||||
|
||||
/// Environment affecting the translation of a WebAssembly.
|
||||
pub trait TargetEnvironment {
|
||||
/// Get the information needed to produce Cranelift IR for the given target.
|
||||
@@ -588,20 +554,6 @@ pub trait ModuleEnvironment<'data> {
|
||||
Err(WasmError::Unsupported("module linking".to_string()))
|
||||
}
|
||||
|
||||
/// Translates a type index to its module type index, only called for type
|
||||
/// indices which point to modules.
|
||||
fn type_to_module_type(&self, index: TypeIndex) -> WasmResult<ModuleTypeIndex> {
|
||||
drop(index);
|
||||
Err(WasmError::Unsupported("module linking".to_string()))
|
||||
}
|
||||
|
||||
/// Translates a type index to its instance type index, only called for type
|
||||
/// indices which point to instances.
|
||||
fn type_to_instance_type(&self, index: TypeIndex) -> WasmResult<InstanceTypeIndex> {
|
||||
drop(index);
|
||||
Err(WasmError::Unsupported("module linking".to_string()))
|
||||
}
|
||||
|
||||
/// Provides the number of imports up front. By default this does nothing, but
|
||||
/// implementations can use this to preallocate memory if desired.
|
||||
fn reserve_imports(&mut self, _num: u32) -> WasmResult<()> {
|
||||
@@ -662,17 +614,6 @@ pub trait ModuleEnvironment<'data> {
|
||||
Err(WasmError::Unsupported("module linking".to_string()))
|
||||
}
|
||||
|
||||
/// Declares an instance import to the environment.
|
||||
fn declare_instance_import(
|
||||
&mut self,
|
||||
ty_index: TypeIndex,
|
||||
module: &'data str,
|
||||
field: Option<&'data str>,
|
||||
) -> WasmResult<()> {
|
||||
drop((ty_index, module, field));
|
||||
Err(WasmError::Unsupported("module linking".to_string()))
|
||||
}
|
||||
|
||||
/// Notifies the implementation that all imports have been declared.
|
||||
fn finish_imports(&mut self) -> WasmResult<()> {
|
||||
Ok(())
|
||||
@@ -759,22 +700,6 @@ pub trait ModuleEnvironment<'data> {
|
||||
name: &'data str,
|
||||
) -> WasmResult<()>;
|
||||
|
||||
/// Declares an instance export to the environment.
|
||||
fn declare_instance_export(
|
||||
&mut self,
|
||||
index: InstanceIndex,
|
||||
name: &'data str,
|
||||
) -> WasmResult<()> {
|
||||
drop((index, name));
|
||||
Err(WasmError::Unsupported("module linking".to_string()))
|
||||
}
|
||||
|
||||
/// Declares an instance export to the environment.
|
||||
fn declare_module_export(&mut self, index: ModuleIndex, name: &'data str) -> WasmResult<()> {
|
||||
drop((index, name));
|
||||
Err(WasmError::Unsupported("module linking".to_string()))
|
||||
}
|
||||
|
||||
/// Notifies the implementation that all exports have been declared.
|
||||
fn finish_exports(&mut self) -> WasmResult<()> {
|
||||
Ok(())
|
||||
@@ -880,48 +805,4 @@ pub trait ModuleEnvironment<'data> {
|
||||
fn wasm_features(&self) -> WasmFeatures {
|
||||
WasmFeatures::default()
|
||||
}
|
||||
|
||||
/// Indicates that this module will have `amount` submodules.
|
||||
///
|
||||
/// Note that this is just child modules of this module, and each child
|
||||
/// module may have yet more submodules.
|
||||
fn reserve_modules(&mut self, amount: u32) {
|
||||
drop(amount);
|
||||
}
|
||||
|
||||
/// Called at the beginning of translating a module.
|
||||
///
|
||||
/// Note that for nested modules this may be called multiple times.
|
||||
fn module_start(&mut self) {}
|
||||
|
||||
/// Called at the end of translating a module.
|
||||
///
|
||||
/// Note that for nested modules this may be called multiple times.
|
||||
fn module_end(&mut self) {}
|
||||
|
||||
/// Indicates that this module will have `amount` instances.
|
||||
fn reserve_instances(&mut self, amount: u32) {
|
||||
drop(amount);
|
||||
}
|
||||
|
||||
/// Declares a new instance which this module will instantiate before it's
|
||||
/// instantiated.
|
||||
fn declare_instance(
|
||||
&mut self,
|
||||
module: ModuleIndex,
|
||||
args: Vec<(&'data str, EntityIndex)>,
|
||||
) -> WasmResult<()> {
|
||||
drop((module, args));
|
||||
Err(WasmError::Unsupported("wasm instance".to_string()))
|
||||
}
|
||||
|
||||
/// Declares a new alias being added to this module.
|
||||
///
|
||||
/// The alias comes from the `instance` specified (or the parent if `None`
|
||||
/// is supplied) and the index is either in the module's own index spaces
|
||||
/// for the parent or an index into the exports for nested instances.
|
||||
fn declare_alias(&mut self, alias: Alias<'data>) -> WasmResult<()> {
|
||||
drop(alias);
|
||||
Err(WasmError::Unsupported("wasm alias".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ mod state;
|
||||
mod translation_utils;
|
||||
|
||||
pub use crate::environ::{
|
||||
Alias, DummyEnvironment, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode,
|
||||
DummyEnvironment, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode,
|
||||
TargetEnvironment,
|
||||
};
|
||||
pub use crate::func_translator::FuncTranslator;
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
//! to deal with each part of it.
|
||||
use crate::environ::ModuleEnvironment;
|
||||
use crate::sections_translator::{
|
||||
parse_alias_section, parse_data_section, parse_element_section, parse_export_section,
|
||||
parse_function_section, parse_global_section, parse_import_section, parse_instance_section,
|
||||
parse_memory_section, parse_name_section, parse_start_section, parse_table_section,
|
||||
parse_tag_section, parse_type_section,
|
||||
parse_data_section, parse_element_section, parse_export_section, parse_function_section,
|
||||
parse_global_section, parse_import_section, parse_memory_section, parse_name_section,
|
||||
parse_start_section, parse_table_section, parse_tag_section, parse_type_section,
|
||||
};
|
||||
use crate::state::ModuleTranslationState;
|
||||
use crate::WasmResult;
|
||||
@@ -28,11 +27,9 @@ pub fn translate_module<'data>(
|
||||
match payload? {
|
||||
Payload::Version { num, range } => {
|
||||
validator.version(num, &range)?;
|
||||
environ.module_start();
|
||||
}
|
||||
Payload::End => {
|
||||
validator.end()?;
|
||||
environ.module_end();
|
||||
}
|
||||
|
||||
Payload::TypeSection(types) => {
|
||||
@@ -109,11 +106,11 @@ pub fn translate_module<'data>(
|
||||
|
||||
Payload::InstanceSection(s) => {
|
||||
validator.instance_section(&s)?;
|
||||
parse_instance_section(s, environ)?;
|
||||
unimplemented!();
|
||||
}
|
||||
Payload::AliasSection(s) => {
|
||||
validator.alias_section(&s)?;
|
||||
parse_alias_section(s, environ)?;
|
||||
unimplemented!();
|
||||
}
|
||||
Payload::ModuleSectionStart {
|
||||
count,
|
||||
@@ -121,11 +118,12 @@ pub fn translate_module<'data>(
|
||||
size: _,
|
||||
} => {
|
||||
validator.module_section_start(count, &range)?;
|
||||
environ.reserve_modules(count);
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
Payload::ModuleSectionEntry { .. } => {
|
||||
validator.module_section_entry();
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
Payload::CustomSection {
|
||||
|
||||
@@ -7,13 +7,12 @@
|
||||
//! The special case of the initialize expressions for table elements offsets or global variables
|
||||
//! is handled, according to the semantics of WebAssembly, to only specific expressions that are
|
||||
//! interpreted on the fly.
|
||||
use crate::environ::{Alias, ModuleEnvironment};
|
||||
use crate::environ::ModuleEnvironment;
|
||||
use crate::state::ModuleTranslationState;
|
||||
use crate::wasm_unsupported;
|
||||
use crate::{
|
||||
DataIndex, ElemIndex, EntityIndex, EntityType, FuncIndex, Global, GlobalIndex, GlobalInit,
|
||||
InstanceIndex, Memory, MemoryIndex, ModuleIndex, Table, TableIndex, Tag, TagIndex, TypeIndex,
|
||||
WasmError, WasmResult,
|
||||
DataIndex, ElemIndex, EntityType, FuncIndex, Global, GlobalIndex, GlobalInit, Memory,
|
||||
MemoryIndex, Table, TableIndex, Tag, TagIndex, TypeIndex, WasmError, WasmResult,
|
||||
};
|
||||
use core::convert::TryFrom;
|
||||
use core::convert::TryInto;
|
||||
@@ -37,16 +36,15 @@ fn entity_type(
|
||||
ImportSectionEntryType::Function(sig) => {
|
||||
EntityType::Function(environ.type_to_signature(TypeIndex::from_u32(sig))?)
|
||||
}
|
||||
ImportSectionEntryType::Module(sig) => {
|
||||
EntityType::Module(environ.type_to_module_type(TypeIndex::from_u32(sig))?)
|
||||
}
|
||||
ImportSectionEntryType::Instance(sig) => {
|
||||
EntityType::Instance(environ.type_to_instance_type(TypeIndex::from_u32(sig))?)
|
||||
}
|
||||
ImportSectionEntryType::Memory(ty) => EntityType::Memory(memory(ty)),
|
||||
ImportSectionEntryType::Tag(t) => EntityType::Tag(tag(t)),
|
||||
ImportSectionEntryType::Global(ty) => EntityType::Global(global(ty, GlobalInit::Import)?),
|
||||
ImportSectionEntryType::Table(ty) => EntityType::Table(table(ty)?),
|
||||
|
||||
// doesn't get past validation
|
||||
ImportSectionEntryType::Module(_) | ImportSectionEntryType::Instance(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -142,20 +140,6 @@ pub fn parse_import_section<'data>(
|
||||
import.field,
|
||||
)?;
|
||||
}
|
||||
ImportSectionEntryType::Module(sig) => {
|
||||
environ.declare_module_import(
|
||||
TypeIndex::from_u32(sig),
|
||||
import.module,
|
||||
import.field,
|
||||
)?;
|
||||
}
|
||||
ImportSectionEntryType::Instance(sig) => {
|
||||
environ.declare_instance_import(
|
||||
TypeIndex::from_u32(sig),
|
||||
import.module,
|
||||
import.field,
|
||||
)?;
|
||||
}
|
||||
ImportSectionEntryType::Memory(ty) => {
|
||||
environ.declare_memory_import(memory(ty), import.module, import.field)?;
|
||||
}
|
||||
@@ -170,6 +154,10 @@ pub fn parse_import_section<'data>(
|
||||
let ty = table(ty)?;
|
||||
environ.declare_table_import(ty, import.module, import.field)?;
|
||||
}
|
||||
|
||||
ImportSectionEntryType::Module(_) | ImportSectionEntryType::Instance(_) => {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,15 +298,9 @@ pub fn parse_export_section<'data>(
|
||||
ExternalKind::Global => {
|
||||
environ.declare_global_export(GlobalIndex::new(index), field)?
|
||||
}
|
||||
ExternalKind::Module => {
|
||||
environ.declare_module_export(ModuleIndex::new(index), field)?
|
||||
}
|
||||
ExternalKind::Instance => {
|
||||
environ.declare_instance_export(InstanceIndex::new(index), field)?
|
||||
}
|
||||
|
||||
// this never gets past validation
|
||||
ExternalKind::Type => unreachable!(),
|
||||
ExternalKind::Module | ExternalKind::Instance | ExternalKind::Type => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,75 +488,3 @@ pub fn parse_name_section<'data>(
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Parses the Instance section of the wasm module.
|
||||
pub fn parse_instance_section<'data>(
|
||||
section: wasmparser::InstanceSectionReader<'data>,
|
||||
environ: &mut dyn ModuleEnvironment<'data>,
|
||||
) -> WasmResult<()> {
|
||||
environ.reserve_instances(section.get_count());
|
||||
|
||||
for instance in section {
|
||||
let instance = instance?;
|
||||
let module = ModuleIndex::from_u32(instance.module());
|
||||
let args = instance
|
||||
.args()?
|
||||
.into_iter()
|
||||
.map(|arg| {
|
||||
let arg = arg?;
|
||||
let index = match arg.kind {
|
||||
ExternalKind::Function => EntityIndex::Function(FuncIndex::from_u32(arg.index)),
|
||||
ExternalKind::Table => EntityIndex::Table(TableIndex::from_u32(arg.index)),
|
||||
ExternalKind::Memory => EntityIndex::Memory(MemoryIndex::from_u32(arg.index)),
|
||||
ExternalKind::Global => EntityIndex::Global(GlobalIndex::from_u32(arg.index)),
|
||||
ExternalKind::Module => EntityIndex::Module(ModuleIndex::from_u32(arg.index)),
|
||||
ExternalKind::Instance => {
|
||||
EntityIndex::Instance(InstanceIndex::from_u32(arg.index))
|
||||
}
|
||||
ExternalKind::Tag => unimplemented!(),
|
||||
|
||||
// this won't pass validation
|
||||
ExternalKind::Type => unreachable!(),
|
||||
};
|
||||
Ok((arg.name, index))
|
||||
})
|
||||
.collect::<WasmResult<Vec<_>>>()?;
|
||||
environ.declare_instance(module, args)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Parses the Alias section of the wasm module.
|
||||
pub fn parse_alias_section<'data>(
|
||||
section: wasmparser::AliasSectionReader<'data>,
|
||||
environ: &mut dyn ModuleEnvironment<'data>,
|
||||
) -> WasmResult<()> {
|
||||
for alias in section {
|
||||
let alias = match alias? {
|
||||
wasmparser::Alias::OuterType {
|
||||
relative_depth,
|
||||
index,
|
||||
} => Alias::OuterType {
|
||||
relative_depth,
|
||||
index: TypeIndex::from_u32(index),
|
||||
},
|
||||
wasmparser::Alias::OuterModule {
|
||||
relative_depth,
|
||||
index,
|
||||
} => Alias::OuterModule {
|
||||
relative_depth,
|
||||
index: ModuleIndex::from_u32(index),
|
||||
},
|
||||
wasmparser::Alias::InstanceExport {
|
||||
instance,
|
||||
export,
|
||||
kind: _,
|
||||
} => Alias::InstanceExport {
|
||||
instance: InstanceIndex::from_u32(instance),
|
||||
export,
|
||||
},
|
||||
};
|
||||
environ.declare_alias(alias)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user