From 59307625c80fe5e0c023317273865dce4a563f38 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Fri, 5 Jun 2020 15:32:24 -0700 Subject: [PATCH] Allow ModuleTranslationState to be constructed with signatures. This is needed to allow SpiderMonkey to provide function signature types to the wasm translator when it uses Cranelift as a backend without using the wasm translator to parse the entire module. There is perhaps a better long-term design here where we allow an embedding that already parses the Wasm module (such as SpiderMonkey) to provide information in a more principled way, this suffices for now. Patch is inspired by Ben's patch in https://bugzilla.mozilla.org/show_bug.cgi?id=1641504, but does not expose `wasmparser` types directly, instead using Cranelift types across the API boundary. --- cranelift/wasm/src/state/module_state.rs | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/cranelift/wasm/src/state/module_state.rs b/cranelift/wasm/src/state/module_state.rs index e997305858..4f6ce35394 100644 --- a/cranelift/wasm/src/state/module_state.rs +++ b/cranelift/wasm/src/state/module_state.rs @@ -1,6 +1,9 @@ +use crate::environ::{WasmError, WasmResult}; use crate::translation_utils::SignatureIndex; +use cranelift_codegen::ir::{types, Type}; use cranelift_entity::PrimaryMap; use std::boxed::Box; +use std::vec::Vec; /// Map of signatures to a function's parameter and return types. pub(crate) type WasmTypes = @@ -21,6 +24,21 @@ pub struct ModuleTranslationState { pub(crate) wasm_types: WasmTypes, } +fn cranelift_to_wasmparser_type(ty: Type) -> WasmResult { + Ok(match ty { + types::I32 => wasmparser::Type::I32, + types::I64 => wasmparser::Type::I64, + types::F32 => wasmparser::Type::F32, + types::F64 => wasmparser::Type::F64, + _ => { + return Err(WasmError::Unsupported(format!( + "Cannot convert Cranelift type to Wasm signature: {:?}", + ty + ))); + } + }) +} + impl ModuleTranslationState { /// Creates a new empty ModuleTranslationState. pub fn new() -> Self { @@ -28,4 +46,24 @@ impl ModuleTranslationState { wasm_types: PrimaryMap::new(), } } + + /// Create a new ModuleTranslationState with the given function signatures, + /// provided in terms of Cranelift types. The provided slice of signatures + /// is indexed by signature number, and contains pairs of (args, results) + /// slices. + pub fn from_func_sigs(sigs: &[(&[Type], &[Type])]) -> WasmResult { + let mut wasm_types = PrimaryMap::with_capacity(sigs.len()); + for &(ref args, ref results) in sigs { + let args: Vec = args + .iter() + .map(|&ty| cranelift_to_wasmparser_type(ty)) + .collect::>()?; + let results: Vec = results + .iter() + .map(|&ty| cranelift_to_wasmparser_type(ty)) + .collect::>()?; + wasm_types.push((args.into_boxed_slice(), results.into_boxed_slice())); + } + Ok(Self { wasm_types }) + } }