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:
Alex Crichton
2020-11-06 14:48:09 -06:00
committed by GitHub
parent 77827a48a9
commit 73cda83548
27 changed files with 782 additions and 213 deletions

View File

@@ -23,14 +23,18 @@ mod r#extern;
mod func;
mod global;
mod import;
mod instance;
mod memory;
mod module;
mod table;
mod val;
pub use self::export::*;
pub use self::func::*;
pub use self::global::*;
pub use self::import::*;
pub use self::instance::*;
pub use self::memory::*;
pub use self::module::*;
pub use self::r#extern::*;
pub use self::table::*;
pub use self::val::*;

View File

@@ -1,5 +1,6 @@
use crate::{wasm_functype_t, wasm_globaltype_t, wasm_memorytype_t, wasm_tabletype_t};
use crate::{CFuncType, CGlobalType, CMemoryType, CTableType};
use crate::{wasm_instancetype_t, wasm_moduletype_t};
use crate::{CFuncType, CGlobalType, CInstanceType, CMemoryType, CModuleType, CTableType};
use wasmtime::ExternType;
#[repr(C)]
@@ -16,6 +17,8 @@ pub(crate) enum CExternType {
Global(CGlobalType),
Memory(CMemoryType),
Table(CTableType),
Instance(CInstanceType),
Module(CModuleType),
}
pub type wasm_externkind_t = u8;
@@ -24,6 +27,8 @@ pub const WASM_EXTERN_FUNC: wasm_externkind_t = 0;
pub const WASM_EXTERN_GLOBAL: wasm_externkind_t = 1;
pub const WASM_EXTERN_TABLE: wasm_externkind_t = 2;
pub const WASM_EXTERN_MEMORY: wasm_externkind_t = 3;
pub const WASMTIME_EXTERN_MODULE: wasm_externkind_t = 4;
pub const WASMTIME_EXTERN_INSTANCE: wasm_externkind_t = 5;
impl wasm_externtype_t {
pub(crate) fn new(ty: ExternType) -> wasm_externtype_t {
@@ -33,6 +38,8 @@ impl wasm_externtype_t {
ExternType::Global(f) => CExternType::Global(CGlobalType::new(f)),
ExternType::Memory(f) => CExternType::Memory(CMemoryType::new(f)),
ExternType::Table(f) => CExternType::Table(CTableType::new(f)),
ExternType::Instance(f) => CExternType::Instance(CInstanceType::new(f)),
ExternType::Module(f) => CExternType::Module(CModuleType::new(f)),
},
}
}
@@ -43,6 +50,8 @@ impl wasm_externtype_t {
CExternType::Table(f) => ExternType::Table(f.ty.clone()),
CExternType::Global(f) => ExternType::Global(f.ty.clone()),
CExternType::Memory(f) => ExternType::Memory(f.ty.clone()),
CExternType::Instance(f) => ExternType::Instance(f.ty.clone()),
CExternType::Module(f) => ExternType::Module(f.ty.clone()),
}
}
}
@@ -54,6 +63,8 @@ pub extern "C" fn wasm_externtype_kind(et: &wasm_externtype_t) -> wasm_externkin
CExternType::Table(_) => WASM_EXTERN_TABLE,
CExternType::Global(_) => WASM_EXTERN_GLOBAL,
CExternType::Memory(_) => WASM_EXTERN_MEMORY,
CExternType::Instance(_) => WASMTIME_EXTERN_INSTANCE,
CExternType::Module(_) => WASMTIME_EXTERN_MODULE,
}
}
@@ -110,3 +121,31 @@ pub extern "C" fn wasm_externtype_as_memorytype_const(
) -> Option<&wasm_memorytype_t> {
wasm_memorytype_t::try_from(et)
}
#[no_mangle]
pub extern "C" fn wasm_externtype_as_moduletype(
et: &wasm_externtype_t,
) -> Option<&wasm_moduletype_t> {
wasm_externtype_as_moduletype_const(et)
}
#[no_mangle]
pub extern "C" fn wasm_externtype_as_moduletype_const(
et: &wasm_externtype_t,
) -> Option<&wasm_moduletype_t> {
wasm_moduletype_t::try_from(et)
}
#[no_mangle]
pub extern "C" fn wasm_externtype_as_instancetype(
et: &wasm_externtype_t,
) -> Option<&wasm_instancetype_t> {
wasm_externtype_as_instancetype_const(et)
}
#[no_mangle]
pub extern "C" fn wasm_externtype_as_instancetype_const(
et: &wasm_externtype_t,
) -> Option<&wasm_instancetype_t> {
wasm_instancetype_t::try_from(et)
}

View File

@@ -0,0 +1,46 @@
use crate::{wasm_externtype_t, wasm_limits_t, CExternType};
use once_cell::unsync::OnceCell;
use wasmtime::InstanceType;
#[repr(transparent)]
#[derive(Clone)]
pub struct wasm_instancetype_t {
ext: wasm_externtype_t,
}
wasmtime_c_api_macros::declare_ty!(wasm_instancetype_t);
#[derive(Clone)]
pub(crate) struct CInstanceType {
pub(crate) ty: InstanceType,
limits_cache: OnceCell<wasm_limits_t>,
}
impl wasm_instancetype_t {
pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_instancetype_t> {
match &e.which {
CExternType::Instance(_) => Some(unsafe { &*(e as *const _ as *const _) }),
_ => None,
}
}
}
impl CInstanceType {
pub(crate) fn new(ty: InstanceType) -> CInstanceType {
CInstanceType {
ty,
limits_cache: OnceCell::new(),
}
}
}
#[no_mangle]
pub extern "C" fn wasm_instancetype_as_externtype(ty: &wasm_instancetype_t) -> &wasm_externtype_t {
&ty.ext
}
#[no_mangle]
pub extern "C" fn wasm_instancetype_as_externtype_const(
ty: &wasm_instancetype_t,
) -> &wasm_externtype_t {
&ty.ext
}

View File

@@ -0,0 +1,47 @@
use crate::{wasm_externtype_t, wasm_limits_t, CExternType};
use once_cell::unsync::OnceCell;
use wasmtime::ModuleType;
#[repr(transparent)]
#[derive(Clone)]
pub struct wasm_moduletype_t {
ext: wasm_externtype_t,
}
wasmtime_c_api_macros::declare_ty!(wasm_moduletype_t);
#[derive(Clone)]
pub(crate) struct CModuleType {
pub(crate) ty: ModuleType,
limits_cache: OnceCell<wasm_limits_t>,
}
impl wasm_moduletype_t {
pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_moduletype_t> {
match &e.which {
CExternType::Module(_) => Some(unsafe { &*(e as *const _ as *const _) }),
_ => None,
}
}
}
impl CModuleType {
pub(crate) fn new(ty: ModuleType) -> CModuleType {
CModuleType {
ty,
limits_cache: OnceCell::new(),
}
}
}
#[no_mangle]
pub extern "C" fn wasm_moduletype_as_externtype(ty: &wasm_moduletype_t) -> &wasm_externtype_t {
&ty.ext
}
#[no_mangle]
pub extern "C" fn wasm_moduletype_as_externtype_const(
ty: &wasm_moduletype_t,
) -> &wasm_externtype_t {
&ty.ext
}

View File

@@ -9,7 +9,7 @@ use cranelift_entity::{EntityRef, PrimaryMap};
use cranelift_frontend::FunctionBuilder;
use cranelift_wasm::{
self, FuncIndex, GlobalIndex, GlobalVariable, MemoryIndex, SignatureIndex, TableIndex,
TargetEnvironment, WasmError, WasmResult, WasmType,
TargetEnvironment, TypeIndex, WasmError, WasmResult, WasmType,
};
use std::convert::TryFrom;
use wasmtime_environ::{
@@ -996,8 +996,9 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
fn make_indirect_sig(
&mut self,
func: &mut ir::Function,
index: SignatureIndex,
index: TypeIndex,
) -> WasmResult<ir::SigRef> {
let index = self.module.types[index].unwrap_function();
Ok(func.import_signature(self.native_signatures[index].clone()))
}
@@ -1024,11 +1025,12 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
mut pos: FuncCursor<'_>,
table_index: TableIndex,
table: ir::Table,
sig_index: SignatureIndex,
ty_index: TypeIndex,
sig_ref: ir::SigRef,
callee: ir::Value,
call_args: &[ir::Value],
) -> WasmResult<ir::Inst> {
let sig_index = self.module.types[ty_index].unwrap_function();
let pointer_type = self.pointer_type();
let table_entry_addr = pos.ins().table_addr(pointer_type, table, callee, 0);

View File

@@ -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::*;
}

View File

@@ -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};

View File

@@ -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(),
}
}

View File

@@ -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(())
}

View File

@@ -17,6 +17,10 @@ pub fn dummy_imports<'module>(
ExternType::Global(global_ty) => Extern::Global(dummy_global(&store, global_ty)?),
ExternType::Table(table_ty) => Extern::Table(dummy_table(&store, table_ty)?),
ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(&store, mem_ty)),
// FIXME(#2094)
ExternType::Instance(_) => unimplemented!(),
ExternType::Module(_) => unimplemented!(),
})
})
.collect()

View File

@@ -28,10 +28,10 @@ use thiserror::Error;
use wasmtime_environ::entity::{packed_option::ReservedValue, BoxedSlice, EntityRef, PrimaryMap};
use wasmtime_environ::wasm::{
DataIndex, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex,
ElemIndex, FuncIndex, GlobalIndex, GlobalInit, MemoryIndex, SignatureIndex, TableElementType,
TableIndex, WasmType,
ElemIndex, EntityIndex, FuncIndex, GlobalIndex, GlobalInit, MemoryIndex, SignatureIndex,
TableElementType, TableIndex, WasmType,
};
use wasmtime_environ::{ir, DataInitializer, EntityIndex, Module, TableElements, VMOffsets};
use wasmtime_environ::{ir, DataInitializer, Module, TableElements, VMOffsets};
/// A WebAssembly instance.
///
@@ -325,6 +325,10 @@ impl Instance {
global: self.module.globals[*index],
}
.into(),
// FIXME(#2094)
EntityIndex::Instance(_index) => unimplemented!(),
EntityIndex::Module(_index) => unimplemented!(),
}
}

View File

@@ -3,7 +3,7 @@ use crate::{Engine, Export, Extern, Func, Global, Memory, Module, Store, Table,
use anyhow::{anyhow, bail, Context, Error, Result};
use std::any::Any;
use std::mem;
use wasmtime_environ::EntityIndex;
use wasmtime_environ::wasm::EntityIndex;
use wasmtime_jit::CompiledModule;
use wasmtime_runtime::{
Imports, InstantiationError, StackMapRegistry, VMContext, VMExternRefActivationsTable,
@@ -300,6 +300,10 @@ fn with_imports<R>(
}
functions.push(func.vmimport());
}
// FIXME(#2094)
EntityIndex::Module(_i) => unimplemented!(),
EntityIndex::Instance(_i) => unimplemented!(),
}
Ok(())
};

View File

@@ -516,6 +516,10 @@ impl Linker {
ExternType::Global(f) => ImportKind::Global(f),
ExternType::Memory(_) => ImportKind::Memory,
ExternType::Table(_) => ImportKind::Table,
// FIXME(#2094)
ExternType::Module(_) => unimplemented!(),
ExternType::Instance(_) => unimplemented!(),
}
}

View File

@@ -84,7 +84,12 @@ impl Config {
profiler: Arc::new(NullProfilerAgent),
memory_creator: None,
max_wasm_stack: 1 << 20,
features: WasmFeatures::default(),
features: WasmFeatures {
reference_types: true,
bulk_memory: true,
multi_value: true,
..WasmFeatures::default()
},
}
}
@@ -655,6 +660,7 @@ impl fmt::Debug for Config {
.field("wasm_bulk_memory", &self.features.bulk_memory)
.field("wasm_simd", &self.features.simd)
.field("wasm_multi_value", &self.features.multi_value)
.field("wasm_module_linking", &self.features.module_linking)
.field(
"flags",
&settings::Flags::new(self.flags.clone()).to_string(),

View File

@@ -10,7 +10,7 @@ use std::mem;
use std::panic::{self, AssertUnwindSafe};
use wasmtime_environ::entity::PrimaryMap;
use wasmtime_environ::isa::TargetIsa;
use wasmtime_environ::{ir, CompiledFunction, EntityIndex, Module};
use wasmtime_environ::{ir, wasm, CompiledFunction, Module};
use wasmtime_jit::trampoline::ir::{
ExternalName, Function, InstBuilder, MemFlags, StackSlotData, StackSlotKind,
};
@@ -227,7 +227,7 @@ pub fn create_handle_with_function(
let func_id = module.functions.push(sig_id);
module
.exports
.insert(String::new(), EntityIndex::Function(func_id));
.insert(String::new(), wasm::EntityIndex::Function(func_id));
let trampoline = make_trampoline(isa.as_ref(), &mut code_memory, &mut fn_builder_ctx, &sig);
finished_functions.push(trampoline);
@@ -274,7 +274,7 @@ pub unsafe fn create_handle_with_raw_function(
let func_id = module.functions.push(sig_id);
module
.exports
.insert(String::new(), EntityIndex::Function(func_id));
.insert(String::new(), wasm::EntityIndex::Function(func_id));
finished_functions.push(func);
store.signatures().borrow_mut().register(wft, trampoline);

View File

@@ -3,7 +3,7 @@ use crate::trampoline::StoreInstanceHandle;
use crate::{GlobalType, Mutability, Store, Val};
use anyhow::Result;
use wasmtime_environ::entity::PrimaryMap;
use wasmtime_environ::{wasm, EntityIndex, Module};
use wasmtime_environ::{wasm, Module};
use wasmtime_runtime::VMFunctionImport;
pub fn create_global(store: &Store, gt: &GlobalType, val: Val) -> Result<StoreInstanceHandle> {
@@ -43,9 +43,11 @@ pub fn create_global(store: &Store, gt: &GlobalType, val: Val) -> Result<StoreIn
let local_sig_index = module.signatures.push(wasm.clone());
let func_index = module.functions.push(local_sig_index);
module.num_imported_funcs = 1;
module
.imports
.push(("".into(), "".into(), EntityIndex::Function(func_index)));
module.imports.push((
"".into(),
"".into(),
wasm::EntityIndex::Function(func_index),
));
let f = f.caller_checked_anyfunc();
let f = unsafe { f.as_ref() };
@@ -63,7 +65,7 @@ pub fn create_global(store: &Store, gt: &GlobalType, val: Val) -> Result<StoreIn
let global_id = module.globals.push(global);
module
.exports
.insert(String::new(), EntityIndex::Global(global_id));
.insert(String::new(), wasm::EntityIndex::Global(global_id));
let handle = create_handle(
module,
store,

View File

@@ -5,7 +5,7 @@ use crate::Store;
use crate::{Limits, MemoryType};
use anyhow::Result;
use wasmtime_environ::entity::PrimaryMap;
use wasmtime_environ::{wasm, EntityIndex, MemoryPlan, MemoryStyle, Module, WASM_PAGE_SIZE};
use wasmtime_environ::{wasm, MemoryPlan, MemoryStyle, Module, WASM_PAGE_SIZE};
use wasmtime_runtime::{RuntimeLinearMemory, RuntimeMemoryCreator, VMMemoryDefinition};
use std::sync::Arc;
@@ -27,7 +27,7 @@ pub fn create_handle_with_memory(
let memory_id = module.memory_plans.push(memory_plan);
module
.exports
.insert(String::new(), EntityIndex::Memory(memory_id));
.insert(String::new(), wasm::EntityIndex::Memory(memory_id));
create_handle(module, store, PrimaryMap::new(), Box::new(()), &[])
}

View File

@@ -4,7 +4,7 @@ use crate::Store;
use crate::{TableType, ValType};
use anyhow::{bail, Result};
use wasmtime_environ::entity::PrimaryMap;
use wasmtime_environ::{wasm, EntityIndex, Module};
use wasmtime_environ::{wasm, Module};
pub fn create_handle_with_table(store: &Store, table: &TableType) -> Result<StoreInstanceHandle> {
let mut module = Module::new();
@@ -25,7 +25,7 @@ pub fn create_handle_with_table(store: &Store, table: &TableType) -> Result<Stor
let table_id = module.table_plans.push(table_plan);
module
.exports
.insert(String::new(), EntityIndex::Table(table_id));
.insert(String::new(), wasm::EntityIndex::Table(table_id));
create_handle(module, store, PrimaryMap::new(), Box::new(()), &[])
}

View File

@@ -1,6 +1,6 @@
use std::fmt;
use wasmtime_environ::wasm::WasmFuncType;
use wasmtime_environ::{ir, wasm, EntityIndex};
use wasmtime_environ::{ir, wasm};
// Type Representations
@@ -144,7 +144,7 @@ impl ValType {
///
/// This list can be found in [`ImportType`] or [`ExportType`], so these types
/// can either be imported or exported.
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
#[derive(Debug, Clone)]
pub enum ExternType {
/// This external type is the type of a WebAssembly function.
Func(FuncType),
@@ -154,6 +154,10 @@ pub enum ExternType {
Table(TableType),
/// This external type is the type of a WebAssembly memory.
Memory(MemoryType),
/// This external type is the type of a WebAssembly instance.
Instance(InstanceType),
/// This external type is the type of a WebAssembly module.
Module(ModuleType),
}
macro_rules! accessors {
@@ -186,6 +190,39 @@ impl ExternType {
(Global(GlobalType) global unwrap_global)
(Table(TableType) table unwrap_table)
(Memory(MemoryType) memory unwrap_memory)
(Module(ModuleType) module unwrap_module)
(Instance(InstanceType) instance unwrap_instance)
}
fn from_wasmtime(
module: &wasmtime_environ::Module,
ty: &wasmtime_environ::wasm::EntityType,
) -> ExternType {
use wasmtime_environ::wasm::EntityType;
match ty {
EntityType::Function(idx) => {
let sig = module.types[*idx].unwrap_function();
let sig = &module.signatures[sig];
FuncType::from_wasm_func_type(sig).into()
}
EntityType::Global(ty) => GlobalType::from_wasmtime_global(ty).into(),
EntityType::Memory(ty) => MemoryType::from_wasmtime_memory(ty).into(),
EntityType::Table(ty) => TableType::from_wasmtime_table(ty).into(),
EntityType::Module(ty) => {
let (imports, exports) = match &module.types[*ty] {
wasmtime_environ::ModuleType::Module { imports, exports } => (imports, exports),
_ => unreachable!("not possible in valid wasm modules"),
};
ModuleType::from_wasmtime(module, imports, exports).into()
}
EntityType::Instance(ty) => {
let exports = match &module.types[*ty] {
wasmtime_environ::ModuleType::Instance { exports } => exports,
_ => unreachable!("not possible in valid wasm modules"),
};
InstanceType::from_wasmtime(module, exports).into()
}
}
}
}
@@ -213,6 +250,18 @@ impl From<TableType> for ExternType {
}
}
impl From<ModuleType> for ExternType {
fn from(ty: ModuleType) -> ExternType {
ExternType::Module(ty)
}
}
impl From<InstanceType> for ExternType {
fn from(ty: InstanceType) -> ExternType {
ExternType::Instance(ty)
}
}
/// A descriptor for a function in a WebAssembly module.
///
/// WebAssembly functions can have 0 or more parameters and results.
@@ -397,34 +446,198 @@ impl MemoryType {
}
}
// Module Types
/// A descriptor for a WebAssembly module type.
///
/// This is a part of the [WebAssembly module-linking proposal][proposal].
///
/// [proposal]: https://github.com/webassembly/module-linking
#[derive(Debug, Clone)]
pub struct ModuleType {
imports: Vec<(String, Option<String>, ExternType)>,
exports: Vec<(String, ExternType)>,
}
impl ModuleType {
/// Creates a new empty module type.
pub fn new() -> ModuleType {
ModuleType {
imports: Vec::new(),
exports: Vec::new(),
}
}
/// Adds a new export to this `ModuleType`.
pub fn add_named_export(&mut self, name: &str, ty: ExternType) {
self.exports.push((name.to_string(), ty));
}
/// Adds a new import to this `ModuleType`.
pub fn add_named_import(&mut self, module: &str, field: Option<&str>, ty: ExternType) {
self.imports
.push((module.to_string(), field.map(|f| f.to_string()), ty));
}
/// Returns the list of imports associated with this module type.
pub fn imports(&self) -> impl ExactSizeIterator<Item = ImportType<'_>> {
self.imports.iter().map(|(module, name, ty)| {
ImportType {
module,
// FIXME(#2094) should thread through the `Option`
name: name.as_ref().unwrap(),
ty: EntityOrExtern::Extern(ty),
}
})
}
/// Returns the list of exports associated with this module type.
pub fn exports(&self) -> impl ExactSizeIterator<Item = ExportType<'_>> {
self.exports.iter().map(|(name, ty)| ExportType {
name,
ty: EntityOrExtern::Extern(ty),
})
}
pub(crate) fn from_wasmtime(
module: &wasmtime_environ::Module,
imports: &[(String, Option<String>, wasmtime_environ::wasm::EntityType)],
exports: &[(String, wasmtime_environ::wasm::EntityType)],
) -> ModuleType {
ModuleType {
exports: exports
.iter()
.map(|(name, ty)| (name.to_string(), ExternType::from_wasmtime(module, ty)))
.collect(),
imports: imports
.iter()
.map(|(m, name, ty)| {
(
m.to_string(),
name.as_ref().map(|n| n.to_string()),
ExternType::from_wasmtime(module, ty),
)
})
.collect(),
}
}
}
// Instance Types
/// A descriptor for a WebAssembly instance type.
///
/// This is a part of the [WebAssembly module-linking proposal][proposal].
///
/// [proposal]: https://github.com/webassembly/module-linking
#[derive(Debug, Clone)]
pub struct InstanceType {
exports: Vec<(String, ExternType)>,
}
impl InstanceType {
/// Creates a new empty instance type.
pub fn new() -> InstanceType {
InstanceType {
exports: Vec::new(),
}
}
/// Adds a new export to this `ModuleType`.
pub fn add_named_export(&mut self, name: &str, ty: ExternType) {
self.exports.push((name.to_string(), ty));
}
/// Returns the list of exports associated with this module type.
pub fn exports(&self) -> impl ExactSizeIterator<Item = ExportType<'_>> {
self.exports.iter().map(|(name, ty)| ExportType {
name,
ty: EntityOrExtern::Extern(ty),
})
}
pub(crate) fn from_wasmtime(
module: &wasmtime_environ::Module,
exports: &[(String, wasmtime_environ::wasm::EntityType)],
) -> InstanceType {
InstanceType {
exports: exports
.iter()
.map(|(name, ty)| (name.to_string(), ExternType::from_wasmtime(module, ty)))
.collect(),
}
}
}
// Entity Types
#[derive(Clone, Hash, Eq, PartialEq)]
#[derive(Clone)]
pub(crate) enum EntityType<'module> {
Function(&'module wasm::WasmFuncType),
Table(&'module wasm::Table),
Memory(&'module wasm::Memory),
Global(&'module wasm::Global),
Module {
imports: &'module [(String, Option<String>, wasmtime_environ::wasm::EntityType)],
exports: &'module [(String, wasmtime_environ::wasm::EntityType)],
module: &'module wasmtime_environ::Module,
},
Instance {
exports: &'module [(String, wasmtime_environ::wasm::EntityType)],
module: &'module wasmtime_environ::Module,
},
}
impl<'module> EntityType<'module> {
/// Translate from a `EntityIndex` into an `ExternType`.
pub(crate) fn new(
entity_index: &EntityIndex,
entity_index: &wasm::EntityIndex,
module: &'module wasmtime_environ::Module,
) -> EntityType<'module> {
match entity_index {
EntityIndex::Function(func_index) => {
wasm::EntityIndex::Function(func_index) => {
let sig = module.wasm_func_type(*func_index);
EntityType::Function(&sig)
}
EntityIndex::Table(table_index) => {
wasm::EntityIndex::Table(table_index) => {
EntityType::Table(&module.table_plans[*table_index].table)
}
EntityIndex::Memory(memory_index) => {
wasm::EntityIndex::Memory(memory_index) => {
EntityType::Memory(&module.memory_plans[*memory_index].memory)
}
EntityIndex::Global(global_index) => EntityType::Global(&module.globals[*global_index]),
wasm::EntityIndex::Global(global_index) => {
EntityType::Global(&module.globals[*global_index])
}
wasm::EntityIndex::Module(idx) => {
let (imports, exports) = match &module.types[module.modules[*idx]] {
wasmtime_environ::ModuleType::Module { imports, exports } => (imports, exports),
_ => unreachable!("valid modules should never hit this"),
};
EntityType::Module {
imports,
exports,
module,
}
}
wasm::EntityIndex::Instance(idx) => {
// Get the type, either a pointer to an instance for an import
// or a module for an instantiation.
let ty = match module.instances[*idx] {
wasmtime_environ::Instance::Import(ty) => ty,
wasmtime_environ::Instance::Instantiate { module: idx, .. } => {
module.modules[idx]
}
};
// Get the exports of whatever our type specifies, ignoring
// imports in the module case since we're instantiating the
// module.
let exports = match &module.types[ty] {
wasmtime_environ::ModuleType::Instance { exports } => exports,
wasmtime_environ::ModuleType::Module { exports, .. } => exports,
_ => unreachable!("valid modules should never hit this"),
};
EntityType::Instance { exports, module }
}
}
}
@@ -435,6 +648,14 @@ impl<'module> EntityType<'module> {
EntityType::Table(table) => TableType::from_wasmtime_table(table).into(),
EntityType::Memory(memory) => MemoryType::from_wasmtime_memory(memory).into(),
EntityType::Global(global) => GlobalType::from_wasmtime_global(global).into(),
EntityType::Instance { exports, module } => {
InstanceType::from_wasmtime(module, exports).into()
}
EntityType::Module {
imports,
exports,
module,
} => ModuleType::from_wasmtime(module, imports, exports).into(),
}
}
}
@@ -447,7 +668,7 @@ impl<'module> EntityType<'module> {
/// [`Module::imports`](crate::Module::imports) API. Each [`ImportType`]
/// describes an import into the wasm module with the module/name that it's
/// imported from as well as the type of item that's being imported.
#[derive(Clone, Hash, Eq, PartialEq)]
#[derive(Clone)]
pub struct ImportType<'module> {
/// The module of the import.
module: &'module str,
@@ -456,7 +677,13 @@ pub struct ImportType<'module> {
name: &'module str,
/// The type of the import.
ty: EntityType<'module>,
ty: EntityOrExtern<'module>,
}
#[derive(Clone)]
enum EntityOrExtern<'a> {
Entity(EntityType<'a>),
Extern(&'a ExternType),
}
impl<'module> ImportType<'module> {
@@ -467,7 +694,11 @@ impl<'module> ImportType<'module> {
name: &'module str,
ty: EntityType<'module>,
) -> ImportType<'module> {
ImportType { module, name, ty }
ImportType {
module,
name,
ty: EntityOrExtern::Entity(ty),
}
}
/// Returns the module name that this import is expected to come from.
@@ -483,7 +714,10 @@ impl<'module> ImportType<'module> {
/// Returns the expected type of this import.
pub fn ty(&self) -> ExternType {
self.ty.extern_type()
match &self.ty {
EntityOrExtern::Entity(e) => e.extern_type(),
EntityOrExtern::Extern(e) => (*e).clone(),
}
}
}
@@ -505,20 +739,23 @@ impl<'module> fmt::Debug for ImportType<'module> {
/// [`Module::exports`](crate::Module::exports) accessor and describes what
/// names are exported from a wasm module and the type of the item that is
/// exported.
#[derive(Clone, Hash, Eq, PartialEq)]
#[derive(Clone)]
pub struct ExportType<'module> {
/// The name of the export.
name: &'module str,
/// The type of the export.
ty: EntityType<'module>,
ty: EntityOrExtern<'module>,
}
impl<'module> ExportType<'module> {
/// Creates a new export which is exported with the given `name` and has the
/// given `ty`.
pub(crate) fn new(name: &'module str, ty: EntityType<'module>) -> ExportType<'module> {
ExportType { name, ty }
ExportType {
name,
ty: EntityOrExtern::Entity(ty),
}
}
/// Returns the name by which this export is known.
@@ -528,7 +765,10 @@ impl<'module> ExportType<'module> {
/// Returns the type of this export.
pub fn ty(&self) -> ExternType {
self.ty.extern_type()
match &self.ty {
EntityOrExtern::Entity(e) => e.extern_type(),
EntityOrExtern::Extern(e) => (*e).clone(),
}
}
}