Instantiate nested modules for module linking (#2447)

This commit implements the interpretation necessary of the instance
section of the module linking proposal. Instantiating a module which
itself has nested instantiated instances will now instantiate the nested
instances properly. This isn't all that useful without the ability to
alias exports off the result, but we can at least observe the side
effects of instantiation through the `start` function.

cc #2094
This commit is contained in:
Alex Crichton
2020-12-01 14:01:31 -06:00
committed by GitHub
parent 40ad39fee9
commit 88a8a8993a
11 changed files with 433 additions and 105 deletions

View File

@@ -8,8 +8,8 @@
use crate::state::FuncTranslationState;
use crate::translation_utils::{
DataIndex, ElemIndex, EntityType, Event, EventIndex, FuncIndex, Global, GlobalIndex, Memory,
MemoryIndex, Table, TableIndex, TypeIndex,
DataIndex, ElemIndex, EntityIndex, EntityType, Event, EventIndex, FuncIndex, Global,
GlobalIndex, Memory, MemoryIndex, ModuleIndex, Table, TableIndex, TypeIndex,
};
use core::convert::From;
use core::convert::TryFrom;
@@ -22,6 +22,7 @@ use cranelift_frontend::FunctionBuilder;
use serde::{Deserialize, Serialize};
use std::boxed::Box;
use std::string::ToString;
use std::vec::Vec;
use thiserror::Error;
use wasmparser::ValidatorResources;
use wasmparser::{BinaryReaderError, FuncValidator, FunctionBody, Operator, WasmFeatures};
@@ -969,4 +970,16 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
fn module_end(&mut self, index: usize) {
drop(index);
}
/// 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<EntityIndex>) -> WasmResult<()> {
drop((module, args));
Err(WasmError::Unsupported("wasm instance".to_string()))
}
}

View File

@@ -3,8 +3,9 @@
use crate::environ::{ModuleEnvironment, WasmResult};
use crate::sections_translator::{
parse_data_section, parse_element_section, parse_event_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_type_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_type_section,
};
use crate::state::ModuleTranslationState;
use cranelift_codegen::timing;
@@ -116,7 +117,7 @@ pub fn translate_module<'data>(
}
Payload::InstanceSection(s) => {
validator.instance_section(&s)?;
unimplemented!("module linking not implemented yet")
parse_instance_section(s, environ)?;
}
Payload::AliasSection(s) => {
validator.alias_section(&s)?;

View File

@@ -10,9 +10,9 @@
use crate::environ::{ModuleEnvironment, WasmError, WasmResult};
use crate::state::ModuleTranslationState;
use crate::translation_utils::{
tabletype_to_type, type_to_type, DataIndex, ElemIndex, EntityType, Event, EventIndex,
FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, Table, TableElementType,
TableIndex, TypeIndex,
tabletype_to_type, type_to_type, DataIndex, ElemIndex, EntityIndex, EntityType, Event,
EventIndex, FuncIndex, Global, GlobalIndex, GlobalInit, InstanceIndex, Memory, MemoryIndex,
ModuleIndex, Table, TableElementType, TableIndex, TypeIndex,
};
use crate::wasm_unsupported;
use core::convert::TryFrom;
@@ -475,3 +475,37 @@ 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_types(section.get_count())?;
for instance in section {
let instance = instance?;
let module = ModuleIndex::from_u32(instance.module());
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)),
ExternalKind::Event => unimplemented!(),
// this won't pass validation
ExternalKind::Type => unreachable!(),
})
})
.collect::<WasmResult<Vec<_>>>()?;
environ.declare_instance(module, args)?;
}
Ok(())
}