From ca53090f1bc2ce61fa440576168e259a80eff121 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 11 Oct 2019 12:37:17 -0700 Subject: [PATCH] cranelift-wasm: Create `ModuleTranslationState` and polish API a little (#1111) * cranelift-wasm: replace `WasmTypesMap` with `ModuleTranslationState` The `ModuleTranslationState` contains information decoded from the Wasm module that must be referenced during each Wasm function's translation. This is only for data that is maintained by `cranelift-wasm` itself, as opposed to being maintained by the embedder. Data that is maintained by the embedder is represented with `ModuleEnvironment`. A `ModuleTranslationState` is returned by `translate_module`, and can then be used when translating functions from that module. * cranelift-wasm: rename `TranslationState` to `FuncTranslationState` To disambiguate a bit with the new `ModuleTranslationState`. * cranelift-wasm: Reorganize the internal `state` module into submodules One module for the `ModuleTranslationState` and another for the `FuncTranslationState`. * cranelift-wasm: replace `FuncTranslator` with methods on `ModuleTranslationState` `FuncTranslator` was two methods that always took ownership of `self`, so it didn't really make sense as an object as opposed to two different functions, or in this case methods on the object that actually persists for a longer time. I think this improves ergonomics nicely. Before: ```rust let module_translation = translate_module(...)?; for body in func_bodies { let mut translator = FuncTranslator::new(); translator.translate(body, ...)?; } ``` After: ```rust let module_translation = translate_module(...)?; for body in func_bodies { module_translation.translate_func(body, ...)?; } ``` Note that this commit does not remove `FuncTranslator`. It still exists, but is just a wrapper over the `ModuleTranslationState` methods, and it is marked deprecated, so that downstream users get a heads up. This should make the transition easier. * Revert "cranelift-wasm: replace `FuncTranslator` with methods on `ModuleTranslationState`" This reverts commit 075f9ae933bcaae39348b61287c8f78a4009340d. --- cranelift/wasm/src/code_translator.rs | 38 ++++++++-------- cranelift/wasm/src/environ/dummy.rs | 9 ++-- cranelift/wasm/src/environ/mod.rs | 1 - cranelift/wasm/src/environ/spec.rs | 28 ++---------- cranelift/wasm/src/func_translator.rs | 43 +++++++++++-------- cranelift/wasm/src/lib.rs | 5 ++- cranelift/wasm/src/module_translator.rs | 13 +++--- cranelift/wasm/src/sections_translator.rs | 13 +++--- .../src/{state.rs => state/func_state.rs} | 21 +++++---- cranelift/wasm/src/state/mod.rs | 14 ++++++ cranelift/wasm/src/state/module_state.rs | 27 ++++++++++++ cranelift/wasm/src/translation_utils.rs | 7 +-- 12 files changed, 127 insertions(+), 92 deletions(-) rename cranelift/wasm/src/{state.rs => state/func_state.rs} (96%) create mode 100644 cranelift/wasm/src/state/mod.rs create mode 100644 cranelift/wasm/src/state/module_state.rs diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index a6aa6a32d1..bc75157a88 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -23,8 +23,8 @@ //! That is why `translate_function_body` takes an object having the `WasmRuntime` trait as //! argument. use super::{hash_map, HashMap}; -use crate::environ::{FuncEnvironment, GlobalVariable, ReturnMode, WasmResult, WasmTypesMap}; -use crate::state::{ControlStackFrame, ElseData, TranslationState}; +use crate::environ::{FuncEnvironment, GlobalVariable, ReturnMode, WasmResult}; +use crate::state::{ControlStackFrame, ElseData, FuncTranslationState, ModuleTranslationState}; use crate::translation_utils::{ blocktype_params_results, ebb_with_params, f32_translation, f64_translation, }; @@ -43,14 +43,14 @@ use wasmparser::{MemoryImmediate, Operator}; /// Translates wasm operators into Cranelift IR instructions. Returns `true` if it inserted /// a return. pub fn translate_operator( - wasm_types: &WasmTypesMap, + module_translation_state: &ModuleTranslationState, op: &Operator, builder: &mut FunctionBuilder, - state: &mut TranslationState, + state: &mut FuncTranslationState, environ: &mut FE, ) -> WasmResult<()> { if !state.reachable { - translate_unreachable_operator(wasm_types, &op, builder, state)?; + translate_unreachable_operator(module_translation_state, &op, builder, state)?; return Ok(()); } @@ -133,12 +133,12 @@ pub fn translate_operator( * possible `Ebb`'s arguments values. ***********************************************************************************/ Operator::Block { ty } => { - let (params, results) = blocktype_params_results(wasm_types, *ty)?; + let (params, results) = blocktype_params_results(module_translation_state, *ty)?; let next = ebb_with_params(builder, results)?; state.push_block(next, params.len(), results.len()); } Operator::Loop { ty } => { - let (params, results) = blocktype_params_results(wasm_types, *ty)?; + let (params, results) = blocktype_params_results(module_translation_state, *ty)?; let loop_body = ebb_with_params(builder, params)?; let next = ebb_with_params(builder, results)?; builder.ins().jump(loop_body, state.peekn(params.len())); @@ -155,7 +155,7 @@ pub fn translate_operator( Operator::If { ty } => { let val = state.pop1(); - let (params, results) = blocktype_params_results(wasm_types, *ty)?; + let (params, results) = blocktype_params_results(module_translation_state, *ty)?; let (destination, else_data) = if params == results { // It is possible there is no `else` block, so we will only // allocate an ebb for it if/when we find the `else`. For now, @@ -214,7 +214,8 @@ pub fn translate_operator( // The `if` has an `else`, so there's no branch to the end from the top. *reachable_from_top = false; - let (params, _results) = blocktype_params_results(wasm_types, blocktype)?; + let (params, _results) = + blocktype_params_results(module_translation_state, blocktype)?; let else_ebb = ebb_with_params(builder, params)?; builder.ins().jump(destination, state.peekn(params.len())); state.popn(params.len()); @@ -1206,10 +1207,10 @@ pub fn translate_operator( /// are dropped but special ones like `End` or `Else` signal the potential end of the unreachable /// portion so the translation state must be updated accordingly. fn translate_unreachable_operator( - wasm_types: &WasmTypesMap, + module_translation_state: &ModuleTranslationState, op: &Operator, builder: &mut FunctionBuilder, - state: &mut TranslationState, + state: &mut FuncTranslationState, ) -> WasmResult<()> { match *op { Operator::If { ty } => { @@ -1244,7 +1245,8 @@ fn translate_unreachable_operator( // branch from the top directly to the end. *reachable_from_top = false; - let (params, _results) = blocktype_params_results(wasm_types, blocktype)?; + let (params, _results) = + blocktype_params_results(module_translation_state, blocktype)?; let else_ebb = ebb_with_params(builder, params)?; // We change the target of the branch instruction. @@ -1371,7 +1373,7 @@ fn translate_load( opcode: ir::Opcode, result_ty: Type, builder: &mut FunctionBuilder, - state: &mut TranslationState, + state: &mut FuncTranslationState, environ: &mut FE, ) -> WasmResult<()> { let addr32 = state.pop1(); @@ -1394,7 +1396,7 @@ fn translate_store( offset: u32, opcode: ir::Opcode, builder: &mut FunctionBuilder, - state: &mut TranslationState, + state: &mut FuncTranslationState, environ: &mut FE, ) -> WasmResult<()> { let (addr32, val) = state.pop2(); @@ -1411,13 +1413,13 @@ fn translate_store( Ok(()) } -fn translate_icmp(cc: IntCC, builder: &mut FunctionBuilder, state: &mut TranslationState) { +fn translate_icmp(cc: IntCC, builder: &mut FunctionBuilder, state: &mut FuncTranslationState) { let (arg0, arg1) = state.pop2(); let val = builder.ins().icmp(cc, arg0, arg1); state.push1(builder.ins().bint(I32, val)); } -fn translate_fcmp(cc: FloatCC, builder: &mut FunctionBuilder, state: &mut TranslationState) { +fn translate_fcmp(cc: FloatCC, builder: &mut FunctionBuilder, state: &mut FuncTranslationState) { let (arg0, arg1) = state.pop2(); let val = builder.ins().fcmp(cc, arg0, arg1); state.push1(builder.ins().bint(I32, val)); @@ -1426,7 +1428,7 @@ fn translate_fcmp(cc: FloatCC, builder: &mut FunctionBuilder, state: &mut Transl fn translate_br_if( relative_depth: u32, builder: &mut FunctionBuilder, - state: &mut TranslationState, + state: &mut FuncTranslationState, ) { let val = state.pop1(); let (br_destination, inputs) = translate_br_if_args(relative_depth, state); @@ -1443,7 +1445,7 @@ fn translate_br_if( fn translate_br_if_args( relative_depth: u32, - state: &mut TranslationState, + state: &mut FuncTranslationState, ) -> (ir::Ebb, &[ir::Value]) { let i = state.control_stack.len() - 1 - (relative_depth as usize); let (return_count, br_destination) = { diff --git a/cranelift/wasm/src/environ/dummy.rs b/cranelift/wasm/src/environ/dummy.rs index cd84c00a28..2d3137f250 100644 --- a/cranelift/wasm/src/environ/dummy.rs +++ b/cranelift/wasm/src/environ/dummy.rs @@ -5,10 +5,9 @@ //! [wasmtime-environ]: https://crates.io/crates/wasmtime-environ //! [Wasmtime]: https://github.com/CraneStation/wasmtime -use crate::environ::{ - FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, WasmResult, WasmTypesMap, -}; +use crate::environ::{FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, WasmResult}; use crate::func_translator::FuncTranslator; +use crate::state::ModuleTranslationState; use crate::translation_utils::{ DefinedFuncIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex, @@ -531,7 +530,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { fn define_function_body( &mut self, - wasm_types: &WasmTypesMap, + module_translation_state: &ModuleTranslationState, body_bytes: &'data [u8], body_offset: usize, ) -> WasmResult<()> { @@ -546,7 +545,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { func.collect_debug_info(); } self.trans.translate( - wasm_types, + module_translation_state, body_bytes, body_offset, &mut func, diff --git a/cranelift/wasm/src/environ/mod.rs b/cranelift/wasm/src/environ/mod.rs index ac29af7c8f..4b7405ea7b 100644 --- a/cranelift/wasm/src/environ/mod.rs +++ b/cranelift/wasm/src/environ/mod.rs @@ -7,5 +7,4 @@ mod spec; pub use crate::environ::dummy::DummyEnvironment; pub use crate::environ::spec::{ FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, WasmError, WasmResult, - WasmTypesMap, }; diff --git a/cranelift/wasm/src/environ/spec.rs b/cranelift/wasm/src/environ/spec.rs index 499483116f..6e44f22c74 100644 --- a/cranelift/wasm/src/environ/spec.rs +++ b/cranelift/wasm/src/environ/spec.rs @@ -6,7 +6,7 @@ //! //! [Wasmtime]: https://github.com/CraneStation/wasmtime -use crate::state::TranslationState; +use crate::state::{FuncTranslationState, ModuleTranslationState}; use crate::translation_utils::{ FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex, }; @@ -15,7 +15,6 @@ use cranelift_codegen::cursor::FuncCursor; use cranelift_codegen::ir::immediates::Offset32; use cranelift_codegen::ir::{self, InstBuilder}; use cranelift_codegen::isa::TargetFrontendConfig; -use cranelift_entity::PrimaryMap; use cranelift_frontend::FunctionBuilder; use failure_derive::Fail; use std::boxed::Box; @@ -104,25 +103,6 @@ pub enum ReturnMode { FallthroughReturn, } -/// A map containing a Wasm module's original, raw signatures. -/// -/// This is used for translating multi-value Wasm blocks inside functions, which -/// are encoded to refer to their type signature via index. -#[derive(Debug)] -pub struct WasmTypesMap { - pub(crate) inner: - PrimaryMap, Box<[wasmparser::Type]>)>, -} - -impl WasmTypesMap { - /// Creates a new type map. - pub fn new() -> Self { - Self { - inner: PrimaryMap::new(), - } - } -} - /// Environment affecting the translation of a single WebAssembly function. /// /// A `FuncEnvironment` trait object is required to translate a WebAssembly function to Cranelift @@ -301,7 +281,7 @@ pub trait FuncEnvironment { &mut self, _op: &Operator, _builder: &mut FunctionBuilder, - _state: &TranslationState, + _state: &FuncTranslationState, ) -> WasmResult<()> { Ok(()) } @@ -312,7 +292,7 @@ pub trait FuncEnvironment { &mut self, _op: &Operator, _builder: &mut FunctionBuilder, - _state: &TranslationState, + _state: &FuncTranslationState, ) -> WasmResult<()> { Ok(()) } @@ -469,7 +449,7 @@ pub trait ModuleEnvironment<'data> { /// functions is already provided by `reserve_func_types`. fn define_function_body( &mut self, - wasm_types: &WasmTypesMap, + module_translation_state: &ModuleTranslationState, body_bytes: &'data [u8], body_offset: usize, ) -> WasmResult<()>; diff --git a/cranelift/wasm/src/func_translator.rs b/cranelift/wasm/src/func_translator.rs index 0f9f979e92..39b8dd43ca 100644 --- a/cranelift/wasm/src/func_translator.rs +++ b/cranelift/wasm/src/func_translator.rs @@ -5,8 +5,8 @@ //! WebAssembly module and the runtime environment. use crate::code_translator::translate_operator; -use crate::environ::{FuncEnvironment, ReturnMode, WasmResult, WasmTypesMap}; -use crate::state::TranslationState; +use crate::environ::{FuncEnvironment, ReturnMode, WasmResult}; +use crate::state::{FuncTranslationState, ModuleTranslationState}; use crate::translation_utils::get_vmctx_value_label; use crate::wasm_unsupported; use cranelift_codegen::entity::EntityRef; @@ -23,7 +23,7 @@ use wasmparser::{self, BinaryReader}; /// functions which will reduce heap allocation traffic. pub struct FuncTranslator { func_ctx: FunctionBuilderContext, - state: TranslationState, + state: FuncTranslationState, } impl FuncTranslator { @@ -31,7 +31,7 @@ impl FuncTranslator { pub fn new() -> Self { Self { func_ctx: FunctionBuilderContext::new(), - state: TranslationState::new(), + state: FuncTranslationState::new(), } } @@ -55,14 +55,14 @@ impl FuncTranslator { /// pub fn translate( &mut self, - wasm_types: &WasmTypesMap, + module_translation_state: &ModuleTranslationState, code: &[u8], code_offset: usize, func: &mut ir::Function, environ: &mut FE, ) -> WasmResult<()> { self.translate_from_reader( - wasm_types, + module_translation_state, BinaryReader::new_with_offset(code, code_offset), func, environ, @@ -72,7 +72,7 @@ impl FuncTranslator { /// Translate a binary WebAssembly function from a `BinaryReader`. pub fn translate_from_reader( &mut self, - wasm_types: &WasmTypesMap, + module_translation_state: &ModuleTranslationState, mut reader: BinaryReader, func: &mut ir::Function, environ: &mut FE, @@ -108,7 +108,13 @@ impl FuncTranslator { self.state.initialize(&builder.func.signature, exit_block); parse_local_decls(&mut reader, &mut builder, num_params, environ)?; - parse_function_body(wasm_types, reader, &mut builder, &mut self.state, environ)?; + parse_function_body( + module_translation_state, + reader, + &mut builder, + &mut self.state, + environ, + )?; builder.finalize(); Ok(()) @@ -206,10 +212,10 @@ fn declare_locals( /// This assumes that the local variable declarations have already been parsed and function /// arguments and locals are declared in the builder. fn parse_function_body( - wasm_types: &WasmTypesMap, + module_translation_state: &ModuleTranslationState, mut reader: BinaryReader, builder: &mut FunctionBuilder, - state: &mut TranslationState, + state: &mut FuncTranslationState, environ: &mut FE, ) -> WasmResult<()> { // The control stack is initialized with a single block representing the whole function. @@ -220,7 +226,7 @@ fn parse_function_body( builder.set_srcloc(cur_srcloc(&reader)); let op = reader.read_operator()?; environ.before_translate_operator(&op, builder, state)?; - translate_operator(wasm_types, &op, builder, state, environ)?; + translate_operator(module_translation_state, &op, builder, state, environ)?; environ.after_translate_operator(&op, builder, state)?; } @@ -258,7 +264,8 @@ fn cur_srcloc(reader: &BinaryReader) -> ir::SourceLoc { #[cfg(test)] mod tests { use super::{FuncTranslator, ReturnMode}; - use crate::environ::{DummyEnvironment, WasmTypesMap}; + use crate::environ::DummyEnvironment; + use crate::ModuleTranslationState; use cranelift_codegen::ir::types::I32; use cranelift_codegen::{ir, isa, settings, Context}; use log::debug; @@ -290,7 +297,7 @@ mod tests { false, ); - let wasm_types = WasmTypesMap::new(); + let module_translation_state = ModuleTranslationState::new(); let mut ctx = Context::new(); ctx.func.name = ir::ExternalName::testcase("small1"); @@ -299,7 +306,7 @@ mod tests { trans .translate( - &wasm_types, + &module_translation_state, &BODY, 0, &mut ctx.func, @@ -337,7 +344,7 @@ mod tests { false, ); - let wasm_types = WasmTypesMap::new(); + let module_translation_state = ModuleTranslationState::new(); let mut ctx = Context::new(); ctx.func.name = ir::ExternalName::testcase("small2"); @@ -346,7 +353,7 @@ mod tests { trans .translate( - &wasm_types, + &module_translation_state, &BODY, 0, &mut ctx.func, @@ -393,7 +400,7 @@ mod tests { false, ); - let wasm_types = WasmTypesMap::new(); + let module_translation_state = ModuleTranslationState::new(); let mut ctx = Context::new(); ctx.func.name = ir::ExternalName::testcase("infloop"); @@ -401,7 +408,7 @@ mod tests { trans .translate( - &wasm_types, + &module_translation_state, &BODY, 0, &mut ctx.func, diff --git a/cranelift/wasm/src/lib.rs b/cranelift/wasm/src/lib.rs index f4fa3a7358..a50bd79320 100644 --- a/cranelift/wasm/src/lib.rs +++ b/cranelift/wasm/src/lib.rs @@ -59,11 +59,12 @@ mod translation_utils; pub use crate::environ::{ DummyEnvironment, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, WasmError, - WasmResult, WasmTypesMap, + WasmResult, }; pub use crate::func_translator::FuncTranslator; pub use crate::module_translator::translate_module; -pub use crate::state::TranslationState; +pub use crate::state::func_state::FuncTranslationState; +pub use crate::state::module_state::ModuleTranslationState; pub use crate::translation_utils::{ get_vmctx_value_label, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, diff --git a/cranelift/wasm/src/module_translator.rs b/cranelift/wasm/src/module_translator.rs index 4076b8c740..257daa1f20 100644 --- a/cranelift/wasm/src/module_translator.rs +++ b/cranelift/wasm/src/module_translator.rs @@ -1,11 +1,12 @@ //! Translation skeleton that traverses the whole WebAssembly module and call helper functions //! to deal with each part of it. -use crate::environ::{ModuleEnvironment, WasmError, WasmResult, WasmTypesMap}; +use crate::environ::{ModuleEnvironment, WasmError, WasmResult}; use crate::sections_translator::{ parse_code_section, parse_data_section, parse_element_section, parse_export_section, parse_function_section, parse_global_section, parse_import_section, parse_memory_section, parse_name_section, parse_start_section, parse_table_section, parse_type_section, }; +use crate::state::ModuleTranslationState; use cranelift_codegen::timing; use wasmparser::{CustomSectionContent, ModuleReader, SectionContent}; @@ -14,16 +15,16 @@ use wasmparser::{CustomSectionContent, ModuleReader, SectionContent}; pub fn translate_module<'data>( data: &'data [u8], environ: &mut dyn ModuleEnvironment<'data>, -) -> WasmResult<()> { +) -> WasmResult { let _tt = timing::wasm_translate_module(); let mut reader = ModuleReader::new(data)?; - let mut wasm_types = WasmTypesMap::new(); + let mut module_translation_state = ModuleTranslationState::new(); while !reader.eof() { let section = reader.read()?; match section.content()? { SectionContent::Type(types) => { - parse_type_section(types, &mut wasm_types, environ)?; + parse_type_section(types, &mut module_translation_state, environ)?; } SectionContent::Import(imports) => { @@ -59,7 +60,7 @@ pub fn translate_module<'data>( } SectionContent::Code(code) => { - parse_code_section(code, &wasm_types, environ)?; + parse_code_section(code, &module_translation_state, environ)?; } SectionContent::Data(data) => { @@ -91,5 +92,5 @@ pub fn translate_module<'data>( } } - Ok(()) + Ok(module_translation_state) } diff --git a/cranelift/wasm/src/sections_translator.rs b/cranelift/wasm/src/sections_translator.rs index d14852f609..cc479c8a3e 100644 --- a/cranelift/wasm/src/sections_translator.rs +++ b/cranelift/wasm/src/sections_translator.rs @@ -7,7 +7,8 @@ //! The special case of the initialize expressions for table elements offsets or global variables //! is handled, according to the semantics of WebAssembly, to only specific expressions that are //! interpreted on the fly. -use crate::environ::{ModuleEnvironment, WasmResult, WasmTypesMap}; +use crate::environ::{ModuleEnvironment, WasmResult}; +use crate::state::ModuleTranslationState; use crate::translation_utils::{ tabletype_to_type, type_to_type, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex, Table, TableElementType, TableIndex, @@ -29,11 +30,11 @@ use wasmparser::{ /// Parses the Type section of the wasm module. pub fn parse_type_section( types: TypeSectionReader, - wasm_types: &mut WasmTypesMap, + module_translation_state: &mut ModuleTranslationState, environ: &mut dyn ModuleEnvironment, ) -> WasmResult<()> { let count = types.get_count(); - wasm_types.inner.reserve(count as usize); + module_translation_state.wasm_types.reserve(count as usize); environ.reserve_signatures(count)?; for entry in types { @@ -55,7 +56,7 @@ pub fn parse_type_section( AbiParam::new(cret_arg) })); environ.declare_signature(sig)?; - wasm_types.inner.push((params, returns)); + module_translation_state.wasm_types.push((params, returns)); } ty => { return Err(wasm_unsupported!( @@ -327,14 +328,14 @@ pub fn parse_element_section<'data>( /// Parses the Code section of the wasm module. pub fn parse_code_section<'data>( code: CodeSectionReader<'data>, - wasm_types: &WasmTypesMap, + module_translation_state: &ModuleTranslationState, environ: &mut dyn ModuleEnvironment<'data>, ) -> WasmResult<()> { for body in code { let mut reader = body?.get_binary_reader(); let size = reader.bytes_remaining(); let offset = reader.original_position(); - environ.define_function_body(wasm_types, reader.read_bytes(size)?, offset)?; + environ.define_function_body(module_translation_state, reader.read_bytes(size)?, offset)?; } Ok(()) } diff --git a/cranelift/wasm/src/state.rs b/cranelift/wasm/src/state/func_state.rs similarity index 96% rename from cranelift/wasm/src/state.rs rename to cranelift/wasm/src/state/func_state.rs index cd84434e2d..4b3627e008 100644 --- a/cranelift/wasm/src/state.rs +++ b/cranelift/wasm/src/state/func_state.rs @@ -1,11 +1,14 @@ -//! WebAssembly function translation state. +//! WebAssembly module and function translation state. //! -//! The `TranslationState` struct defined in this module is used to keep track of the WebAssembly +//! The `ModuleTranslationState` struct defined in this module is used to keep track of data about +//! the whole WebAssembly module, such as the decoded type signatures. +//! +//! The `FuncTranslationState` struct defined in this module is used to keep track of the WebAssembly //! value and control stacks during the translation of a single function. -use super::{HashMap, Occupied, Vacant}; use crate::environ::{FuncEnvironment, GlobalVariable, WasmResult}; use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex}; +use crate::{HashMap, Occupied, Vacant}; use cranelift_codegen::ir::{self, Ebb, Inst, Value}; use std::vec::Vec; @@ -159,12 +162,12 @@ impl ControlStackFrame { } } -/// Contains information passed along during the translation and that records: +/// Contains information passed along during a function's translation and that records: /// /// - The current value and control stacks. /// - The depth of the two unreachable control blocks stacks, that are manipulated when translating /// unreachable code; -pub struct TranslationState { +pub struct FuncTranslationState { /// A stack of values corresponding to the active values in the input wasm function at this /// point. pub(crate) stack: Vec, @@ -195,7 +198,7 @@ pub struct TranslationState { } // Public methods that are exposed to non-`cranelift_wasm` API consumers. -impl TranslationState { +impl FuncTranslationState { /// True if the current translation state expresses reachable code, false if it is unreachable. #[inline] pub fn reachable(&self) -> bool { @@ -203,8 +206,8 @@ impl TranslationState { } } -impl TranslationState { - /// Construct a new, empty, `TranslationState` +impl FuncTranslationState { + /// Construct a new, empty, `FuncTranslationState` pub(crate) fn new() -> Self { Self { stack: Vec::new(), @@ -386,7 +389,7 @@ impl TranslationState { } /// Methods for handling entity references. -impl TranslationState { +impl FuncTranslationState { /// Get the `GlobalVariable` reference that should be used to access the global variable /// `index`. Create the reference if necessary. /// Also return the WebAssembly type of the global. diff --git a/cranelift/wasm/src/state/mod.rs b/cranelift/wasm/src/state/mod.rs new file mode 100644 index 0000000000..730dc8beb5 --- /dev/null +++ b/cranelift/wasm/src/state/mod.rs @@ -0,0 +1,14 @@ +//! WebAssembly module and function translation state. +//! +//! The `ModuleTranslationState` struct defined in this module is used to keep track of data about +//! the whole WebAssembly module, such as the decoded type signatures. +//! +//! The `FuncTranslationState` struct defined in this module is used to keep track of the WebAssembly +//! value and control stacks during the translation of a single function. + +pub(crate) mod func_state; +pub(crate) mod module_state; + +// Re-export for convenience. +pub(crate) use func_state::*; +pub(crate) use module_state::*; diff --git a/cranelift/wasm/src/state/module_state.rs b/cranelift/wasm/src/state/module_state.rs new file mode 100644 index 0000000000..b2cbca77eb --- /dev/null +++ b/cranelift/wasm/src/state/module_state.rs @@ -0,0 +1,27 @@ +use crate::translation_utils::SignatureIndex; +use cranelift_entity::PrimaryMap; +use std::boxed::Box; + +/// Contains information decoded from the Wasm module that must be referenced +/// during each Wasm function's translation. +/// +/// This is only for data that is maintained by `cranelift-wasm` itself, as +/// opposed to being maintained by the embedder. Data that is maintained by the +/// embedder is represented with `ModuleEnvironment`. +#[derive(Debug)] +pub struct ModuleTranslationState { + /// A map containing a Wasm module's original, raw signatures. + /// + /// This is used for translating multi-value Wasm blocks inside functions, + /// which are encoded to refer to their type signature via index. + pub(crate) wasm_types: + PrimaryMap, Box<[wasmparser::Type]>)>, +} + +impl ModuleTranslationState { + pub(crate) fn new() -> Self { + ModuleTranslationState { + wasm_types: PrimaryMap::new(), + } + } +} diff --git a/cranelift/wasm/src/translation_utils.rs b/cranelift/wasm/src/translation_utils.rs index aba5ce5178..1e5e963b4a 100644 --- a/cranelift/wasm/src/translation_utils.rs +++ b/cranelift/wasm/src/translation_utils.rs @@ -1,5 +1,6 @@ //! Helper functions and structures for the translation. -use crate::environ::{WasmResult, WasmTypesMap}; +use crate::environ::WasmResult; +use crate::state::ModuleTranslationState; use crate::wasm_unsupported; use core::u32; use cranelift_codegen::entity::entity_impl; @@ -148,7 +149,7 @@ pub fn tabletype_to_type(ty: wasmparser::Type) -> WasmResult> { /// Get the parameter and result types for the given Wasm blocktype. pub fn blocktype_params_results( - wasm_types: &WasmTypesMap, + module_translation_state: &ModuleTranslationState, ty_or_ft: wasmparser::TypeOrFuncType, ) -> WasmResult<(&[wasmparser::Type], &[wasmparser::Type])> { Ok(match ty_or_ft { @@ -163,7 +164,7 @@ pub fn blocktype_params_results( }, wasmparser::TypeOrFuncType::FuncType(ty_index) => { let sig_idx = SignatureIndex::from_u32(ty_index); - let (ref params, ref returns) = wasm_types.inner[sig_idx]; + let (ref params, ref returns) = module_translation_state.wasm_types[sig_idx]; (&*params, &*returns) } })