diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index 3db93b57c9..b674fbf7f9 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -15,6 +15,7 @@ path = "src/clif-util.rs" [dependencies] cfg-if = "0.1" cranelift-codegen = { path = "lib/codegen", version = "0.18.1" } +cranelift-entity = { path = "lib/entity", version = "0.18.1" } cranelift-reader = { path = "lib/reader", version = "0.18.1" } cranelift-frontend = { path = "lib/frontend", version = "0.18.1" } cranelift-serde = { path = "lib/serde", version = "0.18.1", optional = true } diff --git a/cranelift/src/clif-util.rs b/cranelift/src/clif-util.rs index 8df6a603d7..0f7edd4ce3 100644 --- a/cranelift/src/clif-util.rs +++ b/cranelift/src/clif-util.rs @@ -23,6 +23,7 @@ extern crate term; cfg_if! { if #[cfg(feature = "wasm")] { + extern crate cranelift_entity; extern crate cranelift_wasm; extern crate wabt; mod wasm; diff --git a/cranelift/src/wasm.rs b/cranelift/src/wasm.rs index 72fcb0d729..d448f75389 100644 --- a/cranelift/src/wasm.rs +++ b/cranelift/src/wasm.rs @@ -7,7 +7,8 @@ use cranelift_codegen::Context; use cranelift_codegen::print_errors::{pretty_error, pretty_verifier_error}; use cranelift_codegen::settings::FlagsOrIsa; -use cranelift_wasm::{translate_module, DummyEnvironment, ModuleEnvironment}; +use cranelift_entity::EntityRef; +use cranelift_wasm::{translate_module, DummyEnvironment, FuncIndex, ModuleEnvironment}; use std::error::Error; use std::path::Path; use std::path::PathBuf; @@ -107,17 +108,17 @@ fn handle_module( } let num_func_imports = dummy_environ.get_num_func_imports(); - for (def_index, func) in dummy_environ.info.function_bodies.iter().enumerate() { - let func_index = num_func_imports + def_index; + for (def_index, func) in dummy_environ.info.function_bodies.iter() { + let func_index = num_func_imports + def_index.index(); let mut context = Context::new(); context.func = func.clone(); if let Some(start_func) = dummy_environ.info.start_func { - if func_index == start_func { + if func_index == start_func.index() { println!("; Selected as wasm start function"); } } vprintln!(flag_verbose, ""); - for export_name in &dummy_environ.info.functions[func_index].export_names { + for export_name in &dummy_environ.info.functions[FuncIndex::new(func_index)].export_names { println!("; Exported as \"{}\"", export_name); } println!("{}", context.func.display(None)); @@ -142,10 +143,10 @@ fn handle_module( let num_func_imports = dummy_environ.get_num_func_imports(); let mut total_module_code_size = 0; let mut context = Context::new(); - for (def_index, func) in dummy_environ.info.function_bodies.iter().enumerate() { + for (def_index, func) in dummy_environ.info.function_bodies.iter() { context.func = func.clone(); - let func_index = num_func_imports + def_index; + let func_index = num_func_imports + def_index.index(); if flag_check_translation { context .verify(fisa) @@ -162,7 +163,7 @@ fn handle_module( total_module_code_size += compiled_size; println!( "Function #{} bytecode size: {} bytes", - func_index, dummy_environ.func_bytecode_sizes[def_index] + func_index, dummy_environ.func_bytecode_sizes[def_index.index()] ); } } @@ -170,11 +171,11 @@ fn handle_module( if flag_print { vprintln!(flag_verbose, ""); if let Some(start_func) = dummy_environ.info.start_func { - if func_index == start_func { + if func_index == start_func.index() { println!("; Selected as wasm start function"); } } - for export_name in &dummy_environ.info.functions[func_index].export_names { + for export_name in &dummy_environ.info.functions[FuncIndex::new(func_index)].export_names { println!("; Exported as \"{}\"", export_name); } println!("{}", context.func.display(fisa.isa)); diff --git a/lib/wasm/Cargo.toml b/lib/wasm/Cargo.toml index ff1a8fc48b..abc33510a1 100644 --- a/lib/wasm/Cargo.toml +++ b/lib/wasm/Cargo.toml @@ -11,6 +11,7 @@ keywords = ["webassembly", "wasm"] [dependencies] wasmparser = { version = "0.17.2", default-features = false } cranelift-codegen = { path = "../codegen", version = "0.18.1", default-features = false } +cranelift-entity = { path = "../entity", version = "0.18.1", default-features = false } cranelift-frontend = { path = "../frontend", version = "0.18.1", default-features = false } hashmap_core = { version = "0.1.9", optional = true } failure = { version = "0.1.1", default-features = false, features = ["derive"] } diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index e158b76c08..7ab5f00cb6 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -26,6 +26,7 @@ use cranelift_codegen::ir::condcodes::{FloatCC, IntCC}; use cranelift_codegen::ir::types::*; use cranelift_codegen::ir::{self, InstBuilder, JumpTableData, MemFlags}; use cranelift_codegen::packed_option::ReservedValue; +use cranelift_entity::EntityRef; use cranelift_frontend::{FunctionBuilder, Variable}; use environ::{FuncEnvironment, GlobalVariable, WasmError, WasmResult}; use state::{ControlStackFrame, TranslationState}; @@ -33,7 +34,7 @@ use std::collections::{hash_map, HashMap}; use std::vec::Vec; use std::{i32, u32}; use translation_utils::{f32_translation, f64_translation, num_return_values, type_to_type}; -use translation_utils::{FunctionIndex, MemoryIndex, SignatureIndex, TableIndex}; +use translation_utils::{FuncIndex, MemoryIndex, SignatureIndex, TableIndex}; use wasmparser::{MemoryImmediate, Operator}; // Clippy warns about "flags: _" but its important to document that the flags field is ignored @@ -358,7 +359,7 @@ pub fn translate_operator( let (fref, num_args) = state.get_direct_func(builder.func, function_index, environ); let call = environ.translate_call( builder.cursor(), - function_index as FunctionIndex, + FuncIndex::new(function_index as usize), fref, state.peekn(num_args), )?; diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index 1fdbbe7df3..b2db269e24 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -5,19 +5,20 @@ use cranelift_codegen::ir::immediates::Imm64; use cranelift_codegen::ir::types::*; use cranelift_codegen::ir::{self, InstBuilder}; use cranelift_codegen::settings; +use cranelift_entity::{EntityRef, PrimaryMap}; use environ::{FuncEnvironment, GlobalVariable, ModuleEnvironment, WasmResult}; use func_translator::FuncTranslator; use std::string::String; use std::vec::Vec; use target_lexicon::Triple; use translation_utils::{ - FunctionIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex, + DefinedFuncIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex, }; use wasmparser; /// Compute a `ir::ExternalName` for a given wasm function index. -fn get_func_name(func_index: FunctionIndex) -> ir::ExternalName { - ir::ExternalName::user(0, func_index as u32) +fn get_func_name(func_index: FuncIndex) -> ir::ExternalName { + ir::ExternalName::user(0, func_index.index() as u32) } /// A collection of names under which a given entity is exported. @@ -55,10 +56,10 @@ pub struct DummyModuleInfo { pub imported_funcs: Vec<(String, String)>, /// Functions, imported and local. - pub functions: Vec>, + pub functions: PrimaryMap>, /// Function bodies. - pub function_bodies: Vec, + pub function_bodies: PrimaryMap, /// Tables as provided by `declare_table`. pub tables: Vec>, @@ -70,7 +71,7 @@ pub struct DummyModuleInfo { pub globals: Vec>, /// The start function. - pub start_func: Option, + pub start_func: Option, } impl DummyModuleInfo { @@ -81,8 +82,8 @@ impl DummyModuleInfo { flags, signatures: Vec::new(), imported_funcs: Vec::new(), - functions: Vec::new(), - function_bodies: Vec::new(), + functions: PrimaryMap::new(), + function_bodies: PrimaryMap::new(), tables: Vec::new(), memories: Vec::new(), globals: Vec::new(), @@ -215,7 +216,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ func.import_signature(self.vmctx_sig(index)) } - fn make_direct_func(&mut self, func: &mut ir::Function, index: FunctionIndex) -> ir::FuncRef { + fn make_direct_func(&mut self, func: &mut ir::Function, index: FuncIndex) -> ir::FuncRef { let sigidx = self.mod_info.functions[index].entity; // A real implementation would probably add a `vmctx` argument. // And maybe attempt some signature de-duplication. @@ -275,7 +276,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ fn translate_call( &mut self, mut pos: FuncCursor, - _callee_index: FunctionIndex, + _callee_index: FuncIndex, callee: ir::FuncRef, call_args: &[ir::Value], ) -> WasmResult { @@ -319,7 +320,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { &self.info.flags } - fn get_func_name(&self, func_index: FunctionIndex) -> ir::ExternalName { + fn get_func_name(&self, func_index: FuncIndex) -> ir::ExternalName { get_func_name(func_index) } @@ -356,7 +357,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { self.info.functions.push(Exportable::new(sig_index)); } - fn get_func_type(&self, func_index: FunctionIndex) -> SignatureIndex { + fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex { self.info.functions[func_index].entity } @@ -376,7 +377,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { _table_index: TableIndex, _base: Option, _offset: usize, - _elements: Vec, + _elements: Vec, ) { // We do nothing } @@ -393,7 +394,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { // We do nothing } - fn declare_func_export(&mut self, func_index: FunctionIndex, name: &'data str) { + fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) { self.info.functions[func_index] .export_names .push(String::from(name)); @@ -417,7 +418,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { .push(String::from(name)); } - fn declare_start_func(&mut self, func_index: FunctionIndex) { + fn declare_start_func(&mut self, func_index: DefinedFuncIndex) { debug_assert!(self.info.start_func.is_none()); self.info.start_func = Some(func_index); } @@ -425,9 +426,9 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { fn define_function_body(&mut self, body_bytes: &'data [u8]) -> WasmResult<()> { let func = { let mut func_environ = DummyFuncEnvironment::new(&self.info); - let function_index = self.get_num_func_imports() + self.info.function_bodies.len(); - let name = get_func_name(function_index); - let sig = func_environ.vmctx_sig(self.get_func_type(function_index)); + let func_index = FuncIndex::new(self.get_num_func_imports() + self.info.function_bodies.len()); + let name = get_func_name(func_index); + let sig = func_environ.vmctx_sig(self.get_func_type(func_index)); let mut func = ir::Function::with_name_signature(name, sig); let reader = wasmparser::BinaryReader::new(body_bytes); self.trans diff --git a/lib/wasm/src/environ/spec.rs b/lib/wasm/src/environ/spec.rs index 1a002d5da1..157f531270 100644 --- a/lib/wasm/src/environ/spec.rs +++ b/lib/wasm/src/environ/spec.rs @@ -6,7 +6,7 @@ use cranelift_codegen::settings::Flags; use std::vec::Vec; use target_lexicon::Triple; use translation_utils::{ - FunctionIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex, + DefinedFuncIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex, }; use wasmparser::BinaryReaderError; @@ -137,7 +137,7 @@ pub trait FuncEnvironment { /// /// The function's signature will only be used for direct calls, even if the module has /// indirect calls with the same WebAssembly type. - fn make_direct_func(&mut self, func: &mut ir::Function, index: FunctionIndex) -> ir::FuncRef; + fn make_direct_func(&mut self, func: &mut ir::Function, index: FuncIndex) -> ir::FuncRef; /// Translate a `call_indirect` WebAssembly instruction at `pos`. /// @@ -169,7 +169,7 @@ pub trait FuncEnvironment { fn translate_call( &mut self, mut pos: FuncCursor, - _callee_index: FunctionIndex, + _callee_index: FuncIndex, callee: ir::FuncRef, call_args: &[ir::Value], ) -> WasmResult { @@ -222,7 +222,7 @@ pub trait ModuleEnvironment<'data> { fn flags(&self) -> &Flags; /// Return the name for the given function index. - fn get_func_name(&self, func_index: FunctionIndex) -> ir::ExternalName; + fn get_func_name(&self, func_index: FuncIndex) -> ir::ExternalName; /// Declares a function signature to the environment. fn declare_signature(&mut self, sig: &ir::Signature); @@ -245,7 +245,7 @@ pub trait ModuleEnvironment<'data> { fn declare_func_type(&mut self, sig_index: SignatureIndex); /// Return the signature index for the given function index. - fn get_func_type(&self, func_index: FunctionIndex) -> SignatureIndex; + fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex; /// Declares a global to the environment. fn declare_global(&mut self, global: Global); @@ -261,7 +261,7 @@ pub trait ModuleEnvironment<'data> { table_index: TableIndex, base: Option, offset: usize, - elements: Vec, + elements: Vec, ); /// Declares a memory to the environment fn declare_memory(&mut self, memory: Memory); @@ -275,7 +275,7 @@ pub trait ModuleEnvironment<'data> { ); /// Declares a function export to the environment. - fn declare_func_export(&mut self, func_index: FunctionIndex, name: &'data str); + fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str); /// Declares a table export to the environment. fn declare_table_export(&mut self, table_index: TableIndex, name: &'data str); /// Declares a memory export to the environment. @@ -284,7 +284,7 @@ pub trait ModuleEnvironment<'data> { fn declare_global_export(&mut self, global_index: GlobalIndex, name: &'data str); /// Declares a start function. - fn declare_start_func(&mut self, index: FunctionIndex); + fn declare_start_func(&mut self, index: DefinedFuncIndex); /// Provides the contents of a function body. fn define_function_body(&mut self, body_bytes: &'data [u8]) -> WasmResult<()>; diff --git a/lib/wasm/src/lib.rs b/lib/wasm/src/lib.rs index 995adf10de..b537534bd5 100644 --- a/lib/wasm/src/lib.rs +++ b/lib/wasm/src/lib.rs @@ -26,6 +26,8 @@ #[macro_use(dbg)] extern crate cranelift_codegen; +#[macro_use] +extern crate cranelift_entity; extern crate cranelift_frontend; extern crate target_lexicon; extern crate wasmparser; @@ -48,7 +50,7 @@ pub use environ::{ pub use func_translator::FuncTranslator; pub use module_translator::translate_module; pub use translation_utils::{ - FunctionIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex, Table, + DefinedFuncIndex, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex, Table, TableIndex, }; diff --git a/lib/wasm/src/sections_translator.rs b/lib/wasm/src/sections_translator.rs index 6fdeb38719..e1450ee24b 100644 --- a/lib/wasm/src/sections_translator.rs +++ b/lib/wasm/src/sections_translator.rs @@ -8,11 +8,12 @@ //! is handled, according to the semantics of WebAssembly, to only specific expressions that are //! interpreted on the fly. use cranelift_codegen::ir::{self, AbiParam, Signature}; +use cranelift_entity::EntityRef; use environ::{ModuleEnvironment, WasmError, WasmResult}; use std::str::from_utf8; use std::vec::Vec; use translation_utils::{ - type_to_type, FunctionIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, + type_to_type, DefinedFuncIndex, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex, Table, TableElementType, TableIndex, }; use wasmparser; @@ -150,12 +151,12 @@ pub fn parse_export_section<'data>( // assume valid UTF-8 and use `from_utf8_unchecked` if performance // becomes a concern here. let name = from_utf8(field).unwrap(); - let func_index = index as FunctionIndex; + let func_index = FuncIndex::new(index as usize); match *kind { ExternalKind::Function => environ.declare_func_export(func_index, name), - ExternalKind::Table => environ.declare_table_export(func_index, name), - ExternalKind::Memory => environ.declare_memory_export(func_index, name), - ExternalKind::Global => environ.declare_global_export(func_index, name), + ExternalKind::Table => environ.declare_table_export(func_index.index(), name), + ExternalKind::Memory => environ.declare_memory_export(func_index.index(), name), + ExternalKind::Global => environ.declare_global_export(func_index.index(), name), } } ParserState::EndSection => break, @@ -171,7 +172,7 @@ pub fn parse_start_section(parser: &mut Parser, environ: &mut ModuleEnvironment) loop { match *parser.read() { ParserState::StartSectionEntry(index) => { - environ.declare_start_func(index as FunctionIndex); + environ.declare_start_func(DefinedFuncIndex::new(index as usize)); } ParserState::EndSection => break, ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), @@ -382,8 +383,8 @@ pub fn parse_elements_section( }; match *parser.read() { ParserState::ElementSectionEntryBody(ref elements) => { - let elems: Vec = - elements.iter().map(|&x| x as FunctionIndex).collect(); + let elems: Vec = + elements.iter().map(|&x| FuncIndex::new(x as usize)).collect(); environ.declare_table_elements(table_index, base, offset, elems) } ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), diff --git a/lib/wasm/src/state.rs b/lib/wasm/src/state.rs index d81234fbde..9b32fe3bbd 100644 --- a/lib/wasm/src/state.rs +++ b/lib/wasm/src/state.rs @@ -4,10 +4,11 @@ //! value and control stacks during the translation of a single function. use cranelift_codegen::ir::{self, Ebb, Inst, Value}; +use cranelift_entity::EntityRef; use environ::{FuncEnvironment, GlobalVariable}; use std::collections::HashMap; use std::vec::Vec; -use translation_utils::{FunctionIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex}; +use translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex}; /// A control stack frame can be an `if`, a `block` or a `loop`, each one having the following /// fields: @@ -151,7 +152,7 @@ pub struct TranslationState { // Imported and local functions that have been created by // `FuncEnvironment::make_direct_func()`. // Stores both the function reference and the number of WebAssembly arguments - functions: HashMap, + functions: HashMap, } impl TranslationState { @@ -349,7 +350,7 @@ impl TranslationState { index: u32, environ: &mut FE, ) -> (ir::FuncRef, usize) { - let index = index as FunctionIndex; + let index = FuncIndex::new(index as usize); *self.functions.entry(index).or_insert_with(|| { let fref = environ.make_direct_func(func, index); let sig = func.dfg.ext_funcs[fref].signature; diff --git a/lib/wasm/src/translation_utils.rs b/lib/wasm/src/translation_utils.rs index e6822af761..242e3feef0 100644 --- a/lib/wasm/src/translation_utils.rs +++ b/lib/wasm/src/translation_utils.rs @@ -3,8 +3,16 @@ use cranelift_codegen::ir; use std::u32; use wasmparser; -/// Index of a function (imported or defined) inside the WebAssembly module. -pub type FunctionIndex = usize; +/// Index type of a function (imported or defined) inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct FuncIndex(u32); +entity_impl!(FuncIndex); + +/// Index type of a defined function inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct DefinedFuncIndex(u32); +entity_impl!(DefinedFuncIndex); + /// Index of a table (imported or defined) inside the WebAssembly module. pub type TableIndex = usize; /// Index of a global variable (imported or defined) inside the WebAssembly module. diff --git a/lib/wasm/tests/wasm_testsuite.rs b/lib/wasm/tests/wasm_testsuite.rs index 1924a17d07..166b3af076 100644 --- a/lib/wasm/tests/wasm_testsuite.rs +++ b/lib/wasm/tests/wasm_testsuite.rs @@ -75,7 +75,7 @@ fn handle_module(path: &Path, flags: &Flags) { }; let mut dummy_environ = DummyEnvironment::with_triple_flags(triple!("riscv64"), flags.clone()); translate_module(&data, &mut dummy_environ).unwrap(); - for func in &dummy_environ.info.function_bodies { + for func in dummy_environ.info.function_bodies.values() { verifier::verify_function(func, flags) .map_err(|err| panic!(pretty_verifier_error(func, None, None, &err))) .unwrap();