Propagate module-linking types to wasmtime (#2115)
This commit adds lots of plumbing to get the type section from the module linking proposal plumbed all the way through to the `wasmtime` crate and the `wasmtime-c-api` crate. This isn't all that useful right now because Wasmtime doesn't support imported/exported modules/instances, but this is all necessary groundwork to getting that exported at some point. I've added some light tests but I suspect the bulk of the testing will come in a future commit. One major change in this commit is that `SignatureIndex` no longer follows type type index space in a wasm module. Instead a new `TypeIndex` type is used to track that. Function signatures, still indexed by `SignatureIndex`, are then packed together tightly.
This commit is contained in:
@@ -24,9 +24,5 @@ pub mod entity {
|
||||
}
|
||||
|
||||
pub mod wasm {
|
||||
pub use cranelift_wasm::{
|
||||
get_vmctx_value_label, DataIndex, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex,
|
||||
DefinedTableIndex, ElemIndex, FuncIndex, Global, GlobalIndex, GlobalInit, Memory,
|
||||
MemoryIndex, SignatureIndex, Table, TableElementType, TableIndex, WasmFuncType, WasmType,
|
||||
};
|
||||
pub use cranelift_wasm::*;
|
||||
}
|
||||
|
||||
@@ -37,10 +37,7 @@ pub use crate::address_map::*;
|
||||
pub use crate::builtin::*;
|
||||
pub use crate::compilation::*;
|
||||
pub use crate::data_structures::*;
|
||||
// pub use crate::func_environ::BuiltinFunctionIndex;
|
||||
pub use crate::module::{
|
||||
EntityIndex, MemoryPlan, MemoryStyle, Module, TableElements, TablePlan, TableStyle,
|
||||
};
|
||||
pub use crate::module::*;
|
||||
pub use crate::module_environ::*;
|
||||
pub use crate::tunables::Tunables;
|
||||
pub use crate::vmoffsets::{TargetSharedSignatureIndex, VMOffsets, INTERRUPTED};
|
||||
|
||||
@@ -5,8 +5,8 @@ use crate::WASM_MAX_PAGES;
|
||||
use cranelift_entity::{EntityRef, PrimaryMap};
|
||||
use cranelift_wasm::{
|
||||
DataIndex, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex,
|
||||
ElemIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table,
|
||||
TableIndex, WasmFuncType,
|
||||
ElemIndex, EntityIndex, EntityType, FuncIndex, Global, GlobalIndex, InstanceIndex, Memory,
|
||||
MemoryIndex, ModuleIndex, SignatureIndex, Table, TableIndex, TypeIndex, WasmFuncType,
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
use more_asserts::assert_ge;
|
||||
@@ -30,19 +30,6 @@ pub struct TableElements {
|
||||
pub elements: Box<[FuncIndex]>,
|
||||
}
|
||||
|
||||
/// An index of an entity.
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub enum EntityIndex {
|
||||
/// Function index.
|
||||
Function(FuncIndex),
|
||||
/// Table index.
|
||||
Table(TableIndex),
|
||||
/// Memory index.
|
||||
Memory(MemoryIndex),
|
||||
/// Global index.
|
||||
Global(GlobalIndex),
|
||||
}
|
||||
|
||||
/// Implemenation styles for WebAssembly linear memory.
|
||||
#[derive(Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub enum MemoryStyle {
|
||||
@@ -134,6 +121,36 @@ impl TablePlan {
|
||||
}
|
||||
}
|
||||
|
||||
/// Different types that can appear in a module
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ModuleType {
|
||||
/// A function type, indexed further into the `signatures` table.
|
||||
Function(SignatureIndex),
|
||||
/// A module type
|
||||
Module {
|
||||
/// The module's imports
|
||||
imports: Vec<(String, Option<String>, EntityType)>,
|
||||
/// The module's exports
|
||||
exports: Vec<(String, EntityType)>,
|
||||
},
|
||||
/// An instance type
|
||||
Instance {
|
||||
/// the instance's exports
|
||||
exports: Vec<(String, EntityType)>,
|
||||
},
|
||||
}
|
||||
|
||||
impl ModuleType {
|
||||
/// Asserts this is a `ModuleType::Function`, returning the underlying
|
||||
/// `SignatureIndex`.
|
||||
pub fn unwrap_function(&self) -> SignatureIndex {
|
||||
match self {
|
||||
ModuleType::Function(f) => *f,
|
||||
_ => panic!("not a function type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A translated WebAssembly module, excluding the function bodies and
|
||||
/// memory initializers.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -170,6 +187,9 @@ pub struct Module {
|
||||
/// Unprocessed signatures exactly as provided by `declare_signature()`.
|
||||
pub signatures: PrimaryMap<SignatureIndex, WasmFuncType>,
|
||||
|
||||
/// Types declared in the wasm module.
|
||||
pub types: PrimaryMap<TypeIndex, ModuleType>,
|
||||
|
||||
/// Number of imported functions in the module.
|
||||
pub num_imported_funcs: usize,
|
||||
|
||||
@@ -193,6 +213,27 @@ pub struct Module {
|
||||
|
||||
/// WebAssembly global variables.
|
||||
pub globals: PrimaryMap<GlobalIndex, Global>,
|
||||
|
||||
/// WebAssembly instances.
|
||||
pub instances: PrimaryMap<InstanceIndex, Instance>,
|
||||
|
||||
/// WebAssembly modules.
|
||||
pub modules: PrimaryMap<ModuleIndex, TypeIndex>,
|
||||
}
|
||||
|
||||
/// Different forms an instance can take in a wasm module
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum Instance {
|
||||
/// This is an imported instance with the specified type
|
||||
Import(TypeIndex),
|
||||
/// This is a locally created instance which instantiates the specified
|
||||
/// module with the given list of entities.
|
||||
Instantiate {
|
||||
/// The module that this instance is instantiating.
|
||||
module: ModuleIndex,
|
||||
/// The arguments provided to instantiation.
|
||||
args: Vec<EntityIndex>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Module {
|
||||
@@ -217,6 +258,9 @@ impl Module {
|
||||
table_plans: PrimaryMap::new(),
|
||||
memory_plans: PrimaryMap::new(),
|
||||
globals: PrimaryMap::new(),
|
||||
instances: PrimaryMap::new(),
|
||||
modules: PrimaryMap::new(),
|
||||
types: PrimaryMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crate::module::{EntityIndex, MemoryPlan, Module, TableElements, TablePlan};
|
||||
use crate::module::{MemoryPlan, Module, ModuleType, TableElements, TablePlan};
|
||||
use crate::tunables::Tunables;
|
||||
use cranelift_codegen::ir;
|
||||
use cranelift_codegen::ir::{AbiParam, ArgumentPurpose};
|
||||
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||
use cranelift_entity::PrimaryMap;
|
||||
use cranelift_wasm::{
|
||||
self, translate_module, DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex,
|
||||
Memory, MemoryIndex, SignatureIndex, Table, TableIndex, TargetEnvironment, WasmError,
|
||||
WasmFuncType, WasmResult,
|
||||
self, translate_module, DataIndex, DefinedFuncIndex, ElemIndex, EntityIndex, EntityType,
|
||||
FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex,
|
||||
TargetEnvironment, TypeIndex, WasmError, WasmFuncType, WasmResult,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
@@ -201,18 +201,54 @@ impl<'data> TargetEnvironment for ModuleEnvironment<'data> {
|
||||
/// This trait is useful for `translate_module` because it tells how to translate
|
||||
/// environment-dependent wasm instructions. These functions should not be called by the user.
|
||||
impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data> {
|
||||
fn reserve_signatures(&mut self, num: u32) -> WasmResult<()> {
|
||||
fn reserve_types(&mut self, num: u32) -> WasmResult<()> {
|
||||
let num = usize::try_from(num).unwrap();
|
||||
self.result.module.signatures.reserve_exact(num);
|
||||
self.result.module.types.reserve_exact(num);
|
||||
self.result.native_signatures.reserve_exact(num);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn declare_signature(&mut self, wasm: WasmFuncType, sig: ir::Signature) -> WasmResult<()> {
|
||||
fn declare_type_func(&mut self, wasm: WasmFuncType, sig: ir::Signature) -> WasmResult<()> {
|
||||
let sig = translate_signature(sig, self.pointer_type());
|
||||
// TODO: Deduplicate signatures.
|
||||
self.result.module.signatures.push(wasm);
|
||||
self.result.native_signatures.push(sig);
|
||||
let sig_index = self.result.module.signatures.push(wasm);
|
||||
self.result
|
||||
.module
|
||||
.types
|
||||
.push(ModuleType::Function(sig_index));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn declare_type_module(
|
||||
&mut self,
|
||||
imports: &[(&'data str, Option<&'data str>, EntityType)],
|
||||
exports: &[(&'data str, EntityType)],
|
||||
) -> WasmResult<()> {
|
||||
let imports = imports
|
||||
.iter()
|
||||
.map(|i| (i.0.to_string(), i.1.map(|s| s.to_string()), i.2.clone()))
|
||||
.collect();
|
||||
let exports = exports
|
||||
.iter()
|
||||
.map(|e| (e.0.to_string(), e.1.clone()))
|
||||
.collect();
|
||||
self.result
|
||||
.module
|
||||
.types
|
||||
.push(ModuleType::Module { imports, exports });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn declare_type_instance(&mut self, exports: &[(&'data str, EntityType)]) -> WasmResult<()> {
|
||||
let exports = exports
|
||||
.iter()
|
||||
.map(|e| (e.0.to_string(), e.1.clone()))
|
||||
.collect();
|
||||
self.result
|
||||
.module
|
||||
.types
|
||||
.push(ModuleType::Instance { exports });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -226,7 +262,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
||||
|
||||
fn declare_func_import(
|
||||
&mut self,
|
||||
sig_index: SignatureIndex,
|
||||
index: TypeIndex,
|
||||
module: &str,
|
||||
field: &str,
|
||||
) -> WasmResult<()> {
|
||||
@@ -235,6 +271,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
||||
self.result.module.num_imported_funcs,
|
||||
"Imported functions must be declared first"
|
||||
);
|
||||
let sig_index = self.result.module.types[index].unwrap_function();
|
||||
let func_index = self.result.module.functions.push(sig_index);
|
||||
self.result.module.imports.push((
|
||||
module.to_owned(),
|
||||
@@ -320,7 +357,8 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()> {
|
||||
fn declare_func_type(&mut self, index: TypeIndex) -> WasmResult<()> {
|
||||
let sig_index = self.result.module.types[index].unwrap_function();
|
||||
self.result.module.functions.push(sig_index);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user