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:
@@ -77,7 +77,7 @@ use crate::state::{ControlStackFrame, ElseData, FuncTranslationState};
|
|||||||
use crate::translation_utils::{
|
use crate::translation_utils::{
|
||||||
block_with_params, blocktype_params_results, f32_translation, f64_translation,
|
block_with_params, blocktype_params_results, f32_translation, f64_translation,
|
||||||
};
|
};
|
||||||
use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex};
|
use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex, TypeIndex};
|
||||||
use crate::wasm_unsupported;
|
use crate::wasm_unsupported;
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
use core::{i32, u32};
|
use core::{i32, u32};
|
||||||
@@ -587,7 +587,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
builder.cursor(),
|
builder.cursor(),
|
||||||
TableIndex::from_u32(*table_index),
|
TableIndex::from_u32(*table_index),
|
||||||
table,
|
table,
|
||||||
SignatureIndex::from_u32(*index),
|
TypeIndex::from_u32(*index),
|
||||||
sigref,
|
sigref,
|
||||||
callee,
|
callee,
|
||||||
state.peekn(num_args),
|
state.peekn(num_args),
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use crate::environ::{
|
|||||||
use crate::func_translator::FuncTranslator;
|
use crate::func_translator::FuncTranslator;
|
||||||
use crate::translation_utils::{
|
use crate::translation_utils::{
|
||||||
DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex,
|
DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex,
|
||||||
SignatureIndex, Table, TableIndex,
|
Table, TableIndex, TypeIndex,
|
||||||
};
|
};
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use cranelift_codegen::cursor::FuncCursor;
|
use cranelift_codegen::cursor::FuncCursor;
|
||||||
@@ -58,7 +58,7 @@ pub struct DummyModuleInfo {
|
|||||||
config: TargetFrontendConfig,
|
config: TargetFrontendConfig,
|
||||||
|
|
||||||
/// Signatures as provided by `declare_signature`.
|
/// Signatures as provided by `declare_signature`.
|
||||||
pub signatures: PrimaryMap<SignatureIndex, ir::Signature>,
|
pub signatures: PrimaryMap<TypeIndex, ir::Signature>,
|
||||||
|
|
||||||
/// Module and field names of imported functions as provided by `declare_func_import`.
|
/// Module and field names of imported functions as provided by `declare_func_import`.
|
||||||
pub imported_funcs: Vec<(String, String)>,
|
pub imported_funcs: Vec<(String, String)>,
|
||||||
@@ -73,7 +73,7 @@ pub struct DummyModuleInfo {
|
|||||||
pub imported_memories: Vec<(String, String)>,
|
pub imported_memories: Vec<(String, String)>,
|
||||||
|
|
||||||
/// Functions, imported and local.
|
/// Functions, imported and local.
|
||||||
pub functions: PrimaryMap<FuncIndex, Exportable<SignatureIndex>>,
|
pub functions: PrimaryMap<FuncIndex, Exportable<TypeIndex>>,
|
||||||
|
|
||||||
/// Function bodies.
|
/// Function bodies.
|
||||||
pub function_bodies: PrimaryMap<DefinedFuncIndex, ir::Function>,
|
pub function_bodies: PrimaryMap<DefinedFuncIndex, ir::Function>,
|
||||||
@@ -157,7 +157,7 @@ impl DummyEnvironment {
|
|||||||
DummyFuncEnvironment::new(&self.info, self.return_mode)
|
DummyFuncEnvironment::new(&self.info, self.return_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex {
|
fn get_func_type(&self, func_index: FuncIndex) -> TypeIndex {
|
||||||
self.info.functions[func_index].entity
|
self.info.functions[func_index].entity
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ impl<'dummy_environment> DummyFuncEnvironment<'dummy_environment> {
|
|||||||
|
|
||||||
// Create a signature for `sigidx` amended with a `vmctx` argument after the standard wasm
|
// Create a signature for `sigidx` amended with a `vmctx` argument after the standard wasm
|
||||||
// arguments.
|
// arguments.
|
||||||
fn vmctx_sig(&self, sigidx: SignatureIndex) -> ir::Signature {
|
fn vmctx_sig(&self, sigidx: TypeIndex) -> ir::Signature {
|
||||||
let mut sig = self.mod_info.signatures[sigidx].clone();
|
let mut sig = self.mod_info.signatures[sigidx].clone();
|
||||||
sig.params.push(ir::AbiParam::special(
|
sig.params.push(ir::AbiParam::special(
|
||||||
self.pointer_type(),
|
self.pointer_type(),
|
||||||
@@ -283,7 +283,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
|||||||
fn make_indirect_sig(
|
fn make_indirect_sig(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &mut ir::Function,
|
func: &mut ir::Function,
|
||||||
index: SignatureIndex,
|
index: TypeIndex,
|
||||||
) -> WasmResult<ir::SigRef> {
|
) -> WasmResult<ir::SigRef> {
|
||||||
// A real implementation would probably change the calling convention and add `vmctx` and
|
// A real implementation would probably change the calling convention and add `vmctx` and
|
||||||
// signature index arguments.
|
// signature index arguments.
|
||||||
@@ -312,7 +312,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
|||||||
mut pos: FuncCursor,
|
mut pos: FuncCursor,
|
||||||
_table_index: TableIndex,
|
_table_index: TableIndex,
|
||||||
_table: ir::Table,
|
_table: ir::Table,
|
||||||
_sig_index: SignatureIndex,
|
_sig_index: TypeIndex,
|
||||||
sig_ref: ir::SigRef,
|
sig_ref: ir::SigRef,
|
||||||
callee: ir::Value,
|
callee: ir::Value,
|
||||||
call_args: &[ir::Value],
|
call_args: &[ir::Value],
|
||||||
@@ -572,14 +572,14 @@ impl TargetEnvironment for DummyEnvironment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
||||||
fn declare_signature(&mut self, _wasm: WasmFuncType, sig: ir::Signature) -> WasmResult<()> {
|
fn declare_type_func(&mut self, _wasm: WasmFuncType, sig: ir::Signature) -> WasmResult<()> {
|
||||||
self.info.signatures.push(sig);
|
self.info.signatures.push(sig);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_func_import(
|
fn declare_func_import(
|
||||||
&mut self,
|
&mut self,
|
||||||
sig_index: SignatureIndex,
|
index: TypeIndex,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: &'data str,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
@@ -588,15 +588,15 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
|||||||
self.info.imported_funcs.len(),
|
self.info.imported_funcs.len(),
|
||||||
"Imported functions must be declared first"
|
"Imported functions must be declared first"
|
||||||
);
|
);
|
||||||
self.info.functions.push(Exportable::new(sig_index));
|
self.info.functions.push(Exportable::new(index));
|
||||||
self.info
|
self.info
|
||||||
.imported_funcs
|
.imported_funcs
|
||||||
.push((String::from(module), String::from(field)));
|
.push((String::from(module), String::from(field)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()> {
|
fn declare_func_type(&mut self, index: TypeIndex) -> WasmResult<()> {
|
||||||
self.info.functions.push(Exportable::new(sig_index));
|
self.info.functions.push(Exportable::new(index));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
use crate::state::FuncTranslationState;
|
use crate::state::FuncTranslationState;
|
||||||
use crate::translation_utils::{
|
use crate::translation_utils::{
|
||||||
DataIndex, ElemIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex,
|
DataIndex, ElemIndex, EntityType, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, Table,
|
||||||
Table, TableIndex,
|
TableIndex, TypeIndex,
|
||||||
};
|
};
|
||||||
use core::convert::From;
|
use core::convert::From;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
@@ -293,7 +293,7 @@ pub trait FuncEnvironment: TargetEnvironment {
|
|||||||
fn make_indirect_sig(
|
fn make_indirect_sig(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &mut ir::Function,
|
func: &mut ir::Function,
|
||||||
index: SignatureIndex,
|
index: TypeIndex,
|
||||||
) -> WasmResult<ir::SigRef>;
|
) -> WasmResult<ir::SigRef>;
|
||||||
|
|
||||||
/// Set up an external function definition in the preamble of `func` that can be used to
|
/// Set up an external function definition in the preamble of `func` that can be used to
|
||||||
@@ -328,7 +328,7 @@ pub trait FuncEnvironment: TargetEnvironment {
|
|||||||
pos: FuncCursor,
|
pos: FuncCursor,
|
||||||
table_index: TableIndex,
|
table_index: TableIndex,
|
||||||
table: ir::Table,
|
table: ir::Table,
|
||||||
sig_index: SignatureIndex,
|
sig_index: TypeIndex,
|
||||||
sig_ref: ir::SigRef,
|
sig_ref: ir::SigRef,
|
||||||
callee: ir::Value,
|
callee: ir::Value,
|
||||||
call_args: &[ir::Value],
|
call_args: &[ir::Value],
|
||||||
@@ -630,19 +630,35 @@ pub trait FuncEnvironment: TargetEnvironment {
|
|||||||
/// [`translate_module`](fn.translate_module.html) function. These methods should not be called
|
/// [`translate_module`](fn.translate_module.html) function. These methods should not be called
|
||||||
/// by the user, they are only for `cranelift-wasm` internal use.
|
/// by the user, they are only for `cranelift-wasm` internal use.
|
||||||
pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
||||||
/// Provides the number of signatures up front. By default this does nothing, but
|
/// Provides the number of types up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
fn reserve_signatures(&mut self, _num: u32) -> WasmResult<()> {
|
fn reserve_types(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Declares a function signature to the environment.
|
/// Declares a function signature to the environment.
|
||||||
fn declare_signature(
|
fn declare_type_func(
|
||||||
&mut self,
|
&mut self,
|
||||||
wasm_func_type: WasmFuncType,
|
wasm_func_type: WasmFuncType,
|
||||||
sig: ir::Signature,
|
sig: ir::Signature,
|
||||||
) -> WasmResult<()>;
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
|
/// Declares a module type signature to the environment.
|
||||||
|
fn declare_type_module(
|
||||||
|
&mut self,
|
||||||
|
imports: &[(&'data str, Option<&'data str>, EntityType)],
|
||||||
|
exports: &[(&'data str, EntityType)],
|
||||||
|
) -> WasmResult<()> {
|
||||||
|
drop((imports, exports));
|
||||||
|
Err(WasmError::Unsupported("module linking".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Declares an instance type signature to the environment.
|
||||||
|
fn declare_type_instance(&mut self, exports: &[(&'data str, EntityType)]) -> WasmResult<()> {
|
||||||
|
drop(exports);
|
||||||
|
Err(WasmError::Unsupported("module linking".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Provides the number of imports up front. By default this does nothing, but
|
/// Provides the number of imports up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
fn reserve_imports(&mut self, _num: u32) -> WasmResult<()> {
|
fn reserve_imports(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
@@ -652,7 +668,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
|||||||
/// Declares a function import to the environment.
|
/// Declares a function import to the environment.
|
||||||
fn declare_func_import(
|
fn declare_func_import(
|
||||||
&mut self,
|
&mut self,
|
||||||
sig_index: SignatureIndex,
|
index: TypeIndex,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: &'data str,
|
||||||
) -> WasmResult<()>;
|
) -> WasmResult<()>;
|
||||||
@@ -681,6 +697,28 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
|||||||
field: &'data str,
|
field: &'data str,
|
||||||
) -> WasmResult<()>;
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
|
/// Declares a module import to the environment.
|
||||||
|
fn declare_module_import(
|
||||||
|
&mut self,
|
||||||
|
ty_index: TypeIndex,
|
||||||
|
module: &'data str,
|
||||||
|
field: &'data str,
|
||||||
|
) -> WasmResult<()> {
|
||||||
|
drop((ty_index, module, field));
|
||||||
|
Err(WasmError::Unsupported("module linking".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Declares an instance import to the environment.
|
||||||
|
fn declare_instance_import(
|
||||||
|
&mut self,
|
||||||
|
ty_index: TypeIndex,
|
||||||
|
module: &'data str,
|
||||||
|
field: &'data str,
|
||||||
|
) -> WasmResult<()> {
|
||||||
|
drop((ty_index, module, field));
|
||||||
|
Err(WasmError::Unsupported("module linking".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Notifies the implementation that all imports have been declared.
|
/// Notifies the implementation that all imports have been declared.
|
||||||
fn finish_imports(&mut self) -> WasmResult<()> {
|
fn finish_imports(&mut self) -> WasmResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -693,7 +731,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Declares the type (signature) of a local function in the module.
|
/// Declares the type (signature) of a local function in the module.
|
||||||
fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()>;
|
fn declare_func_type(&mut self, index: TypeIndex) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Provides the number of defined tables up front. By default this does nothing, but
|
/// Provides the number of defined tables up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
|
|||||||
@@ -65,11 +65,7 @@ pub use crate::func_translator::FuncTranslator;
|
|||||||
pub use crate::module_translator::translate_module;
|
pub use crate::module_translator::translate_module;
|
||||||
pub use crate::state::func_state::FuncTranslationState;
|
pub use crate::state::func_state::FuncTranslationState;
|
||||||
pub use crate::state::module_state::ModuleTranslationState;
|
pub use crate::state::module_state::ModuleTranslationState;
|
||||||
pub use crate::translation_utils::{
|
pub use crate::translation_utils::*;
|
||||||
get_vmctx_value_label, DataIndex, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex,
|
|
||||||
DefinedTableIndex, ElemIndex, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex,
|
|
||||||
SignatureIndex, Table, TableElementType, TableIndex,
|
|
||||||
};
|
|
||||||
pub use cranelift_frontend::FunctionBuilder;
|
pub use cranelift_frontend::FunctionBuilder;
|
||||||
|
|
||||||
// Convenience reexport of the wasmparser crate that we're linking against,
|
// Convenience reexport of the wasmparser crate that we're linking against,
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
use crate::environ::{ModuleEnvironment, WasmError, WasmResult};
|
use crate::environ::{ModuleEnvironment, WasmError, WasmResult};
|
||||||
use crate::state::ModuleTranslationState;
|
use crate::state::ModuleTranslationState;
|
||||||
use crate::translation_utils::{
|
use crate::translation_utils::{
|
||||||
tabletype_to_type, type_to_type, DataIndex, ElemIndex, FuncIndex, Global, GlobalIndex,
|
tabletype_to_type, type_to_type, DataIndex, ElemIndex, EntityType, FuncIndex, Global,
|
||||||
GlobalInit, Memory, MemoryIndex, SignatureIndex, Table, TableElementType, TableIndex,
|
GlobalIndex, GlobalInit, Memory, MemoryIndex, Table, TableElementType, TableIndex, TypeIndex,
|
||||||
};
|
};
|
||||||
use crate::wasm_unsupported;
|
use crate::wasm_unsupported;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
@@ -27,18 +27,71 @@ use wasmparser::{
|
|||||||
ElementSectionReader, Export, ExportSectionReader, ExternalKind, FunctionSectionReader,
|
ElementSectionReader, Export, ExportSectionReader, ExternalKind, FunctionSectionReader,
|
||||||
GlobalSectionReader, GlobalType, ImportSectionEntryType, ImportSectionReader,
|
GlobalSectionReader, GlobalType, ImportSectionEntryType, ImportSectionReader,
|
||||||
MemorySectionReader, MemoryType, NameSectionReader, Naming, Operator, TableSectionReader,
|
MemorySectionReader, MemoryType, NameSectionReader, Naming, Operator, TableSectionReader,
|
||||||
TypeDef, TypeSectionReader,
|
TableType, TypeDef, TypeSectionReader,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn entity_type(
|
||||||
|
ty: ImportSectionEntryType,
|
||||||
|
environ: &mut dyn ModuleEnvironment<'_>,
|
||||||
|
) -> WasmResult<EntityType> {
|
||||||
|
Ok(match ty {
|
||||||
|
ImportSectionEntryType::Function(sig) => EntityType::Function(TypeIndex::from_u32(sig)),
|
||||||
|
ImportSectionEntryType::Module(sig) => EntityType::Module(TypeIndex::from_u32(sig)),
|
||||||
|
ImportSectionEntryType::Instance(sig) => EntityType::Instance(TypeIndex::from_u32(sig)),
|
||||||
|
ImportSectionEntryType::Memory(ty) => EntityType::Memory(memory(ty)),
|
||||||
|
ImportSectionEntryType::Global(ty) => {
|
||||||
|
EntityType::Global(global(ty, environ, GlobalInit::Import)?)
|
||||||
|
}
|
||||||
|
ImportSectionEntryType::Table(ty) => EntityType::Table(table(ty, environ)?),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn memory(ty: MemoryType) -> Memory {
|
||||||
|
match ty {
|
||||||
|
MemoryType::M32 { limits, shared } => Memory {
|
||||||
|
minimum: limits.initial,
|
||||||
|
maximum: limits.maximum,
|
||||||
|
shared: shared,
|
||||||
|
},
|
||||||
|
// FIXME(#2361)
|
||||||
|
MemoryType::M64 { .. } => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn table(ty: TableType, environ: &mut dyn ModuleEnvironment<'_>) -> WasmResult<Table> {
|
||||||
|
Ok(Table {
|
||||||
|
wasm_ty: ty.element_type.try_into()?,
|
||||||
|
ty: match tabletype_to_type(ty.element_type, environ)? {
|
||||||
|
Some(t) => TableElementType::Val(t),
|
||||||
|
None => TableElementType::Func,
|
||||||
|
},
|
||||||
|
minimum: ty.limits.initial,
|
||||||
|
maximum: ty.limits.maximum,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn global(
|
||||||
|
ty: GlobalType,
|
||||||
|
environ: &mut dyn ModuleEnvironment<'_>,
|
||||||
|
initializer: GlobalInit,
|
||||||
|
) -> WasmResult<Global> {
|
||||||
|
Ok(Global {
|
||||||
|
wasm_ty: ty.content_type.try_into()?,
|
||||||
|
ty: type_to_type(ty.content_type, environ).unwrap(),
|
||||||
|
mutability: ty.mutable,
|
||||||
|
initializer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses the Type section of the wasm module.
|
/// Parses the Type section of the wasm module.
|
||||||
pub fn parse_type_section(
|
pub fn parse_type_section<'a>(
|
||||||
types: TypeSectionReader,
|
types: TypeSectionReader<'a>,
|
||||||
module_translation_state: &mut ModuleTranslationState,
|
module_translation_state: &mut ModuleTranslationState,
|
||||||
environ: &mut dyn ModuleEnvironment,
|
environ: &mut dyn ModuleEnvironment<'a>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
let count = types.get_count();
|
let count = types.get_count();
|
||||||
module_translation_state.wasm_types.reserve(count as usize);
|
module_translation_state.wasm_types.reserve(count as usize);
|
||||||
environ.reserve_signatures(count)?;
|
environ.reserve_types(count)?;
|
||||||
|
|
||||||
for entry in types {
|
for entry in types {
|
||||||
match entry? {
|
match entry? {
|
||||||
@@ -55,28 +108,31 @@ pub fn parse_type_section(
|
|||||||
.expect("only numeric types are supported in function signatures");
|
.expect("only numeric types are supported in function signatures");
|
||||||
AbiParam::new(cret_arg)
|
AbiParam::new(cret_arg)
|
||||||
}));
|
}));
|
||||||
environ.declare_signature(wasm_func_ty.clone().try_into()?, sig)?;
|
environ.declare_type_func(wasm_func_ty.clone().try_into()?, sig)?;
|
||||||
module_translation_state
|
module_translation_state
|
||||||
.wasm_types
|
.wasm_types
|
||||||
.push((wasm_func_ty.params, wasm_func_ty.returns));
|
.push((wasm_func_ty.params, wasm_func_ty.returns));
|
||||||
}
|
}
|
||||||
|
TypeDef::Module(t) => {
|
||||||
// Not implemented yet for module linking. Push dummy function types
|
let imports = t
|
||||||
// though to keep the function type index space consistent. We'll
|
.imports
|
||||||
// want an actual implementation here that handles this eventually.
|
.iter()
|
||||||
TypeDef::Module(_) | TypeDef::Instance(_) => {
|
.map(|i| Ok((i.module, i.field, entity_type(i.ty, environ)?)))
|
||||||
let sig =
|
.collect::<WasmResult<Vec<_>>>()?;
|
||||||
Signature::new(ModuleEnvironment::target_config(environ).default_call_conv);
|
let exports = t
|
||||||
environ.declare_signature(
|
.exports
|
||||||
crate::environ::WasmFuncType {
|
.iter()
|
||||||
params: Box::new([]),
|
.map(|e| Ok((e.name, entity_type(e.ty, environ)?)))
|
||||||
returns: Box::new([]),
|
.collect::<WasmResult<Vec<_>>>()?;
|
||||||
},
|
environ.declare_type_module(&imports, &exports)?;
|
||||||
sig,
|
}
|
||||||
)?;
|
TypeDef::Instance(t) => {
|
||||||
module_translation_state
|
let exports = t
|
||||||
.wasm_types
|
.exports
|
||||||
.push((Box::new([]), Box::new([])));
|
.iter()
|
||||||
|
.map(|e| Ok((e.name, entity_type(e.ty, environ)?)))
|
||||||
|
.collect::<WasmResult<Vec<_>>>()?;
|
||||||
|
environ.declare_type_instance(&exports)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,61 +150,24 @@ pub fn parse_import_section<'data>(
|
|||||||
let import = entry?;
|
let import = entry?;
|
||||||
let module_name = import.module;
|
let module_name = import.module;
|
||||||
let field_name = import.field.unwrap(); // TODO Handle error when module linking is implemented.
|
let field_name = import.field.unwrap(); // TODO Handle error when module linking is implemented.
|
||||||
|
match entity_type(import.ty, environ)? {
|
||||||
match import.ty {
|
EntityType::Function(idx) => {
|
||||||
ImportSectionEntryType::Function(sig) => {
|
environ.declare_func_import(idx, module_name, field_name)?;
|
||||||
environ.declare_func_import(
|
|
||||||
SignatureIndex::from_u32(sig),
|
|
||||||
module_name,
|
|
||||||
field_name,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
ImportSectionEntryType::Module(_sig) | ImportSectionEntryType::Instance(_sig) => {
|
EntityType::Module(idx) => {
|
||||||
unimplemented!("module linking not implemented yet")
|
environ.declare_module_import(idx, module_name, field_name)?;
|
||||||
}
|
}
|
||||||
ImportSectionEntryType::Memory(MemoryType::M32 {
|
EntityType::Instance(idx) => {
|
||||||
limits: ref memlimits,
|
environ.declare_instance_import(idx, module_name, field_name)?;
|
||||||
shared,
|
|
||||||
}) => {
|
|
||||||
environ.declare_memory_import(
|
|
||||||
Memory {
|
|
||||||
minimum: memlimits.initial,
|
|
||||||
maximum: memlimits.maximum,
|
|
||||||
shared,
|
|
||||||
},
|
|
||||||
module_name,
|
|
||||||
field_name,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
ImportSectionEntryType::Memory(MemoryType::M64 { .. }) => {
|
EntityType::Memory(ty) => {
|
||||||
unimplemented!();
|
environ.declare_memory_import(ty, module_name, field_name)?;
|
||||||
}
|
}
|
||||||
ImportSectionEntryType::Global(ref ty) => {
|
EntityType::Global(ty) => {
|
||||||
environ.declare_global_import(
|
environ.declare_global_import(ty, module_name, field_name)?;
|
||||||
Global {
|
|
||||||
wasm_ty: ty.content_type.try_into()?,
|
|
||||||
ty: type_to_type(ty.content_type, environ).unwrap(),
|
|
||||||
mutability: ty.mutable,
|
|
||||||
initializer: GlobalInit::Import,
|
|
||||||
},
|
|
||||||
module_name,
|
|
||||||
field_name,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
ImportSectionEntryType::Table(ref tab) => {
|
EntityType::Table(ty) => {
|
||||||
environ.declare_table_import(
|
environ.declare_table_import(ty, module_name, field_name)?;
|
||||||
Table {
|
|
||||||
wasm_ty: tab.element_type.try_into()?,
|
|
||||||
ty: match tabletype_to_type(tab.element_type, environ)? {
|
|
||||||
Some(t) => TableElementType::Val(t),
|
|
||||||
None => TableElementType::Func,
|
|
||||||
},
|
|
||||||
minimum: tab.limits.initial,
|
|
||||||
maximum: tab.limits.maximum,
|
|
||||||
},
|
|
||||||
module_name,
|
|
||||||
field_name,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,7 +191,7 @@ pub fn parse_function_section(
|
|||||||
|
|
||||||
for entry in functions {
|
for entry in functions {
|
||||||
let sigindex = entry?;
|
let sigindex = entry?;
|
||||||
environ.declare_func_type(SignatureIndex::from_u32(sigindex))?;
|
environ.declare_func_type(TypeIndex::from_u32(sigindex))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -186,16 +205,8 @@ pub fn parse_table_section(
|
|||||||
environ.reserve_tables(tables.get_count())?;
|
environ.reserve_tables(tables.get_count())?;
|
||||||
|
|
||||||
for entry in tables {
|
for entry in tables {
|
||||||
let table = entry?;
|
let ty = table(entry?, environ)?;
|
||||||
environ.declare_table(Table {
|
environ.declare_table(ty)?;
|
||||||
wasm_ty: table.element_type.try_into()?,
|
|
||||||
ty: match tabletype_to_type(table.element_type, environ)? {
|
|
||||||
Some(t) => TableElementType::Val(t),
|
|
||||||
None => TableElementType::Func,
|
|
||||||
},
|
|
||||||
minimum: table.limits.initial,
|
|
||||||
maximum: table.limits.maximum,
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -209,17 +220,8 @@ pub fn parse_memory_section(
|
|||||||
environ.reserve_memories(memories.get_count())?;
|
environ.reserve_memories(memories.get_count())?;
|
||||||
|
|
||||||
for entry in memories {
|
for entry in memories {
|
||||||
let memory = entry?;
|
let memory = memory(entry?);
|
||||||
match memory {
|
environ.declare_memory(memory)?;
|
||||||
MemoryType::M32 { limits, shared } => {
|
|
||||||
environ.declare_memory(Memory {
|
|
||||||
minimum: limits.initial,
|
|
||||||
maximum: limits.maximum,
|
|
||||||
shared: shared,
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
MemoryType::M64 { .. } => unimplemented!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -233,13 +235,7 @@ pub fn parse_global_section(
|
|||||||
environ.reserve_globals(globals.get_count())?;
|
environ.reserve_globals(globals.get_count())?;
|
||||||
|
|
||||||
for entry in globals {
|
for entry in globals {
|
||||||
let wasmparser::Global {
|
let wasmparser::Global { ty, init_expr } = entry?;
|
||||||
ty: GlobalType {
|
|
||||||
content_type,
|
|
||||||
mutable,
|
|
||||||
},
|
|
||||||
init_expr,
|
|
||||||
} = entry?;
|
|
||||||
let mut init_expr_reader = init_expr.get_binary_reader();
|
let mut init_expr_reader = init_expr.get_binary_reader();
|
||||||
let initializer = match init_expr_reader.read_operator()? {
|
let initializer = match init_expr_reader.read_operator()? {
|
||||||
Operator::I32Const { value } => GlobalInit::I32Const(value),
|
Operator::I32Const { value } => GlobalInit::I32Const(value),
|
||||||
@@ -263,13 +259,8 @@ pub fn parse_global_section(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let global = Global {
|
let ty = global(ty, environ, initializer)?;
|
||||||
wasm_ty: content_type.try_into()?,
|
environ.declare_global(ty)?;
|
||||||
ty: type_to_type(content_type, environ).unwrap(),
|
|
||||||
mutability: mutable,
|
|
||||||
initializer,
|
|
||||||
};
|
|
||||||
environ.declare_global(global)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
//! value and control stacks during the translation of a single function.
|
//! value and control stacks during the translation of a single function.
|
||||||
|
|
||||||
use crate::environ::{FuncEnvironment, GlobalVariable, WasmResult};
|
use crate::environ::{FuncEnvironment, GlobalVariable, WasmResult};
|
||||||
use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex};
|
use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex, TypeIndex};
|
||||||
use crate::{HashMap, Occupied, Vacant};
|
use crate::{HashMap, Occupied, Vacant};
|
||||||
use cranelift_codegen::ir::{self, Block, Inst, Value};
|
use cranelift_codegen::ir::{self, Block, Inst, Value};
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
@@ -236,7 +236,7 @@ pub struct FuncTranslationState {
|
|||||||
// Map of indirect call signatures that have been created by
|
// Map of indirect call signatures that have been created by
|
||||||
// `FuncEnvironment::make_indirect_sig()`.
|
// `FuncEnvironment::make_indirect_sig()`.
|
||||||
// Stores both the signature reference and the number of WebAssembly arguments
|
// Stores both the signature reference and the number of WebAssembly arguments
|
||||||
signatures: HashMap<SignatureIndex, (ir::SigRef, usize)>,
|
signatures: HashMap<TypeIndex, (ir::SigRef, usize)>,
|
||||||
|
|
||||||
// Imported and local functions that have been created by
|
// Imported and local functions that have been created by
|
||||||
// `FuncEnvironment::make_direct_func()`.
|
// `FuncEnvironment::make_direct_func()`.
|
||||||
@@ -498,7 +498,7 @@ impl FuncTranslationState {
|
|||||||
index: u32,
|
index: u32,
|
||||||
environ: &mut FE,
|
environ: &mut FE,
|
||||||
) -> WasmResult<(ir::SigRef, usize)> {
|
) -> WasmResult<(ir::SigRef, usize)> {
|
||||||
let index = SignatureIndex::from_u32(index);
|
let index = TypeIndex::from_u32(index);
|
||||||
match self.signatures.entry(index) {
|
match self.signatures.entry(index) {
|
||||||
Occupied(entry) => Ok(*entry.get()),
|
Occupied(entry) => Ok(*entry.get()),
|
||||||
Vacant(entry) => {
|
Vacant(entry) => {
|
||||||
|
|||||||
@@ -73,6 +73,65 @@ entity_impl!(DataIndex);
|
|||||||
pub struct ElemIndex(u32);
|
pub struct ElemIndex(u32);
|
||||||
entity_impl!(ElemIndex);
|
entity_impl!(ElemIndex);
|
||||||
|
|
||||||
|
/// Index type of a type inside the WebAssembly module.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct TypeIndex(u32);
|
||||||
|
entity_impl!(TypeIndex);
|
||||||
|
|
||||||
|
/// Index type of a module inside the WebAssembly module.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct ModuleIndex(u32);
|
||||||
|
entity_impl!(ModuleIndex);
|
||||||
|
|
||||||
|
/// Index type of an instance inside the WebAssembly module.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct InstanceIndex(u32);
|
||||||
|
entity_impl!(InstanceIndex);
|
||||||
|
|
||||||
|
/// An index of an entity.
|
||||||
|
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
pub enum EntityIndex {
|
||||||
|
/// Function index.
|
||||||
|
Function(FuncIndex),
|
||||||
|
/// Table index.
|
||||||
|
Table(TableIndex),
|
||||||
|
/// Memory index.
|
||||||
|
Memory(MemoryIndex),
|
||||||
|
/// Global index.
|
||||||
|
Global(GlobalIndex),
|
||||||
|
/// Module index.
|
||||||
|
Module(ModuleIndex),
|
||||||
|
/// Instance index.
|
||||||
|
Instance(InstanceIndex),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A type of an item in a wasm module where an item is typically something that
|
||||||
|
/// can be exported.
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
pub enum EntityType {
|
||||||
|
/// A global variable with the specified content type
|
||||||
|
Global(Global),
|
||||||
|
/// A linear memory with the specified limits
|
||||||
|
Memory(Memory),
|
||||||
|
/// A table with the specified element type and limits
|
||||||
|
Table(Table),
|
||||||
|
/// A function type where the index points to the type section and records a
|
||||||
|
/// function signature.
|
||||||
|
Function(TypeIndex),
|
||||||
|
/// An instance where the index points to the type section and records a
|
||||||
|
/// instance's exports.
|
||||||
|
Instance(TypeIndex),
|
||||||
|
/// A module where the index points to the type section and records a
|
||||||
|
/// module's imports and exports.
|
||||||
|
Module(TypeIndex),
|
||||||
|
}
|
||||||
|
|
||||||
/// A WebAssembly global.
|
/// A WebAssembly global.
|
||||||
///
|
///
|
||||||
/// Note that we record both the original Wasm type and the Cranelift IR type
|
/// Note that we record both the original Wasm type and the Cranelift IR type
|
||||||
|
|||||||
@@ -23,14 +23,18 @@ mod r#extern;
|
|||||||
mod func;
|
mod func;
|
||||||
mod global;
|
mod global;
|
||||||
mod import;
|
mod import;
|
||||||
|
mod instance;
|
||||||
mod memory;
|
mod memory;
|
||||||
|
mod module;
|
||||||
mod table;
|
mod table;
|
||||||
mod val;
|
mod val;
|
||||||
pub use self::export::*;
|
pub use self::export::*;
|
||||||
pub use self::func::*;
|
pub use self::func::*;
|
||||||
pub use self::global::*;
|
pub use self::global::*;
|
||||||
pub use self::import::*;
|
pub use self::import::*;
|
||||||
|
pub use self::instance::*;
|
||||||
pub use self::memory::*;
|
pub use self::memory::*;
|
||||||
|
pub use self::module::*;
|
||||||
pub use self::r#extern::*;
|
pub use self::r#extern::*;
|
||||||
pub use self::table::*;
|
pub use self::table::*;
|
||||||
pub use self::val::*;
|
pub use self::val::*;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::{wasm_functype_t, wasm_globaltype_t, wasm_memorytype_t, wasm_tabletype_t};
|
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;
|
use wasmtime::ExternType;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@@ -16,6 +17,8 @@ pub(crate) enum CExternType {
|
|||||||
Global(CGlobalType),
|
Global(CGlobalType),
|
||||||
Memory(CMemoryType),
|
Memory(CMemoryType),
|
||||||
Table(CTableType),
|
Table(CTableType),
|
||||||
|
Instance(CInstanceType),
|
||||||
|
Module(CModuleType),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type wasm_externkind_t = u8;
|
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_GLOBAL: wasm_externkind_t = 1;
|
||||||
pub const WASM_EXTERN_TABLE: wasm_externkind_t = 2;
|
pub const WASM_EXTERN_TABLE: wasm_externkind_t = 2;
|
||||||
pub const WASM_EXTERN_MEMORY: wasm_externkind_t = 3;
|
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 {
|
impl wasm_externtype_t {
|
||||||
pub(crate) fn new(ty: ExternType) -> 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::Global(f) => CExternType::Global(CGlobalType::new(f)),
|
||||||
ExternType::Memory(f) => CExternType::Memory(CMemoryType::new(f)),
|
ExternType::Memory(f) => CExternType::Memory(CMemoryType::new(f)),
|
||||||
ExternType::Table(f) => CExternType::Table(CTableType::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::Table(f) => ExternType::Table(f.ty.clone()),
|
||||||
CExternType::Global(f) => ExternType::Global(f.ty.clone()),
|
CExternType::Global(f) => ExternType::Global(f.ty.clone()),
|
||||||
CExternType::Memory(f) => ExternType::Memory(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::Table(_) => WASM_EXTERN_TABLE,
|
||||||
CExternType::Global(_) => WASM_EXTERN_GLOBAL,
|
CExternType::Global(_) => WASM_EXTERN_GLOBAL,
|
||||||
CExternType::Memory(_) => WASM_EXTERN_MEMORY,
|
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> {
|
) -> Option<&wasm_memorytype_t> {
|
||||||
wasm_memorytype_t::try_from(et)
|
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)
|
||||||
|
}
|
||||||
|
|||||||
46
crates/c-api/src/types/instance.rs
Normal file
46
crates/c-api/src/types/instance.rs
Normal 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
|
||||||
|
}
|
||||||
47
crates/c-api/src/types/module.rs
Normal file
47
crates/c-api/src/types/module.rs
Normal 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
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ use cranelift_entity::{EntityRef, PrimaryMap};
|
|||||||
use cranelift_frontend::FunctionBuilder;
|
use cranelift_frontend::FunctionBuilder;
|
||||||
use cranelift_wasm::{
|
use cranelift_wasm::{
|
||||||
self, FuncIndex, GlobalIndex, GlobalVariable, MemoryIndex, SignatureIndex, TableIndex,
|
self, FuncIndex, GlobalIndex, GlobalVariable, MemoryIndex, SignatureIndex, TableIndex,
|
||||||
TargetEnvironment, WasmError, WasmResult, WasmType,
|
TargetEnvironment, TypeIndex, WasmError, WasmResult, WasmType,
|
||||||
};
|
};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use wasmtime_environ::{
|
use wasmtime_environ::{
|
||||||
@@ -996,8 +996,9 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
|||||||
fn make_indirect_sig(
|
fn make_indirect_sig(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &mut ir::Function,
|
func: &mut ir::Function,
|
||||||
index: SignatureIndex,
|
index: TypeIndex,
|
||||||
) -> WasmResult<ir::SigRef> {
|
) -> WasmResult<ir::SigRef> {
|
||||||
|
let index = self.module.types[index].unwrap_function();
|
||||||
Ok(func.import_signature(self.native_signatures[index].clone()))
|
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<'_>,
|
mut pos: FuncCursor<'_>,
|
||||||
table_index: TableIndex,
|
table_index: TableIndex,
|
||||||
table: ir::Table,
|
table: ir::Table,
|
||||||
sig_index: SignatureIndex,
|
ty_index: TypeIndex,
|
||||||
sig_ref: ir::SigRef,
|
sig_ref: ir::SigRef,
|
||||||
callee: ir::Value,
|
callee: ir::Value,
|
||||||
call_args: &[ir::Value],
|
call_args: &[ir::Value],
|
||||||
) -> WasmResult<ir::Inst> {
|
) -> WasmResult<ir::Inst> {
|
||||||
|
let sig_index = self.module.types[ty_index].unwrap_function();
|
||||||
let pointer_type = self.pointer_type();
|
let pointer_type = self.pointer_type();
|
||||||
|
|
||||||
let table_entry_addr = pos.ins().table_addr(pointer_type, table, callee, 0);
|
let table_entry_addr = pos.ins().table_addr(pointer_type, table, callee, 0);
|
||||||
|
|||||||
@@ -24,9 +24,5 @@ pub mod entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod wasm {
|
pub mod wasm {
|
||||||
pub use cranelift_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,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,7 @@ pub use crate::address_map::*;
|
|||||||
pub use crate::builtin::*;
|
pub use crate::builtin::*;
|
||||||
pub use crate::compilation::*;
|
pub use crate::compilation::*;
|
||||||
pub use crate::data_structures::*;
|
pub use crate::data_structures::*;
|
||||||
// pub use crate::func_environ::BuiltinFunctionIndex;
|
pub use crate::module::*;
|
||||||
pub use crate::module::{
|
|
||||||
EntityIndex, MemoryPlan, MemoryStyle, Module, TableElements, TablePlan, TableStyle,
|
|
||||||
};
|
|
||||||
pub use crate::module_environ::*;
|
pub use crate::module_environ::*;
|
||||||
pub use crate::tunables::Tunables;
|
pub use crate::tunables::Tunables;
|
||||||
pub use crate::vmoffsets::{TargetSharedSignatureIndex, VMOffsets, INTERRUPTED};
|
pub use crate::vmoffsets::{TargetSharedSignatureIndex, VMOffsets, INTERRUPTED};
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use crate::WASM_MAX_PAGES;
|
|||||||
use cranelift_entity::{EntityRef, PrimaryMap};
|
use cranelift_entity::{EntityRef, PrimaryMap};
|
||||||
use cranelift_wasm::{
|
use cranelift_wasm::{
|
||||||
DataIndex, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex,
|
DataIndex, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex,
|
||||||
ElemIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table,
|
ElemIndex, EntityIndex, EntityType, FuncIndex, Global, GlobalIndex, InstanceIndex, Memory,
|
||||||
TableIndex, WasmFuncType,
|
MemoryIndex, ModuleIndex, SignatureIndex, Table, TableIndex, TypeIndex, WasmFuncType,
|
||||||
};
|
};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use more_asserts::assert_ge;
|
use more_asserts::assert_ge;
|
||||||
@@ -30,19 +30,6 @@ pub struct TableElements {
|
|||||||
pub elements: Box<[FuncIndex]>,
|
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.
|
/// Implemenation styles for WebAssembly linear memory.
|
||||||
#[derive(Debug, Clone, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Hash, Serialize, Deserialize)]
|
||||||
pub enum MemoryStyle {
|
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
|
/// A translated WebAssembly module, excluding the function bodies and
|
||||||
/// memory initializers.
|
/// memory initializers.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@@ -170,6 +187,9 @@ pub struct Module {
|
|||||||
/// Unprocessed signatures exactly as provided by `declare_signature()`.
|
/// Unprocessed signatures exactly as provided by `declare_signature()`.
|
||||||
pub signatures: PrimaryMap<SignatureIndex, WasmFuncType>,
|
pub signatures: PrimaryMap<SignatureIndex, WasmFuncType>,
|
||||||
|
|
||||||
|
/// Types declared in the wasm module.
|
||||||
|
pub types: PrimaryMap<TypeIndex, ModuleType>,
|
||||||
|
|
||||||
/// Number of imported functions in the module.
|
/// Number of imported functions in the module.
|
||||||
pub num_imported_funcs: usize,
|
pub num_imported_funcs: usize,
|
||||||
|
|
||||||
@@ -193,6 +213,27 @@ pub struct Module {
|
|||||||
|
|
||||||
/// WebAssembly global variables.
|
/// WebAssembly global variables.
|
||||||
pub globals: PrimaryMap<GlobalIndex, Global>,
|
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 {
|
impl Module {
|
||||||
@@ -217,6 +258,9 @@ impl Module {
|
|||||||
table_plans: PrimaryMap::new(),
|
table_plans: PrimaryMap::new(),
|
||||||
memory_plans: PrimaryMap::new(),
|
memory_plans: PrimaryMap::new(),
|
||||||
globals: 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 crate::tunables::Tunables;
|
||||||
use cranelift_codegen::ir;
|
use cranelift_codegen::ir;
|
||||||
use cranelift_codegen::ir::{AbiParam, ArgumentPurpose};
|
use cranelift_codegen::ir::{AbiParam, ArgumentPurpose};
|
||||||
use cranelift_codegen::isa::TargetFrontendConfig;
|
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||||
use cranelift_entity::PrimaryMap;
|
use cranelift_entity::PrimaryMap;
|
||||||
use cranelift_wasm::{
|
use cranelift_wasm::{
|
||||||
self, translate_module, DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex,
|
self, translate_module, DataIndex, DefinedFuncIndex, ElemIndex, EntityIndex, EntityType,
|
||||||
Memory, MemoryIndex, SignatureIndex, Table, TableIndex, TargetEnvironment, WasmError,
|
FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex,
|
||||||
WasmFuncType, WasmResult,
|
TargetEnvironment, TypeIndex, WasmError, WasmFuncType, WasmResult,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
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
|
/// 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.
|
/// environment-dependent wasm instructions. These functions should not be called by the user.
|
||||||
impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data> {
|
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();
|
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);
|
self.result.native_signatures.reserve_exact(num);
|
||||||
Ok(())
|
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());
|
let sig = translate_signature(sig, self.pointer_type());
|
||||||
// TODO: Deduplicate signatures.
|
// TODO: Deduplicate signatures.
|
||||||
self.result.module.signatures.push(wasm);
|
|
||||||
self.result.native_signatures.push(sig);
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +262,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
|
|
||||||
fn declare_func_import(
|
fn declare_func_import(
|
||||||
&mut self,
|
&mut self,
|
||||||
sig_index: SignatureIndex,
|
index: TypeIndex,
|
||||||
module: &str,
|
module: &str,
|
||||||
field: &str,
|
field: &str,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
@@ -235,6 +271,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
self.result.module.num_imported_funcs,
|
self.result.module.num_imported_funcs,
|
||||||
"Imported functions must be declared first"
|
"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);
|
let func_index = self.result.module.functions.push(sig_index);
|
||||||
self.result.module.imports.push((
|
self.result.module.imports.push((
|
||||||
module.to_owned(),
|
module.to_owned(),
|
||||||
@@ -320,7 +357,8 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
Ok(())
|
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);
|
self.result.module.functions.push(sig_index);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ pub fn dummy_imports<'module>(
|
|||||||
ExternType::Global(global_ty) => Extern::Global(dummy_global(&store, global_ty)?),
|
ExternType::Global(global_ty) => Extern::Global(dummy_global(&store, global_ty)?),
|
||||||
ExternType::Table(table_ty) => Extern::Table(dummy_table(&store, table_ty)?),
|
ExternType::Table(table_ty) => Extern::Table(dummy_table(&store, table_ty)?),
|
||||||
ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(&store, mem_ty)),
|
ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(&store, mem_ty)),
|
||||||
|
|
||||||
|
// FIXME(#2094)
|
||||||
|
ExternType::Instance(_) => unimplemented!(),
|
||||||
|
ExternType::Module(_) => unimplemented!(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ use thiserror::Error;
|
|||||||
use wasmtime_environ::entity::{packed_option::ReservedValue, BoxedSlice, EntityRef, PrimaryMap};
|
use wasmtime_environ::entity::{packed_option::ReservedValue, BoxedSlice, EntityRef, PrimaryMap};
|
||||||
use wasmtime_environ::wasm::{
|
use wasmtime_environ::wasm::{
|
||||||
DataIndex, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex,
|
DataIndex, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex,
|
||||||
ElemIndex, FuncIndex, GlobalIndex, GlobalInit, MemoryIndex, SignatureIndex, TableElementType,
|
ElemIndex, EntityIndex, FuncIndex, GlobalIndex, GlobalInit, MemoryIndex, SignatureIndex,
|
||||||
TableIndex, WasmType,
|
TableElementType, TableIndex, WasmType,
|
||||||
};
|
};
|
||||||
use wasmtime_environ::{ir, DataInitializer, EntityIndex, Module, TableElements, VMOffsets};
|
use wasmtime_environ::{ir, DataInitializer, Module, TableElements, VMOffsets};
|
||||||
|
|
||||||
/// A WebAssembly instance.
|
/// A WebAssembly instance.
|
||||||
///
|
///
|
||||||
@@ -325,6 +325,10 @@ impl Instance {
|
|||||||
global: self.module.globals[*index],
|
global: self.module.globals[*index],
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
|
||||||
|
// FIXME(#2094)
|
||||||
|
EntityIndex::Instance(_index) => unimplemented!(),
|
||||||
|
EntityIndex::Module(_index) => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::{Engine, Export, Extern, Func, Global, Memory, Module, Store, Table,
|
|||||||
use anyhow::{anyhow, bail, Context, Error, Result};
|
use anyhow::{anyhow, bail, Context, Error, Result};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use wasmtime_environ::EntityIndex;
|
use wasmtime_environ::wasm::EntityIndex;
|
||||||
use wasmtime_jit::CompiledModule;
|
use wasmtime_jit::CompiledModule;
|
||||||
use wasmtime_runtime::{
|
use wasmtime_runtime::{
|
||||||
Imports, InstantiationError, StackMapRegistry, VMContext, VMExternRefActivationsTable,
|
Imports, InstantiationError, StackMapRegistry, VMContext, VMExternRefActivationsTable,
|
||||||
@@ -300,6 +300,10 @@ fn with_imports<R>(
|
|||||||
}
|
}
|
||||||
functions.push(func.vmimport());
|
functions.push(func.vmimport());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(#2094)
|
||||||
|
EntityIndex::Module(_i) => unimplemented!(),
|
||||||
|
EntityIndex::Instance(_i) => unimplemented!(),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -516,6 +516,10 @@ impl Linker {
|
|||||||
ExternType::Global(f) => ImportKind::Global(f),
|
ExternType::Global(f) => ImportKind::Global(f),
|
||||||
ExternType::Memory(_) => ImportKind::Memory,
|
ExternType::Memory(_) => ImportKind::Memory,
|
||||||
ExternType::Table(_) => ImportKind::Table,
|
ExternType::Table(_) => ImportKind::Table,
|
||||||
|
|
||||||
|
// FIXME(#2094)
|
||||||
|
ExternType::Module(_) => unimplemented!(),
|
||||||
|
ExternType::Instance(_) => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,12 @@ impl Config {
|
|||||||
profiler: Arc::new(NullProfilerAgent),
|
profiler: Arc::new(NullProfilerAgent),
|
||||||
memory_creator: None,
|
memory_creator: None,
|
||||||
max_wasm_stack: 1 << 20,
|
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_bulk_memory", &self.features.bulk_memory)
|
||||||
.field("wasm_simd", &self.features.simd)
|
.field("wasm_simd", &self.features.simd)
|
||||||
.field("wasm_multi_value", &self.features.multi_value)
|
.field("wasm_multi_value", &self.features.multi_value)
|
||||||
|
.field("wasm_module_linking", &self.features.module_linking)
|
||||||
.field(
|
.field(
|
||||||
"flags",
|
"flags",
|
||||||
&settings::Flags::new(self.flags.clone()).to_string(),
|
&settings::Flags::new(self.flags.clone()).to_string(),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use std::mem;
|
|||||||
use std::panic::{self, AssertUnwindSafe};
|
use std::panic::{self, AssertUnwindSafe};
|
||||||
use wasmtime_environ::entity::PrimaryMap;
|
use wasmtime_environ::entity::PrimaryMap;
|
||||||
use wasmtime_environ::isa::TargetIsa;
|
use wasmtime_environ::isa::TargetIsa;
|
||||||
use wasmtime_environ::{ir, CompiledFunction, EntityIndex, Module};
|
use wasmtime_environ::{ir, wasm, CompiledFunction, Module};
|
||||||
use wasmtime_jit::trampoline::ir::{
|
use wasmtime_jit::trampoline::ir::{
|
||||||
ExternalName, Function, InstBuilder, MemFlags, StackSlotData, StackSlotKind,
|
ExternalName, Function, InstBuilder, MemFlags, StackSlotData, StackSlotKind,
|
||||||
};
|
};
|
||||||
@@ -227,7 +227,7 @@ pub fn create_handle_with_function(
|
|||||||
let func_id = module.functions.push(sig_id);
|
let func_id = module.functions.push(sig_id);
|
||||||
module
|
module
|
||||||
.exports
|
.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);
|
let trampoline = make_trampoline(isa.as_ref(), &mut code_memory, &mut fn_builder_ctx, &sig);
|
||||||
finished_functions.push(trampoline);
|
finished_functions.push(trampoline);
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@ pub unsafe fn create_handle_with_raw_function(
|
|||||||
let func_id = module.functions.push(sig_id);
|
let func_id = module.functions.push(sig_id);
|
||||||
module
|
module
|
||||||
.exports
|
.exports
|
||||||
.insert(String::new(), EntityIndex::Function(func_id));
|
.insert(String::new(), wasm::EntityIndex::Function(func_id));
|
||||||
finished_functions.push(func);
|
finished_functions.push(func);
|
||||||
store.signatures().borrow_mut().register(wft, trampoline);
|
store.signatures().borrow_mut().register(wft, trampoline);
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::trampoline::StoreInstanceHandle;
|
|||||||
use crate::{GlobalType, Mutability, Store, Val};
|
use crate::{GlobalType, Mutability, Store, Val};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use wasmtime_environ::entity::PrimaryMap;
|
use wasmtime_environ::entity::PrimaryMap;
|
||||||
use wasmtime_environ::{wasm, EntityIndex, Module};
|
use wasmtime_environ::{wasm, Module};
|
||||||
use wasmtime_runtime::VMFunctionImport;
|
use wasmtime_runtime::VMFunctionImport;
|
||||||
|
|
||||||
pub fn create_global(store: &Store, gt: &GlobalType, val: Val) -> Result<StoreInstanceHandle> {
|
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 local_sig_index = module.signatures.push(wasm.clone());
|
||||||
let func_index = module.functions.push(local_sig_index);
|
let func_index = module.functions.push(local_sig_index);
|
||||||
module.num_imported_funcs = 1;
|
module.num_imported_funcs = 1;
|
||||||
module
|
module.imports.push((
|
||||||
.imports
|
"".into(),
|
||||||
.push(("".into(), "".into(), EntityIndex::Function(func_index)));
|
"".into(),
|
||||||
|
wasm::EntityIndex::Function(func_index),
|
||||||
|
));
|
||||||
|
|
||||||
let f = f.caller_checked_anyfunc();
|
let f = f.caller_checked_anyfunc();
|
||||||
let f = unsafe { f.as_ref() };
|
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);
|
let global_id = module.globals.push(global);
|
||||||
module
|
module
|
||||||
.exports
|
.exports
|
||||||
.insert(String::new(), EntityIndex::Global(global_id));
|
.insert(String::new(), wasm::EntityIndex::Global(global_id));
|
||||||
let handle = create_handle(
|
let handle = create_handle(
|
||||||
module,
|
module,
|
||||||
store,
|
store,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::Store;
|
|||||||
use crate::{Limits, MemoryType};
|
use crate::{Limits, MemoryType};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use wasmtime_environ::entity::PrimaryMap;
|
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 wasmtime_runtime::{RuntimeLinearMemory, RuntimeMemoryCreator, VMMemoryDefinition};
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -27,7 +27,7 @@ pub fn create_handle_with_memory(
|
|||||||
let memory_id = module.memory_plans.push(memory_plan);
|
let memory_id = module.memory_plans.push(memory_plan);
|
||||||
module
|
module
|
||||||
.exports
|
.exports
|
||||||
.insert(String::new(), EntityIndex::Memory(memory_id));
|
.insert(String::new(), wasm::EntityIndex::Memory(memory_id));
|
||||||
|
|
||||||
create_handle(module, store, PrimaryMap::new(), Box::new(()), &[])
|
create_handle(module, store, PrimaryMap::new(), Box::new(()), &[])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::Store;
|
|||||||
use crate::{TableType, ValType};
|
use crate::{TableType, ValType};
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use wasmtime_environ::entity::PrimaryMap;
|
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> {
|
pub fn create_handle_with_table(store: &Store, table: &TableType) -> Result<StoreInstanceHandle> {
|
||||||
let mut module = Module::new();
|
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);
|
let table_id = module.table_plans.push(table_plan);
|
||||||
module
|
module
|
||||||
.exports
|
.exports
|
||||||
.insert(String::new(), EntityIndex::Table(table_id));
|
.insert(String::new(), wasm::EntityIndex::Table(table_id));
|
||||||
|
|
||||||
create_handle(module, store, PrimaryMap::new(), Box::new(()), &[])
|
create_handle(module, store, PrimaryMap::new(), Box::new(()), &[])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use wasmtime_environ::wasm::WasmFuncType;
|
use wasmtime_environ::wasm::WasmFuncType;
|
||||||
use wasmtime_environ::{ir, wasm, EntityIndex};
|
use wasmtime_environ::{ir, wasm};
|
||||||
|
|
||||||
// Type Representations
|
// Type Representations
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ impl ValType {
|
|||||||
///
|
///
|
||||||
/// This list can be found in [`ImportType`] or [`ExportType`], so these types
|
/// This list can be found in [`ImportType`] or [`ExportType`], so these types
|
||||||
/// can either be imported or exported.
|
/// can either be imported or exported.
|
||||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ExternType {
|
pub enum ExternType {
|
||||||
/// This external type is the type of a WebAssembly function.
|
/// This external type is the type of a WebAssembly function.
|
||||||
Func(FuncType),
|
Func(FuncType),
|
||||||
@@ -154,6 +154,10 @@ pub enum ExternType {
|
|||||||
Table(TableType),
|
Table(TableType),
|
||||||
/// This external type is the type of a WebAssembly memory.
|
/// This external type is the type of a WebAssembly memory.
|
||||||
Memory(MemoryType),
|
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 {
|
macro_rules! accessors {
|
||||||
@@ -186,6 +190,39 @@ impl ExternType {
|
|||||||
(Global(GlobalType) global unwrap_global)
|
(Global(GlobalType) global unwrap_global)
|
||||||
(Table(TableType) table unwrap_table)
|
(Table(TableType) table unwrap_table)
|
||||||
(Memory(MemoryType) memory unwrap_memory)
|
(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.
|
/// A descriptor for a function in a WebAssembly module.
|
||||||
///
|
///
|
||||||
/// WebAssembly functions can have 0 or more parameters and results.
|
/// 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
|
// Entity Types
|
||||||
|
|
||||||
#[derive(Clone, Hash, Eq, PartialEq)]
|
#[derive(Clone)]
|
||||||
pub(crate) enum EntityType<'module> {
|
pub(crate) enum EntityType<'module> {
|
||||||
Function(&'module wasm::WasmFuncType),
|
Function(&'module wasm::WasmFuncType),
|
||||||
Table(&'module wasm::Table),
|
Table(&'module wasm::Table),
|
||||||
Memory(&'module wasm::Memory),
|
Memory(&'module wasm::Memory),
|
||||||
Global(&'module wasm::Global),
|
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> {
|
impl<'module> EntityType<'module> {
|
||||||
/// Translate from a `EntityIndex` into an `ExternType`.
|
/// Translate from a `EntityIndex` into an `ExternType`.
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
entity_index: &EntityIndex,
|
entity_index: &wasm::EntityIndex,
|
||||||
module: &'module wasmtime_environ::Module,
|
module: &'module wasmtime_environ::Module,
|
||||||
) -> EntityType<'module> {
|
) -> EntityType<'module> {
|
||||||
match entity_index {
|
match entity_index {
|
||||||
EntityIndex::Function(func_index) => {
|
wasm::EntityIndex::Function(func_index) => {
|
||||||
let sig = module.wasm_func_type(*func_index);
|
let sig = module.wasm_func_type(*func_index);
|
||||||
EntityType::Function(&sig)
|
EntityType::Function(&sig)
|
||||||
}
|
}
|
||||||
EntityIndex::Table(table_index) => {
|
wasm::EntityIndex::Table(table_index) => {
|
||||||
EntityType::Table(&module.table_plans[*table_index].table)
|
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)
|
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::Table(table) => TableType::from_wasmtime_table(table).into(),
|
||||||
EntityType::Memory(memory) => MemoryType::from_wasmtime_memory(memory).into(),
|
EntityType::Memory(memory) => MemoryType::from_wasmtime_memory(memory).into(),
|
||||||
EntityType::Global(global) => GlobalType::from_wasmtime_global(global).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`]
|
/// [`Module::imports`](crate::Module::imports) API. Each [`ImportType`]
|
||||||
/// describes an import into the wasm module with the module/name that it's
|
/// 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.
|
/// imported from as well as the type of item that's being imported.
|
||||||
#[derive(Clone, Hash, Eq, PartialEq)]
|
#[derive(Clone)]
|
||||||
pub struct ImportType<'module> {
|
pub struct ImportType<'module> {
|
||||||
/// The module of the import.
|
/// The module of the import.
|
||||||
module: &'module str,
|
module: &'module str,
|
||||||
@@ -456,7 +677,13 @@ pub struct ImportType<'module> {
|
|||||||
name: &'module str,
|
name: &'module str,
|
||||||
|
|
||||||
/// The type of the import.
|
/// 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> {
|
impl<'module> ImportType<'module> {
|
||||||
@@ -467,7 +694,11 @@ impl<'module> ImportType<'module> {
|
|||||||
name: &'module str,
|
name: &'module str,
|
||||||
ty: EntityType<'module>,
|
ty: EntityType<'module>,
|
||||||
) -> ImportType<'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.
|
/// 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.
|
/// Returns the expected type of this import.
|
||||||
pub fn ty(&self) -> ExternType {
|
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
|
/// [`Module::exports`](crate::Module::exports) accessor and describes what
|
||||||
/// names are exported from a wasm module and the type of the item that is
|
/// names are exported from a wasm module and the type of the item that is
|
||||||
/// exported.
|
/// exported.
|
||||||
#[derive(Clone, Hash, Eq, PartialEq)]
|
#[derive(Clone)]
|
||||||
pub struct ExportType<'module> {
|
pub struct ExportType<'module> {
|
||||||
/// The name of the export.
|
/// The name of the export.
|
||||||
name: &'module str,
|
name: &'module str,
|
||||||
|
|
||||||
/// The type of the export.
|
/// The type of the export.
|
||||||
ty: EntityType<'module>,
|
ty: EntityOrExtern<'module>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'module> ExportType<'module> {
|
impl<'module> ExportType<'module> {
|
||||||
/// Creates a new export which is exported with the given `name` and has the
|
/// Creates a new export which is exported with the given `name` and has the
|
||||||
/// given `ty`.
|
/// given `ty`.
|
||||||
pub(crate) fn new(name: &'module str, ty: EntityType<'module>) -> ExportType<'module> {
|
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.
|
/// Returns the name by which this export is known.
|
||||||
@@ -528,7 +765,10 @@ impl<'module> ExportType<'module> {
|
|||||||
|
|
||||||
/// Returns the type of this export.
|
/// Returns the type of this export.
|
||||||
pub fn ty(&self) -> ExternType {
|
pub fn ty(&self) -> ExternType {
|
||||||
self.ty.extern_type()
|
match &self.ty {
|
||||||
|
EntityOrExtern::Entity(e) => e.extern_type(),
|
||||||
|
EntityOrExtern::Extern(e) => (*e).clone(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,3 +44,11 @@ fn compile() -> Result<()> {
|
|||||||
assert_eq!(m.exports().len(), 0);
|
assert_eq!(m.exports().len(), 0);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn types() -> Result<()> {
|
||||||
|
let engine = engine();
|
||||||
|
Module::new(&engine, "(module (type (module)))")?;
|
||||||
|
Module::new(&engine, "(module (type (instance)))")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user