Skip to content

Commit 2502e1a

Browse files
committed
Implement imported/exported modules/instances
This commit implements the final piece of the module linking proposal which is to flesh out the support for importing/exporting instances and modules. This ended up having a few changes: * Two more `PrimaryMap` instances are now stored in an `Instance`. The value for instances is `InstanceHandle` (pretty easy) and for modules it's `Box<dyn Any>` (less easy). * The custom host state for `InstanceHandle` for `wasmtime` is now `Arc<TypeTables` to be able to fully reconstruct an instance's types just from its instance. * Type matching for imports now has been updated to take instances/modules into account. One of the main downsides of this implementation is that type matching of imports is duplicated between wasmparser and wasmtime, leading to posssible bugs especially in the subtelties of module linking. I'm not sure how best to unify these two pieces of validation, however, and it may be more trouble than it's worth. cc bytecodealliance#2094
1 parent b93381e commit 2502e1a

File tree

21 files changed

+968
-299
lines changed

21 files changed

+968
-299
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,6 @@ harness = false
9696

9797
[profile.dev.package.backtrace]
9898
debug = false # FIXME(#1813)
99+
100+
[patch.crates-io]
101+
wasmparser = { git = 'https://github.com/alexcrichton/wasm-tools', branch = 'fix-validate-submodule' }

cranelift/wasm/src/translation_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ pub struct InstanceTypeIndex(u32);
110110
entity_impl!(InstanceTypeIndex);
111111

112112
/// An index of an entity.
113-
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
113+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
114114
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
115115
pub enum EntityIndex {
116116
/// Function index.

crates/c-api/src/extern.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ pub extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t {
1616
Extern::Global(_) => crate::WASM_EXTERN_GLOBAL,
1717
Extern::Table(_) => crate::WASM_EXTERN_TABLE,
1818
Extern::Memory(_) => crate::WASM_EXTERN_MEMORY,
19+
20+
// FIXME(#2094)
21+
Extern::Instance(_) => unimplemented!(),
22+
Extern::Module(_) => unimplemented!(),
1923
}
2024
}
2125

crates/environ/src/module.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,30 @@ impl Module {
346346
pub fn is_imported_global(&self, index: GlobalIndex) -> bool {
347347
index.index() < self.num_imported_globals
348348
}
349+
350+
/// Test whether the given global index is for an imported global.
351+
pub fn imports(&self) -> impl Iterator<Item = (&str, Option<&str>, EntityType)> {
352+
self.initializers.iter().filter_map(move |i| match i {
353+
Initializer::Import {
354+
module,
355+
field,
356+
index,
357+
} => Some((module.as_str(), field.as_deref(), self.type_of(*index))),
358+
_ => None,
359+
})
360+
}
361+
362+
/// Returns the type of an item based on its index
363+
pub fn type_of(&self, index: EntityIndex) -> EntityType {
364+
match index {
365+
EntityIndex::Global(i) => EntityType::Global(self.globals[i]),
366+
EntityIndex::Table(i) => EntityType::Table(self.table_plans[i].table),
367+
EntityIndex::Memory(i) => EntityType::Memory(self.memory_plans[i].memory),
368+
EntityIndex::Function(i) => EntityType::Function(self.functions[i]),
369+
EntityIndex::Instance(i) => EntityType::Instance(self.instances[i]),
370+
EntityIndex::Module(i) => EntityType::Module(self.modules[i]),
371+
}
372+
}
349373
}
350374

351375
/// All types which are recorded for the entirety of a translation.
@@ -376,7 +400,7 @@ pub struct ModuleSignature {
376400
#[derive(Debug, Clone, Serialize, Deserialize)]
377401
pub struct InstanceSignature {
378402
/// The name of what's being exported as well as its type signature.
379-
pub exports: Vec<(String, EntityType)>,
403+
pub exports: IndexMap<String, EntityType>,
380404
}
381405

382406
mod passive_data_serde {

crates/environ/src/module_environ.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,7 @@ and for re-adding support for interface types you can see this issue:
857857
// instance.
858858
Alias::Child { instance, export } => {
859859
let ty = self.result.module.instances[instance];
860-
match &self.types.instance_signatures[ty].exports[export].1 {
860+
match &self.types.instance_signatures[ty].exports[export] {
861861
EntityType::Global(g) => {
862862
self.result.module.globals.push(g.clone());
863863
self.result.module.num_imported_globals += 1;

crates/runtime/src/export.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use crate::vmcontext::{
22
VMCallerCheckedAnyfunc, VMContext, VMGlobalDefinition, VMMemoryDefinition, VMTableDefinition,
33
};
4+
use crate::InstanceHandle;
5+
use std::any::Any;
46
use std::ptr::NonNull;
57
use wasmtime_environ::wasm::Global;
68
use wasmtime_environ::{MemoryPlan, TablePlan};
79

810
/// The value of an export passed from one instance to another.
9-
#[derive(Debug, Clone)]
10-
pub enum Export {
11+
pub enum Export<'a> {
1112
/// A function export value.
1213
Function(ExportFunction),
1314

@@ -19,6 +20,12 @@ pub enum Export {
1920

2021
/// A global export value.
2122
Global(ExportGlobal),
23+
24+
/// An instance
25+
Instance(&'a InstanceHandle),
26+
27+
/// A module
28+
Module(&'a dyn Any),
2229
}
2330

2431
/// A function export value.
@@ -31,8 +38,8 @@ pub struct ExportFunction {
3138
pub anyfunc: NonNull<VMCallerCheckedAnyfunc>,
3239
}
3340

34-
impl From<ExportFunction> for Export {
35-
fn from(func: ExportFunction) -> Export {
41+
impl<'a> From<ExportFunction> for Export<'a> {
42+
fn from(func: ExportFunction) -> Export<'a> {
3643
Export::Function(func)
3744
}
3845
}
@@ -48,8 +55,8 @@ pub struct ExportTable {
4855
pub table: TablePlan,
4956
}
5057

51-
impl From<ExportTable> for Export {
52-
fn from(func: ExportTable) -> Export {
58+
impl<'a> From<ExportTable> for Export<'a> {
59+
fn from(func: ExportTable) -> Export<'a> {
5360
Export::Table(func)
5461
}
5562
}
@@ -65,8 +72,8 @@ pub struct ExportMemory {
6572
pub memory: MemoryPlan,
6673
}
6774

68-
impl From<ExportMemory> for Export {
69-
fn from(func: ExportMemory) -> Export {
75+
impl<'a> From<ExportMemory> for Export<'a> {
76+
fn from(func: ExportMemory) -> Export<'a> {
7077
Export::Memory(func)
7178
}
7279
}
@@ -82,8 +89,8 @@ pub struct ExportGlobal {
8289
pub global: Global,
8390
}
8491

85-
impl From<ExportGlobal> for Export {
86-
fn from(func: ExportGlobal) -> Export {
92+
impl<'a> From<ExportGlobal> for Export<'a> {
93+
fn from(func: ExportGlobal) -> Export<'a> {
8794
Export::Global(func)
8895
}
8996
}

crates/runtime/src/imports.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
use crate::vmcontext::{VMFunctionImport, VMGlobalImport, VMMemoryImport, VMTableImport};
2+
use crate::InstanceHandle;
3+
use std::any::Any;
4+
use wasmtime_environ::entity::PrimaryMap;
5+
use wasmtime_environ::wasm::{InstanceIndex, ModuleIndex};
26

37
/// Resolved import pointers.
48
///
5-
/// Note that each of these fields are slices, not `PrimaryMap`. They should be
9+
/// Note that some of these fields are slices, not `PrimaryMap`. They should be
610
/// stored in index-order as with the module that we're providing the imports
711
/// for, and indexing is all done the same way as the main module's index
812
/// spaces.
9-
#[derive(Clone, Default)]
13+
///
14+
/// Also note that the way we compile modules means that for the module linking
15+
/// proposal all `alias` directives should map to imported items. This means
16+
/// that each of these items aren't necessarily directly imported, but may be
17+
/// aliased.
18+
#[derive(Default)]
1019
pub struct Imports<'a> {
1120
/// Resolved addresses for imported functions.
1221
pub functions: &'a [VMFunctionImport],
@@ -19,4 +28,15 @@ pub struct Imports<'a> {
1928

2029
/// Resolved addresses for imported globals.
2130
pub globals: &'a [VMGlobalImport],
31+
32+
/// Resolved imported instances.
33+
pub instances: PrimaryMap<InstanceIndex, InstanceHandle>,
34+
35+
/// Resolved imported modules.
36+
///
37+
/// Note that `Box<Any>` here is chosen to allow the embedder of this crate
38+
/// to pick an appropriate representation of what module type should be. For
39+
/// example for the `wasmtime` crate it's `wasmtime::Module` but that's not
40+
/// defined way down here in this low crate.
41+
pub modules: PrimaryMap<ModuleIndex, Box<dyn Any>>,
2242
}

crates/runtime/src/instance.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ use thiserror::Error;
2828
use wasmtime_environ::entity::{packed_option::ReservedValue, BoxedSlice, EntityRef, PrimaryMap};
2929
use wasmtime_environ::wasm::{
3030
DataIndex, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex,
31-
ElemIndex, EntityIndex, FuncIndex, GlobalIndex, GlobalInit, MemoryIndex, SignatureIndex,
32-
TableElementType, TableIndex, WasmType,
31+
ElemIndex, EntityIndex, FuncIndex, GlobalIndex, GlobalInit, InstanceIndex, MemoryIndex,
32+
ModuleIndex, SignatureIndex, TableElementType, TableIndex, WasmType,
3333
};
3434
use wasmtime_environ::{ir, DataInitializer, Module, ModuleType, TableElements, VMOffsets};
3535

@@ -50,6 +50,15 @@ pub(crate) struct Instance {
5050
/// WebAssembly table data.
5151
tables: BoxedSlice<DefinedTableIndex, Table>,
5252

53+
/// Instances our module defined and their handles.
54+
instances: PrimaryMap<InstanceIndex, InstanceHandle>,
55+
56+
/// Modules that are located in our index space.
57+
///
58+
/// For now these are `Box<Any>` so the caller can define the type of what a
59+
/// module looks like.
60+
modules: PrimaryMap<ModuleIndex, Box<dyn Any>>,
61+
5362
/// Passive elements in this instantiation. As `elem.drop`s happen, these
5463
/// entries get removed. A missing entry is considered equivalent to an
5564
/// empty slice.
@@ -268,7 +277,7 @@ impl Instance {
268277
}
269278

270279
/// Lookup an export with the given export declaration.
271-
pub fn lookup_by_declaration(&self, export: &EntityIndex) -> Export {
280+
pub fn lookup_by_declaration(&self, export: &EntityIndex) -> Export<'_> {
272281
match export {
273282
EntityIndex::Function(index) => {
274283
let anyfunc = self.get_caller_checked_anyfunc(*index).unwrap();
@@ -317,9 +326,8 @@ impl Instance {
317326
}
318327
.into(),
319328

320-
// FIXME(#2094)
321-
EntityIndex::Instance(_index) => unimplemented!(),
322-
EntityIndex::Module(_index) => unimplemented!(),
329+
EntityIndex::Instance(index) => Export::Instance(&self.instances[*index]),
330+
EntityIndex::Module(index) => Export::Module(&*self.modules[*index]),
323331
}
324332
}
325333

@@ -847,6 +855,8 @@ impl InstanceHandle {
847855
passive_elements: Default::default(),
848856
passive_data,
849857
host_state,
858+
instances: imports.instances,
859+
modules: imports.modules,
850860
vmctx: VMContext {},
851861
};
852862
let layout = instance.alloc_layout();

crates/wasmtime/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ wat = { version = "1.0.18", optional = true }
2929
smallvec = "1.4.0"
3030
serde = { version = "1.0.94", features = ["derive"] }
3131
bincode = "1.2.1"
32+
indexmap = "1.6"
3233

3334
[target.'cfg(target_os = "windows")'.dependencies]
3435
winapi = "0.3.7"

0 commit comments

Comments
 (0)