cranelift_wasm: expose the original Wasm function signature

In the `ModuleEnvironment::declare_signature` callback, also pass the original
Wasm function signature, so that consumers may associate this information with
each compiled function. This is often necessary because while each Wasm
signature gets compiled down into a single native signature, multiple Wasm
signatures might compile down into the same native signature, and in these cases
the original Wasm signature is required for dynamic type checking of calls.
This commit is contained in:
Nick Fitzgerald
2020-05-22 15:00:52 -07:00
parent 38a92d89de
commit acf8ad0df7
6 changed files with 36 additions and 36 deletions

View File

@@ -6,7 +6,8 @@
//! [Wasmtime]: https://github.com/bytecodealliance/wasmtime
use crate::environ::{
FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment, WasmResult,
FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment,
WasmFuncType, WasmResult,
};
use crate::func_translator::FuncTranslator;
use crate::state::ModuleTranslationState;
@@ -534,7 +535,7 @@ impl TargetEnvironment for DummyEnvironment {
}
impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
fn declare_signature(&mut self, sig: ir::Signature) -> WasmResult<()> {
fn declare_signature(&mut self, _wasm: &WasmFuncType, sig: ir::Signature) -> WasmResult<()> {
self.info.signatures.push(sig);
Ok(())
}

View File

@@ -7,5 +7,5 @@ mod spec;
pub use crate::environ::dummy::DummyEnvironment;
pub use crate::environ::spec::{
FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment, WasmError,
WasmResult,
WasmFuncType, WasmResult, WasmType,
};

View File

@@ -22,6 +22,13 @@ use thiserror::Error;
use wasmparser::BinaryReaderError;
use wasmparser::Operator;
// Re-export `wasmparser`'s function and value types so that consumers can
// associate this the original Wasm signature with each compiled function. This
// is often necessary because while each Wasm signature gets compiled down into
// a single native signature, multiple Wasm signatures might compile down into
// the same native signature.
pub use wasmparser::{FuncType as WasmFuncType, Type as WasmType};
/// The value of a WebAssembly global variable.
#[derive(Clone, Copy)]
pub enum GlobalVariable {
@@ -472,7 +479,11 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
}
/// Declares a function signature to the environment.
fn declare_signature(&mut self, sig: ir::Signature) -> WasmResult<()>;
fn declare_signature(
&mut self,
wasm_func_type: &WasmFuncType,
sig: ir::Signature,
) -> WasmResult<()>;
/// Provides the number of imports up front. By default this does nothing, but
/// implementations can use this to preallocate memory if desired.

View File

@@ -59,7 +59,7 @@ mod translation_utils;
pub use crate::environ::{
DummyEnvironment, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode,
TargetEnvironment, WasmError, WasmResult,
TargetEnvironment, WasmError, WasmFuncType, WasmResult, WasmType,
};
pub use crate::func_translator::FuncTranslator;
pub use crate::module_translator::translate_module;

View File

@@ -23,7 +23,7 @@ use std::boxed::Box;
use std::vec::Vec;
use wasmparser::{
self, CodeSectionReader, Data, DataKind, DataSectionReader, Element, ElementItem, ElementItems,
ElementKind, ElementSectionReader, Export, ExportSectionReader, ExternalKind, FuncType,
ElementKind, ElementSectionReader, Export, ExportSectionReader, ExternalKind,
FunctionSectionReader, GlobalSectionReader, GlobalType, ImportSectionEntryType,
ImportSectionReader, MemorySectionReader, MemoryType, NameSectionReader, Naming, NamingReader,
Operator, TableSectionReader, Type, TypeSectionReader,
@@ -40,34 +40,22 @@ pub fn parse_type_section(
environ.reserve_signatures(count)?;
for entry in types {
match entry? {
FuncType {
form: wasmparser::Type::Func,
params,
returns,
} => {
let mut sig =
Signature::new(ModuleEnvironment::target_config(environ).default_call_conv);
sig.params.extend(params.iter().map(|ty| {
let wasm_func_ty = entry?;
let mut sig = Signature::new(ModuleEnvironment::target_config(environ).default_call_conv);
sig.params.extend(wasm_func_ty.params.iter().map(|ty| {
let cret_arg: ir::Type = type_to_type(*ty, environ)
.expect("only numeric types are supported in function signatures");
AbiParam::new(cret_arg)
}));
sig.returns.extend(returns.iter().map(|ty| {
sig.returns.extend(wasm_func_ty.returns.iter().map(|ty| {
let cret_arg: ir::Type = type_to_type(*ty, environ)
.expect("only numeric types are supported in function signatures");
AbiParam::new(cret_arg)
}));
environ.declare_signature(sig)?;
module_translation_state.wasm_types.push((params, returns));
}
ty => {
return Err(wasm_unsupported!(
"unsupported type in type section: {:?}",
ty
))
}
}
environ.declare_signature(&wasm_func_ty, sig)?;
module_translation_state
.wasm_types
.push((wasm_func_ty.params, wasm_func_ty.returns));
}
Ok(())
}

View File

@@ -7,7 +7,7 @@ use cranelift_entity::PrimaryMap;
use cranelift_wasm::{
self, translate_module, DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex,
Memory, MemoryIndex, ModuleTranslationState, SignatureIndex, Table, TableIndex,
TargetEnvironment, WasmError, WasmResult,
TargetEnvironment, WasmError, WasmFuncType, WasmResult,
};
use std::convert::TryFrom;
use std::sync::Arc;
@@ -106,7 +106,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
Ok(())
}
fn declare_signature(&mut self, sig: ir::Signature) -> WasmResult<()> {
fn declare_signature(&mut self, _wasm: &WasmFuncType, sig: ir::Signature) -> WasmResult<()> {
let sig = translate_signature(sig, self.pointer_type());
// TODO: Deduplicate signatures.
self.result.module.local.signatures.push(sig);