Merge pull request #2585 from alexcrichton/module-linking-update

Update support for the module linking proposal
This commit is contained in:
Peter Huene
2021-01-14 15:48:14 -08:00
committed by GitHub
45 changed files with 1042 additions and 748 deletions

View File

@@ -30,7 +30,7 @@ peepmatic-traits = { path = "../peepmatic/crates/traits", optional = true, versi
peepmatic-runtime = { path = "../peepmatic/crates/runtime", optional = true, version = "0.69.0" }
regalloc = { version = "0.0.31" }
souper-ir = { version = "2.1.0", optional = true }
wast = { version = "29.0.0", optional = true }
wast = { version = "31.0.0", optional = true }
# It is a goal of the cranelift-codegen crate to have minimal external dependencies.
# Please don't add any unless they are essential to the task of creating binary
# machine code. Integration tests that need external dependencies can be

View File

@@ -15,7 +15,7 @@ peepmatic-macro = { version = "0.69.0", path = "crates/macro" }
peepmatic-runtime = { version = "0.69.0", path = "crates/runtime", features = ["construct"] }
peepmatic-traits = { version = "0.69.0", path = "crates/traits" }
serde = { version = "1.0.105", features = ["derive"] }
wast = "29.0.0"
wast = "31.0.0"
z3 = { version = "0.7.1", features = ["static-link-z3"] }
[dev-dependencies]

View File

@@ -21,4 +21,4 @@ peepmatic-test-operator = { path = "../test-operator" }
peepmatic-traits = { path = "../traits" }
rand = { version = "0.7.3", features = ["small_rng"] }
serde = "1.0.106"
wast = "29.0.0"
wast = "31.0.0"

View File

@@ -16,7 +16,7 @@ peepmatic-automata = { version = "0.69.0", path = "../automata", features = ["se
peepmatic-traits = { version = "0.69.0", path = "../traits" }
serde = { version = "1.0.105", features = ["derive"] }
thiserror = "1.0.15"
wast = { version = "29.0.0", optional = true }
wast = { version = "31.0.0", optional = true }
[dev-dependencies]
peepmatic-test-operator = { version = "0.69.0", path = "../test-operator" }

View File

@@ -16,4 +16,4 @@ log = "0.4.8"
[dev-dependencies]
peepmatic = { path = "../..", version = "0.69.0" }
peepmatic-test-operator = { version = "0.69.0", path = "../test-operator" }
wast = "29.0.0"
wast = "31.0.0"

View File

@@ -11,4 +11,4 @@ edition = "2018"
[dependencies]
peepmatic-traits = { version = "0.69.0", path = "../traits" }
serde = { version = "1.0.105", features = ["derive"] }
wast = "29.0.0"
wast = "31.0.0"

View File

@@ -12,7 +12,7 @@ keywords = ["webassembly", "wasm"]
edition = "2018"
[dependencies]
wasmparser = { version = "0.71", default-features = false }
wasmparser = { version = "0.72", default-features = false }
cranelift-codegen = { path = "../codegen", version = "0.69.0", default-features = false }
cranelift-entity = { path = "../entity", version = "0.69.0" }
cranelift-frontend = { path = "../frontend", version = "0.69.0", default-features = false }

View File

@@ -205,25 +205,34 @@ pub enum ReturnMode {
/// An entry in the alias section of a wasm module (from the module linking
/// proposal)
pub enum Alias {
/// A parent's module is being aliased into our own index space.
///
/// Note that the index here is in the parent's index space, not our own.
ParentModule(ModuleIndex),
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,
},
/// A parent's type is being aliased into our own index space
/// An outer module's type is being aliased into our own index space
///
/// Note that the index here is in the parent's index space, not our own.
ParentType(TypeIndex),
/// 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.
Child {
InstanceExport {
/// The index we're aliasing.
instance: InstanceIndex,
/// The nth export that we're inserting into our own index space
/// locally.
export: usize,
export: &'a str,
},
}
@@ -1014,30 +1023,15 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
drop(amount);
}
/// Declares that a module will come later with the type signature provided.
fn declare_module(&mut self, ty: TypeIndex) -> WasmResult<()> {
drop(ty);
Err(WasmError::Unsupported("module linking".to_string()))
}
/// Called at the beginning of translating a module.
///
/// The `index` argument is a monotonically increasing index which
/// corresponds to the nth module that's being translated. This is not the
/// 32-bit index in the current module's index space. For example the first
/// call to `module_start` will have index 0.
///
/// Note that for nested modules this may be called multiple times.
fn module_start(&mut self, index: usize) {
drop(index);
}
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, index: usize) {
drop(index);
}
fn module_end(&mut self) {}
/// Indicates that this module will have `amount` instances.
fn reserve_instances(&mut self, amount: u32) {
@@ -1046,7 +1040,11 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
/// Declares a new instance which this module will instantiate before it's
/// instantiated.
fn declare_instance(&mut self, module: ModuleIndex, args: Vec<EntityIndex>) -> WasmResult<()> {
fn declare_instance(
&mut self,
module: ModuleIndex,
args: Vec<(&'data str, EntityIndex)>,
) -> WasmResult<()> {
drop((module, args));
Err(WasmError::Unsupported("wasm instance".to_string()))
}
@@ -1056,7 +1054,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
/// 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) -> WasmResult<()> {
fn declare_alias(&mut self, alias: Alias<'data>) -> WasmResult<()> {
drop(alias);
Err(WasmError::Unsupported("wasm alias".to_string()))
}

View File

@@ -4,8 +4,8 @@ use crate::environ::{ModuleEnvironment, WasmResult};
use crate::sections_translator::{
parse_alias_section, parse_data_section, parse_element_section, parse_event_section,
parse_export_section, parse_function_section, parse_global_section, parse_import_section,
parse_instance_section, parse_memory_section, parse_module_section, parse_name_section,
parse_start_section, parse_table_section, parse_type_section,
parse_instance_section, parse_memory_section, parse_name_section, parse_start_section,
parse_table_section, parse_type_section,
};
use crate::state::ModuleTranslationState;
use cranelift_codegen::timing;
@@ -22,23 +22,16 @@ pub fn translate_module<'data>(
let mut module_translation_state = ModuleTranslationState::new();
let mut validator = Validator::new();
validator.wasm_features(environ.wasm_features());
let mut stack = Vec::new();
let mut modules = 1;
let mut cur_module = 0;
for payload in Parser::new(0).parse_all(data) {
match payload? {
Payload::Version { num, range } => {
validator.version(num, &range)?;
environ.module_start(cur_module);
environ.module_start();
}
Payload::End => {
validator.end()?;
environ.module_end(cur_module);
if let Some((other, other_index)) = stack.pop() {
validator = other;
cur_module = other_index;
}
environ.module_end();
}
Payload::TypeSection(types) => {
@@ -111,10 +104,6 @@ pub fn translate_module<'data>(
environ.reserve_passive_data(count)?;
}
Payload::ModuleSection(s) => {
validator.module_section(&s)?;
parse_module_section(s, environ)?;
}
Payload::InstanceSection(s) => {
validator.instance_section(&s)?;
parse_instance_section(s, environ)?;
@@ -123,20 +112,17 @@ pub fn translate_module<'data>(
validator.alias_section(&s)?;
parse_alias_section(s, environ)?;
}
Payload::ModuleCodeSectionStart {
Payload::ModuleSectionStart {
count,
range,
size: _,
} => {
validator.module_code_section_start(count, &range)?;
validator.module_section_start(count, &range)?;
environ.reserve_modules(count);
}
Payload::ModuleCodeSectionEntry { .. } => {
let subvalidator = validator.module_code_section_entry();
stack.push((validator, cur_module));
validator = subvalidator;
cur_module = modules;
modules += 1;
Payload::ModuleSectionEntry { .. } => {
validator.module_section_entry();
}
Payload::CustomSection {

View File

@@ -504,19 +504,6 @@ pub fn parse_name_section<'data>(
Ok(())
}
/// Parses the Module section of the wasm module.
pub fn parse_module_section<'data>(
section: wasmparser::ModuleSectionReader<'data>,
environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
environ.reserve_modules(section.get_count());
for module_ty in section {
environ.declare_module(TypeIndex::from_u32(module_ty?))?;
}
Ok(())
}
/// Parses the Instance section of the wasm module.
pub fn parse_instance_section<'data>(
section: wasmparser::InstanceSectionReader<'data>,
@@ -530,20 +517,23 @@ pub fn parse_instance_section<'data>(
let args = instance
.args()?
.into_iter()
.map(|result| {
let (kind, idx) = result?;
Ok(match kind {
ExternalKind::Function => EntityIndex::Function(FuncIndex::from_u32(idx)),
ExternalKind::Table => EntityIndex::Table(TableIndex::from_u32(idx)),
ExternalKind::Memory => EntityIndex::Memory(MemoryIndex::from_u32(idx)),
ExternalKind::Global => EntityIndex::Global(GlobalIndex::from_u32(idx)),
ExternalKind::Module => EntityIndex::Module(ModuleIndex::from_u32(idx)),
ExternalKind::Instance => EntityIndex::Instance(InstanceIndex::from_u32(idx)),
.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::Event => unimplemented!(),
// this won't pass validation
ExternalKind::Type => unreachable!(),
})
};
Ok((arg.name, index))
})
.collect::<WasmResult<Vec<_>>>()?;
environ.declare_instance(module, args)?;
@@ -557,19 +547,28 @@ pub fn parse_alias_section<'data>(
environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
for alias in section {
let alias = alias?;
let alias = match alias.instance {
wasmparser::AliasedInstance::Parent => {
match alias.kind {
ExternalKind::Module => Alias::ParentModule(ModuleIndex::from_u32(alias.index)),
ExternalKind::Type => Alias::ParentType(TypeIndex::from_u32(alias.index)),
// shouldn't get past validation
_ => unreachable!(),
}
}
wasmparser::AliasedInstance::Child(i) => Alias::Child {
instance: InstanceIndex::from_u32(i),
export: alias.index as usize,
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)?;