diff --git a/Cargo.lock b/Cargo.lock index c12484a741..806030fe31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -805,8 +805,8 @@ dependencies = [ "serde", "smallvec", "target-lexicon", - "thiserror", "wasmparser", + "wasmtime-types", "wat", ] @@ -3645,7 +3645,6 @@ name = "wasmtime-cli" version = "0.29.0" dependencies = [ "anyhow", - "cranelift-native", "criterion", "env_logger 0.8.3", "file-per-thread-logger", @@ -3668,7 +3667,6 @@ dependencies = [ "wasmparser", "wasmtime", "wasmtime-cache", - "wasmtime-debug", "wasmtime-environ", "wasmtime-fuzzing", "wasmtime-jit", @@ -3693,20 +3691,6 @@ dependencies = [ "cranelift-native", "cranelift-wasm", "gimli", - "object", - "target-lexicon", - "wasmparser", - "wasmtime-debug", - "wasmtime-environ", -] - -[[package]] -name = "wasmtime-debug" -version = "0.29.0" -dependencies = [ - "anyhow", - "cranelift-codegen", - "gimli", "more-asserts", "object", "target-lexicon", @@ -3721,9 +3705,7 @@ version = "0.29.0" dependencies = [ "anyhow", "cfg-if 1.0.0", - "cranelift-codegen", "cranelift-entity", - "cranelift-wasm", "gimli", "indexmap", "log", @@ -3732,6 +3714,7 @@ dependencies = [ "target-lexicon", "thiserror", "wasmparser", + "wasmtime-types", ] [[package]] @@ -3862,6 +3845,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "wasmtime-types" +version = "0.29.0" +dependencies = [ + "cranelift-entity", + "serde", + "thiserror", + "wasmparser", +] + [[package]] name = "wasmtime-wasi" version = "0.29.0" diff --git a/Cargo.toml b/Cargo.toml index c1d575f685..993817caeb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ doc = false [dependencies] wasmtime = { path = "crates/wasmtime", version = "0.29.0", default-features = false, features = ['cache'] } wasmtime-cache = { path = "crates/cache", version = "0.29.0" } -wasmtime-debug = { path = "crates/debug", version = "0.29.0" } wasmtime-environ = { path = "crates/environ", version = "0.29.0" } wasmtime-jit = { path = "crates/jit", version = "0.29.0" } wasmtime-wast = { path = "crates/wast", version = "0.29.0" } @@ -43,7 +42,6 @@ rayon = "1.5.0" humantime = "2.0.0" wasmparser = "0.80.0" lazy_static = "1.4.0" -cranelift-native = { path = 'cranelift/native', version = '0.76.0' } [dev-dependencies] env_logger = "0.8.1" diff --git a/cranelift/wasm/Cargo.toml b/cranelift/wasm/Cargo.toml index f00187502d..637284b429 100644 --- a/cranelift/wasm/Cargo.toml +++ b/cranelift/wasm/Cargo.toml @@ -16,12 +16,12 @@ wasmparser = { version = "0.80", default-features = false } cranelift-codegen = { path = "../codegen", version = "0.76.0", default-features = false } cranelift-entity = { path = "../entity", version = "0.76.0" } cranelift-frontend = { path = "../frontend", version = "0.76.0", default-features = false } +wasmtime-types = { path = "../../crates/types", version = "0.29.0" } hashbrown = { version = "0.9.1", optional = true } itertools = "0.10.0" log = { version = "0.4.6", default-features = false } serde = { version = "1.0.94", features = ["derive"], optional = true } smallvec = "1.6.1" -thiserror = "1.0.4" [dev-dependencies] wat = "1.0.37" diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index ee3c15ff16..2ee9df7fbb 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -72,13 +72,13 @@ //! ("Relax verification to allow I8X16 to act as a default vector type") use super::{hash_map, HashMap}; -use crate::environ::{FuncEnvironment, GlobalVariable, ReturnMode, WasmResult}; +use crate::environ::{FuncEnvironment, GlobalVariable, ReturnMode}; use crate::state::{ControlStackFrame, ElseData, FuncTranslationState}; use crate::translation_utils::{ block_with_params, blocktype_params_results, f32_translation, f64_translation, }; -use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex, TypeIndex}; use crate::wasm_unsupported; +use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex, TypeIndex, WasmResult}; use core::convert::TryInto; use core::{i32, u32}; use cranelift_codegen::ir::condcodes::{FloatCC, IntCC}; diff --git a/cranelift/wasm/src/environ/dummy.rs b/cranelift/wasm/src/environ/dummy.rs index 53ecf5d259..0974d68661 100644 --- a/cranelift/wasm/src/environ/dummy.rs +++ b/cranelift/wasm/src/environ/dummy.rs @@ -7,15 +7,14 @@ use crate::environ::{ FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment, - WasmFuncType, WasmResult, }; use crate::func_translator::FuncTranslator; use crate::state::FuncTranslationState; -use crate::translation_utils::{ - DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, - Table, TableIndex, TypeIndex, -}; use crate::WasmType; +use crate::{ + DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, + Table, TableIndex, TypeIndex, WasmFuncType, WasmResult, +}; use core::convert::TryFrom; use cranelift_codegen::cursor::FuncCursor; use cranelift_codegen::ir::immediates::{Offset32, Uimm64}; diff --git a/cranelift/wasm/src/environ/mod.rs b/cranelift/wasm/src/environ/mod.rs index cf4672beb3..21889abf6d 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::{ Alias, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment, - WasmError, WasmFuncType, WasmResult, WasmType, }; diff --git a/cranelift/wasm/src/environ/spec.rs b/cranelift/wasm/src/environ/spec.rs index a4a0e2ea3e..460f4ecf73 100644 --- a/cranelift/wasm/src/environ/spec.rs +++ b/cranelift/wasm/src/environ/spec.rs @@ -7,114 +7,21 @@ //! [Wasmtime]: https://github.com/bytecodealliance/wasmtime use crate::state::FuncTranslationState; -use crate::translation_utils::{ +use crate::{ DataIndex, ElemIndex, EntityIndex, EntityType, FuncIndex, Global, GlobalIndex, InstanceIndex, InstanceTypeIndex, Memory, MemoryIndex, ModuleIndex, ModuleTypeIndex, SignatureIndex, Table, - TableIndex, Tag, TagIndex, TypeIndex, + TableIndex, Tag, TagIndex, TypeIndex, WasmError, WasmFuncType, WasmResult, WasmType, }; use core::convert::From; -use core::convert::TryFrom; use cranelift_codegen::cursor::FuncCursor; use cranelift_codegen::ir::immediates::Offset32; use cranelift_codegen::ir::{self, InstBuilder}; use cranelift_codegen::isa::TargetFrontendConfig; use cranelift_frontend::FunctionBuilder; -#[cfg(feature = "enable-serde")] -use serde::{Deserialize, Serialize}; use std::boxed::Box; use std::string::ToString; use std::vec::Vec; -use thiserror::Error; -use wasmparser::ValidatorResources; -use wasmparser::{BinaryReaderError, FuncValidator, FunctionBody, Operator, WasmFeatures}; - -/// WebAssembly value type -- equivalent of `wasmparser`'s Type. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub enum WasmType { - /// I32 type - I32, - /// I64 type - I64, - /// F32 type - F32, - /// F64 type - F64, - /// V128 type - V128, - /// FuncRef type - FuncRef, - /// ExternRef type - ExternRef, - /// ExnRef type - ExnRef, -} - -impl TryFrom for WasmType { - type Error = WasmError; - fn try_from(ty: wasmparser::Type) -> Result { - use wasmparser::Type::*; - match ty { - I32 => Ok(WasmType::I32), - I64 => Ok(WasmType::I64), - F32 => Ok(WasmType::F32), - F64 => Ok(WasmType::F64), - V128 => Ok(WasmType::V128), - FuncRef => Ok(WasmType::FuncRef), - ExternRef => Ok(WasmType::ExternRef), - ExnRef => Ok(WasmType::ExnRef), - EmptyBlockType | Func => Err(WasmError::InvalidWebAssembly { - message: "unexpected value type".to_string(), - offset: 0, - }), - } - } -} - -impl From for wasmparser::Type { - fn from(ty: WasmType) -> wasmparser::Type { - match ty { - WasmType::I32 => wasmparser::Type::I32, - WasmType::I64 => wasmparser::Type::I64, - WasmType::F32 => wasmparser::Type::F32, - WasmType::F64 => wasmparser::Type::F64, - WasmType::V128 => wasmparser::Type::V128, - WasmType::FuncRef => wasmparser::Type::FuncRef, - WasmType::ExternRef => wasmparser::Type::ExternRef, - WasmType::ExnRef => wasmparser::Type::ExnRef, - } - } -} - -/// WebAssembly function type -- equivalent of `wasmparser`'s FuncType. -#[derive(Debug, Clone, Eq, PartialEq, Hash)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct WasmFuncType { - /// Function params types. - pub params: Box<[WasmType]>, - /// Returns params types. - pub returns: Box<[WasmType]>, -} - -impl TryFrom for WasmFuncType { - type Error = WasmError; - fn try_from(ty: wasmparser::FuncType) -> Result { - Ok(Self { - params: ty - .params - .into_vec() - .into_iter() - .map(WasmType::try_from) - .collect::>()?, - returns: ty - .returns - .into_vec() - .into_iter() - .map(WasmType::try_from) - .collect::>()?, - }) - } -} +use wasmparser::{FuncValidator, FunctionBody, Operator, ValidatorResources, WasmFeatures}; /// The value of a WebAssembly global variable. #[derive(Clone, Copy)] @@ -136,64 +43,6 @@ pub enum GlobalVariable { Custom, } -/// A WebAssembly translation error. -/// -/// When a WebAssembly function can't be translated, one of these error codes will be returned -/// to describe the failure. -#[derive(Error, Debug)] -pub enum WasmError { - /// The input WebAssembly code is invalid. - /// - /// This error code is used by a WebAssembly translator when it encounters invalid WebAssembly - /// code. This should never happen for validated WebAssembly code. - #[error("Invalid input WebAssembly code at offset {offset}: {message}")] - InvalidWebAssembly { - /// A string describing the validation error. - message: std::string::String, - /// The bytecode offset where the error occurred. - offset: usize, - }, - - /// A feature used by the WebAssembly code is not supported by the embedding environment. - /// - /// Embedding environments may have their own limitations and feature restrictions. - #[error("Unsupported feature: {0}")] - Unsupported(std::string::String), - - /// An implementation limit was exceeded. - /// - /// Cranelift can compile very large and complicated functions, but the [implementation has - /// limits][limits] that cause compilation to fail when they are exceeded. - /// - /// [limits]: https://github.com/bytecodealliance/wasmtime/blob/main/cranelift/docs/ir.md#implementation-limits - #[error("Implementation limit exceeded")] - ImplLimitExceeded, - - /// Any user-defined error. - #[error("User error: {0}")] - User(std::string::String), -} - -/// Return an `Err(WasmError::Unsupported(msg))` where `msg` the string built by calling `format!` -/// on the arguments to this macro. -#[macro_export] -macro_rules! wasm_unsupported { - ($($arg:tt)*) => { $crate::environ::WasmError::Unsupported(format!($($arg)*)) } -} - -impl From for WasmError { - /// Convert from a `BinaryReaderError` to a `WasmError`. - fn from(e: BinaryReaderError) -> Self { - Self::InvalidWebAssembly { - message: e.message().into(), - offset: e.offset(), - } - } -} - -/// A convenient alias for a `Result` that uses `WasmError` as the error type. -pub type WasmResult = Result; - /// How to return from functions. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum ReturnMode { diff --git a/cranelift/wasm/src/func_translator.rs b/cranelift/wasm/src/func_translator.rs index bf40466239..f69ac2e77b 100644 --- a/cranelift/wasm/src/func_translator.rs +++ b/cranelift/wasm/src/func_translator.rs @@ -5,10 +5,11 @@ //! WebAssembly module and the runtime environment. use crate::code_translator::{bitcast_arguments, translate_operator, wasm_param_types}; -use crate::environ::{FuncEnvironment, ReturnMode, WasmResult}; +use crate::environ::{FuncEnvironment, ReturnMode}; use crate::state::FuncTranslationState; use crate::translation_utils::get_vmctx_value_label; use crate::wasm_unsupported; +use crate::WasmResult; use core::convert::TryInto; use cranelift_codegen::entity::EntityRef; use cranelift_codegen::ir::{self, Block, InstBuilder, ValueLabel}; diff --git a/cranelift/wasm/src/lib.rs b/cranelift/wasm/src/lib.rs index 4e06680385..a9823681b9 100644 --- a/cranelift/wasm/src/lib.rs +++ b/cranelift/wasm/src/lib.rs @@ -58,7 +58,7 @@ mod translation_utils; pub use crate::environ::{ Alias, DummyEnvironment, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, - TargetEnvironment, WasmError, WasmFuncType, WasmResult, WasmType, + TargetEnvironment, }; pub use crate::func_translator::FuncTranslator; pub use crate::module_translator::translate_module; @@ -66,6 +66,7 @@ pub use crate::state::func_state::FuncTranslationState; pub use crate::state::module_state::ModuleTranslationState; pub use crate::translation_utils::*; pub use cranelift_frontend::FunctionBuilder; +pub use wasmtime_types::*; // Convenience reexport of the wasmparser crate that we're linking against, // since a number of types in `wasmparser` show up in the public API of diff --git a/cranelift/wasm/src/module_translator.rs b/cranelift/wasm/src/module_translator.rs index 5d605d1e77..b78397c707 100644 --- a/cranelift/wasm/src/module_translator.rs +++ b/cranelift/wasm/src/module_translator.rs @@ -1,6 +1,6 @@ //! Translation skeleton that traverses the whole WebAssembly module and call helper functions //! to deal with each part of it. -use crate::environ::{ModuleEnvironment, WasmResult}; +use crate::environ::ModuleEnvironment; use crate::sections_translator::{ parse_alias_section, parse_data_section, parse_element_section, parse_export_section, parse_function_section, parse_global_section, parse_import_section, parse_instance_section, @@ -8,6 +8,7 @@ use crate::sections_translator::{ parse_tag_section, parse_type_section, }; use crate::state::ModuleTranslationState; +use crate::WasmResult; use cranelift_codegen::timing; use std::prelude::v1::*; use wasmparser::{NameSectionReader, Parser, Payload, Validator}; diff --git a/cranelift/wasm/src/sections_translator.rs b/cranelift/wasm/src/sections_translator.rs index aeb8e1e55f..e38afc2f05 100644 --- a/cranelift/wasm/src/sections_translator.rs +++ b/cranelift/wasm/src/sections_translator.rs @@ -7,16 +7,16 @@ //! 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::{Alias, ModuleEnvironment, WasmError, WasmResult}; +use crate::environ::{Alias, ModuleEnvironment}; use crate::state::ModuleTranslationState; -use crate::translation_utils::{ +use crate::wasm_unsupported; +use crate::{ DataIndex, ElemIndex, EntityIndex, EntityType, FuncIndex, Global, GlobalIndex, GlobalInit, InstanceIndex, Memory, MemoryIndex, ModuleIndex, Table, TableIndex, Tag, TagIndex, TypeIndex, + WasmError, WasmResult, }; -use crate::wasm_unsupported; use core::convert::TryFrom; use core::convert::TryInto; -use cranelift_codegen::ir::immediates::V128Imm; use cranelift_entity::packed_option::ReservedValue; use cranelift_entity::EntityRef; use std::boxed::Box; @@ -259,7 +259,7 @@ pub fn parse_global_section( Operator::F32Const { value } => GlobalInit::F32Const(value.bits()), Operator::F64Const { value } => GlobalInit::F64Const(value.bits()), Operator::V128Const { value } => { - GlobalInit::V128Const(V128Imm::from(value.bytes().to_vec().as_slice())) + GlobalInit::V128Const(u128::from_le_bytes(*value.bytes())) } Operator::RefNull { ty: _ } => GlobalInit::RefNullConst, Operator::RefFunc { function_index } => { diff --git a/cranelift/wasm/src/state/func_state.rs b/cranelift/wasm/src/state/func_state.rs index 70d62c7240..4bdb4ecbeb 100644 --- a/cranelift/wasm/src/state/func_state.rs +++ b/cranelift/wasm/src/state/func_state.rs @@ -6,8 +6,8 @@ //! 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 crate::environ::{FuncEnvironment, GlobalVariable, WasmResult}; -use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex, TypeIndex}; +use crate::environ::{FuncEnvironment, GlobalVariable}; +use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex, TypeIndex, WasmResult}; use crate::{HashMap, Occupied, Vacant}; use cranelift_codegen::ir::{self, Block, Inst, Value}; use std::vec::Vec; diff --git a/cranelift/wasm/src/state/module_state.rs b/cranelift/wasm/src/state/module_state.rs index e1b96b8c82..578e9368fa 100644 --- a/cranelift/wasm/src/state/module_state.rs +++ b/cranelift/wasm/src/state/module_state.rs @@ -1,5 +1,4 @@ -use crate::environ::{WasmError, WasmResult}; -use crate::translation_utils::SignatureIndex; +use crate::{SignatureIndex, WasmError, WasmResult}; use cranelift_codegen::ir::{types, Type}; use cranelift_entity::PrimaryMap; use std::boxed::Box; diff --git a/cranelift/wasm/src/translation_utils.rs b/cranelift/wasm/src/translation_utils.rs index f29eb2f18c..296b8ff93d 100644 --- a/cranelift/wasm/src/translation_utils.rs +++ b/cranelift/wasm/src/translation_utils.rs @@ -1,235 +1,15 @@ //! Helper functions and structures for the translation. -use crate::environ::{TargetEnvironment, WasmResult, WasmType}; -use crate::{wasm_unsupported, WasmError}; -use core::convert::{TryFrom, TryInto}; +use crate::environ::TargetEnvironment; +use crate::wasm_unsupported; +use crate::WasmResult; +use core::convert::TryInto; use core::u32; -use cranelift_codegen::entity::entity_impl; use cranelift_codegen::ir; -use cranelift_codegen::ir::immediates::V128Imm; use cranelift_frontend::FunctionBuilder; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; use wasmparser::{FuncValidator, WasmFuncType, WasmModuleResources}; -/// Index type of a function (imported or defined) inside the WebAssembly module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -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, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct DefinedFuncIndex(u32); -entity_impl!(DefinedFuncIndex); - -/// Index type of a defined table inside the WebAssembly module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -pub struct DefinedTableIndex(u32); -entity_impl!(DefinedTableIndex); - -/// Index type of a defined memory inside the WebAssembly module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -pub struct DefinedMemoryIndex(u32); -entity_impl!(DefinedMemoryIndex); - -/// Index type of a defined global inside the WebAssembly module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -pub struct DefinedGlobalIndex(u32); -entity_impl!(DefinedGlobalIndex); - -/// Index type of a table (imported or defined) inside the WebAssembly module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct TableIndex(u32); -entity_impl!(TableIndex); - -/// Index type of a global variable (imported or defined) inside the WebAssembly module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct GlobalIndex(u32); -entity_impl!(GlobalIndex); - -/// Index type of a linear memory (imported or defined) inside the WebAssembly module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct MemoryIndex(u32); -entity_impl!(MemoryIndex); - -/// Index type of a signature (imported or defined) inside the WebAssembly module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct SignatureIndex(u32); -entity_impl!(SignatureIndex); - -/// Index type of a passive data segment inside the WebAssembly module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct DataIndex(u32); -entity_impl!(DataIndex); - -/// Index type of a passive element segment inside the WebAssembly module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct ElemIndex(u32); -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); - -/// Index type of an event inside the WebAssembly module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct TagIndex(u32); -entity_impl!(TagIndex); - -/// Specialized index for just module types. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct ModuleTypeIndex(u32); -entity_impl!(ModuleTypeIndex); - -/// Specialized index for just instance types. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct InstanceTypeIndex(u32); -entity_impl!(InstanceTypeIndex); - -/// An index of an entity. -#[derive(Copy, 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), - /// An event definition. - Tag(Tag), - /// 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(SignatureIndex), - /// An instance where the index points to the type section and records a - /// instance's exports. - Instance(InstanceTypeIndex), - /// A module where the index points to the type section and records a - /// module's imports and exports. - Module(ModuleTypeIndex), -} - -/// A WebAssembly global. -/// -/// Note that we record both the original Wasm type and the Cranelift IR type -/// used to represent it. This is because multiple different kinds of Wasm types -/// might be represented with the same Cranelift IR type. For example, both a -/// Wasm `i64` and a `funcref` might be represented with a Cranelift `i64` on -/// 64-bit architectures, and when GC is not required for func refs. -#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct Global { - /// The Wasm type of the value stored in the global. - pub wasm_ty: crate::WasmType, - /// A flag indicating whether the value may change at runtime. - pub mutability: bool, - /// The source of the initial value. - pub initializer: GlobalInit, -} - -/// Globals are initialized via the `const` operators or by referring to another import. -#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub enum GlobalInit { - /// An `i32.const`. - I32Const(i32), - /// An `i64.const`. - I64Const(i64), - /// An `f32.const`. - F32Const(u32), - /// An `f64.const`. - F64Const(u64), - /// A `vconst`. - V128Const(V128Imm), - /// A `global.get` of another global. - GetGlobal(GlobalIndex), - /// A `ref.null`. - RefNullConst, - /// A `ref.func `. - RefFunc(FuncIndex), - ///< The global is imported from, and thus initialized by, a different module. - Import, -} - -impl Global { - /// Creates a new `Global` type from wasmparser's representation. - pub fn new(ty: wasmparser::GlobalType, initializer: GlobalInit) -> WasmResult { - Ok(Global { - wasm_ty: ty.content_type.try_into()?, - mutability: ty.mutable, - initializer, - }) - } -} - -/// WebAssembly table. -#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct Table { - /// The table elements' Wasm type. - pub wasm_ty: WasmType, - /// The minimum number of elements in the table. - pub minimum: u32, - /// The maximum number of elements in the table. - pub maximum: Option, -} - -impl TryFrom for Table { - type Error = WasmError; - - fn try_from(ty: wasmparser::TableType) -> WasmResult { - Ok(Table { - wasm_ty: ty.element_type.try_into()?, - minimum: ty.initial, - maximum: ty.maximum, - }) - } -} - /// WebAssembly table element. Can be a function or a scalar type. #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] @@ -240,47 +20,6 @@ pub enum TableElementType { Func, } -/// WebAssembly linear memory. -#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct Memory { - /// The minimum number of pages in the memory. - pub minimum: u64, - /// The maximum number of pages in the memory. - pub maximum: Option, - /// Whether the memory may be shared between multiple threads. - pub shared: bool, - /// Whether or not this is a 64-bit memory - pub memory64: bool, -} - -impl From for Memory { - fn from(ty: wasmparser::MemoryType) -> Memory { - Memory { - minimum: ty.initial, - maximum: ty.maximum, - shared: ty.shared, - memory64: ty.memory64, - } - } -} - -/// WebAssembly event. -#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct Tag { - /// The event signature type. - pub ty: TypeIndex, -} - -impl From for Tag { - fn from(ty: wasmparser::TagType) -> Tag { - Tag { - ty: TypeIndex::from_u32(ty.type_index), - } - } -} - /// Helper function translating wasmparser types to Cranelift types when possible. pub fn type_to_type( ty: wasmparser::Type, diff --git a/crates/cranelift/Cargo.toml b/crates/cranelift/Cargo.toml index b520a5277a..aa5e855af5 100644 --- a/crates/cranelift/Cargo.toml +++ b/crates/cranelift/Cargo.toml @@ -18,11 +18,12 @@ cranelift-codegen = { path = "../../cranelift/codegen", version = "0.76.0" } cranelift-frontend = { path = "../../cranelift/frontend", version = "0.76.0" } cranelift-entity = { path = "../../cranelift/entity", version = "0.76.0" } cranelift-native = { path = '../../cranelift/native', version = '0.76.0' } -wasmtime-debug = { path = '../debug', version = '0.29.0' } wasmparser = "0.80.0" target-lexicon = "0.12" gimli = "0.25.0" object = { version = "0.26.0", default-features = false, features = ['write'] } +more-asserts = "0.2.1" +thiserror = "1.0.4" [features] all-arch = ["cranelift-codegen/all-arch"] diff --git a/crates/cranelift/src/compiler.rs b/crates/cranelift/src/compiler.rs index 5c960d506b..d9782fd89b 100644 --- a/crates/cranelift/src/compiler.rs +++ b/crates/cranelift/src/compiler.rs @@ -1,6 +1,9 @@ use crate::func_environ::{get_func_name, FuncEnvironment}; use crate::obj::{ObjectBuilder, ObjectBuilderTarget}; -use crate::{blank_sig, func_signature, indirect_signature, value_type, wasmtime_call_conv}; +use crate::{ + blank_sig, func_signature, indirect_signature, value_type, wasmtime_call_conv, + CompiledFunction, Relocation, RelocationTarget, +}; use anyhow::{Context as _, Result}; use cranelift_codegen::ir::{self, ExternalName, InstBuilder, MemFlags}; use cranelift_codegen::isa::TargetIsa; @@ -8,22 +11,22 @@ use cranelift_codegen::print_errors::pretty_error; use cranelift_codegen::settings; use cranelift_codegen::MachSrcLoc; use cranelift_codegen::{binemit, Context}; -use cranelift_entity::EntityRef; +use cranelift_entity::{EntityRef, PrimaryMap}; use cranelift_frontend::FunctionBuilder; use cranelift_wasm::{ DefinedFuncIndex, DefinedMemoryIndex, FuncIndex, FuncTranslator, MemoryIndex, SignatureIndex, WasmFuncType, }; +use std::any::Any; use std::cmp; use std::collections::{BTreeSet, HashMap}; use std::convert::TryFrom; use std::mem; use std::sync::Mutex; use wasmtime_environ::{ - CompileError, CompiledFunction, CompiledFunctions, FlagValue, FunctionAddressMap, - FunctionBodyData, InstructionAddressMap, Module, ModuleMemoryOffset, ModuleTranslation, - Relocation, RelocationTarget, StackMapInformation, TrapInformation, Tunables, TypeTables, - VMOffsets, + CompileError, FilePos, FlagValue, FunctionAddressMap, FunctionBodyData, FunctionInfo, + InstructionAddressMap, Module, ModuleMemoryOffset, ModuleTranslation, StackMapInformation, + TrapCode, TrapInformation, Tunables, TypeTables, VMOffsets, }; /// A compiler that compiles a WebAssembly module with Compiler, translating @@ -62,8 +65,8 @@ impl Compiler { let offset = data.original_position(); let len = data.bytes_remaining(); assert!((offset + len) <= u32::max_value() as usize); - let start_srcloc = ir::SourceLoc::new(offset as u32); - let end_srcloc = ir::SourceLoc::new((offset + len) as u32); + let start_srcloc = FilePos::new(offset as u32); + let end_srcloc = FilePos::new((offset + len) as u32); let instructions = if let Some(ref mcr) = &context.mach_compile_result { // New-style backend: we have a `MachCompileResult` that will give us `MachSrcLoc` mapping @@ -109,7 +112,7 @@ impl wasmtime_environ::Compiler for Compiler { mut input: FunctionBodyData<'_>, tunables: &Tunables, types: &TypeTables, - ) -> Result { + ) -> Result, CompileError> { let isa = &*self.isa; let module = &translation.module; let func_index = module.func_index(func_index); @@ -196,27 +199,33 @@ impl wasmtime_environ::Compiler for Compiler { None }; - Ok(CompiledFunction { + Ok(Box::new(CompiledFunction { body: code_buf, jt_offsets: context.func.jt_offsets, relocations: reloc_sink.func_relocs, - address_map: address_transform, value_labels_ranges: ranges.unwrap_or(Default::default()), stack_slots: context.func.stack_slots, - traps: trap_sink.traps, unwind_info, - stack_maps: stack_map_sink.finish(), - }) + info: FunctionInfo { + address_map: address_transform, + traps: trap_sink.traps, + stack_maps: stack_map_sink.finish(), + }, + })) } fn emit_obj( &self, translation: &ModuleTranslation, types: &TypeTables, - funcs: &CompiledFunctions, + funcs: PrimaryMap>, emit_dwarf: bool, - ) -> Result> { + ) -> Result<(Vec, PrimaryMap)> { const CODE_SECTION_ALIGNMENT: u64 = 0x1000; + let funcs: crate::CompiledFunctions = funcs + .into_iter() + .map(|(_i, f)| *f.downcast().unwrap()) + .collect(); // Build trampolines for every signature that can be used by this module. let signatures = translation @@ -265,17 +274,20 @@ impl wasmtime_environ::Compiler for Compiler { } else { ModuleMemoryOffset::None }; - let dwarf_sections = wasmtime_debug::emit_dwarf( + let dwarf_sections = crate::debug::emit_dwarf( &*self.isa, &translation.debuginfo, - funcs, + &funcs, &memory_offset, ) .with_context(|| "failed to emit DWARF debug information")?; builder.dwarf_sections(&dwarf_sections)?; } - Ok(builder.finish(&*self.isa)?) + Ok(( + builder.finish(&*self.isa)?, + funcs.into_iter().map(|(_, f)| f.info).collect(), + )) } fn emit_trampoline_obj(&self, ty: &WasmFuncType, host_fn: usize) -> Result> { @@ -507,11 +519,9 @@ impl Compiler { jt_offsets: context.func.jt_offsets, unwind_info, relocations: reloc_sink.relocs, - stack_maps: Default::default(), stack_slots: Default::default(), - traps: Default::default(), value_labels_ranges: Default::default(), - address_map: Default::default(), + info: Default::default(), }) } } @@ -540,14 +550,14 @@ fn collect_address_maps( // Push an entry for the previous source item. ret.push(InstructionAddressMap { - srcloc: cur_loc, + srcloc: cvt(cur_loc), code_offset: cur_offset, }); // And push a "dummy" entry if necessary to cover the span of ranges, // if any, between the previous source offset and this one. if cur_offset + cur_len != offset { ret.push(InstructionAddressMap { - srcloc: ir::SourceLoc::default(), + srcloc: FilePos::default(), code_offset: cur_offset + cur_len, }); } @@ -558,17 +568,25 @@ fn collect_address_maps( cur_len = len; } ret.push(InstructionAddressMap { - srcloc: cur_loc, + srcloc: cvt(cur_loc), code_offset: cur_offset, }); if cur_offset + cur_len != code_size { ret.push(InstructionAddressMap { - srcloc: ir::SourceLoc::default(), + srcloc: FilePos::default(), code_offset: cur_offset + cur_len, }); } return ret; + + fn cvt(loc: ir::SourceLoc) -> FilePos { + if loc.is_default() { + FilePos::default() + } else { + FilePos::new(loc.bits()) + } + } } /// Implementation of a relocation sink that just saves all the information for later @@ -658,7 +676,22 @@ impl binemit::TrapSink for TrapSink { ) { self.traps.push(TrapInformation { code_offset, - trap_code, + trap_code: match trap_code { + ir::TrapCode::StackOverflow => TrapCode::StackOverflow, + ir::TrapCode::HeapOutOfBounds => TrapCode::HeapOutOfBounds, + ir::TrapCode::HeapMisaligned => TrapCode::HeapMisaligned, + ir::TrapCode::TableOutOfBounds => TrapCode::TableOutOfBounds, + ir::TrapCode::IndirectCallToNull => TrapCode::IndirectCallToNull, + ir::TrapCode::BadSignature => TrapCode::BadSignature, + ir::TrapCode::IntegerOverflow => TrapCode::IntegerOverflow, + ir::TrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero, + ir::TrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger, + ir::TrapCode::UnreachableCodeReached => TrapCode::UnreachableCodeReached, + ir::TrapCode::Interrupt => TrapCode::Interrupt, + + // these should never be emitted by wasmtime-cranelift + ir::TrapCode::User(_) => unreachable!(), + }, }); } } @@ -670,6 +703,13 @@ struct StackMapSink { impl binemit::StackMapSink for StackMapSink { fn add_stack_map(&mut self, code_offset: binemit::CodeOffset, stack_map: binemit::StackMap) { + // This is converting from Cranelift's representation of a stack map to + // Wasmtime's representation. They happen to align today but that may + // not always be true in the future. + let stack_map = wasmtime_environ::StackMap::new( + stack_map.mapped_words(), + stack_map.as_slice().iter().map(|a| a.0), + ); self.infos.push(StackMapInformation { code_offset, stack_map, diff --git a/crates/debug/src/lib.rs b/crates/cranelift/src/debug.rs similarity index 61% rename from crates/debug/src/lib.rs rename to crates/cranelift/src/debug.rs index 954674f3c0..5ac0caacc2 100644 --- a/crates/debug/src/lib.rs +++ b/crates/cranelift/src/debug.rs @@ -2,7 +2,7 @@ #![allow(clippy::cast_ptr_alignment)] -pub use crate::write_debuginfo::{emit_dwarf, DwarfSection, DwarfSectionRelocTarget}; +pub use write_debuginfo::{emit_dwarf, DwarfSection, DwarfSectionRelocTarget}; mod gc; mod transform; diff --git a/crates/debug/src/gc.rs b/crates/cranelift/src/debug/gc.rs similarity index 99% rename from crates/debug/src/gc.rs rename to crates/cranelift/src/debug/gc.rs index 0763119aee..ad8c25d8b8 100644 --- a/crates/debug/src/gc.rs +++ b/crates/cranelift/src/debug/gc.rs @@ -1,4 +1,4 @@ -use crate::transform::AddressTransform; +use crate::debug::transform::AddressTransform; use gimli::constants; use gimli::read; use gimli::{Reader, UnitSectionOffset}; diff --git a/crates/debug/src/transform/address_transform.rs b/crates/cranelift/src/debug/transform/address_transform.rs similarity index 94% rename from crates/debug/src/transform/address_transform.rs rename to crates/cranelift/src/debug/transform/address_transform.rs index 0277e6455e..4f3ee2fe04 100644 --- a/crates/debug/src/transform/address_transform.rs +++ b/crates/cranelift/src/debug/transform/address_transform.rs @@ -1,11 +1,11 @@ -use cranelift_codegen::ir::SourceLoc; +use crate::CompiledFunctions; use gimli::write; use more_asserts::assert_le; use std::collections::BTreeMap; use std::iter::FromIterator; -use wasmtime_environ::entity::{EntityRef, PrimaryMap}; -use wasmtime_environ::wasm::DefinedFuncIndex; -use wasmtime_environ::{CompiledFunctions, FunctionAddressMap, WasmFileInfo}; +use wasmtime_environ::{ + DefinedFuncIndex, EntityRef, FilePos, FunctionAddressMap, PrimaryMap, WasmFileInfo, +}; pub type GeneratedAddress = usize; pub type WasmAddress = u64; @@ -78,16 +78,21 @@ pub struct AddressTransform { } /// Returns a wasm bytecode offset in the code section from SourceLoc. -pub fn get_wasm_code_offset(loc: SourceLoc, code_section_offset: u64) -> WasmAddress { +fn get_wasm_code_offset(loc: FilePos, code_section_offset: u64) -> WasmAddress { // Code section size <= 4GB, allow wrapped SourceLoc to recover the overflow. - loc.bits().wrapping_sub(code_section_offset as u32) as WasmAddress + loc.file_offset() + .unwrap() + .wrapping_sub(code_section_offset as u32) as WasmAddress } fn build_function_lookup( ft: &FunctionAddressMap, code_section_offset: u64, ) -> (WasmAddress, WasmAddress, FuncLookup) { - assert_le!(code_section_offset, ft.start_srcloc.bits() as u64); + assert_le!( + code_section_offset, + ft.start_srcloc.file_offset().unwrap().into() + ); let fn_start = get_wasm_code_offset(ft.start_srcloc, code_section_offset); let fn_end = get_wasm_code_offset(ft.end_srcloc, code_section_offset); assert_le!(fn_start, fn_end); @@ -103,7 +108,7 @@ fn build_function_lookup( let mut current_range = Vec::new(); let mut last_gen_inst_empty = false; for (i, t) in ft.instructions.iter().enumerate() { - if t.srcloc.is_default() { + if t.srcloc.file_offset().is_none() { continue; } @@ -194,10 +199,10 @@ fn build_function_addr_map( ) -> PrimaryMap { let mut map = PrimaryMap::new(); for (_, f) in funcs { - let ft = &f.address_map; + let ft = &f.info.address_map; let mut fn_map = Vec::new(); for t in ft.instructions.iter() { - if t.srcloc.is_default() { + if t.srcloc.file_offset().is_none() { continue; } let offset = get_wasm_code_offset(t.srcloc, code_section_offset); @@ -455,7 +460,7 @@ impl AddressTransform { let mut func = BTreeMap::new(); for (i, f) in funcs { - let ft = &f.address_map; + let ft = &f.info.address_map; let (fn_start, fn_end, lookup) = build_function_lookup(ft, code_section_offset); func.insert( @@ -606,21 +611,22 @@ impl AddressTransform { #[cfg(test)] mod tests { use super::{build_function_lookup, get_wasm_code_offset, AddressTransform}; + use crate::{CompiledFunction, CompiledFunctions}; + use cranelift_entity::PrimaryMap; use gimli::write::Address; use std::iter::FromIterator; use std::mem; - use wasmtime_environ::entity::PrimaryMap; - use wasmtime_environ::ir::SourceLoc; - use wasmtime_environ::{CompiledFunction, WasmFileInfo}; - use wasmtime_environ::{CompiledFunctions, FunctionAddressMap, InstructionAddressMap}; + use wasmtime_environ::{ + FilePos, FunctionAddressMap, FunctionInfo, InstructionAddressMap, WasmFileInfo, + }; #[test] fn test_get_wasm_code_offset() { - let offset = get_wasm_code_offset(SourceLoc::new(3), 1); + let offset = get_wasm_code_offset(FilePos::new(3), 1); assert_eq!(2, offset); - let offset = get_wasm_code_offset(SourceLoc::new(16), 0xF000_0000); + let offset = get_wasm_code_offset(FilePos::new(16), 0xF000_0000); assert_eq!(0x1000_0010, offset); - let offset = get_wasm_code_offset(SourceLoc::new(1), 0x20_8000_0000); + let offset = get_wasm_code_offset(FilePos::new(1), 0x20_8000_0000); assert_eq!(0x8000_0001, offset); } @@ -628,25 +634,25 @@ mod tests { FunctionAddressMap { instructions: vec![ InstructionAddressMap { - srcloc: SourceLoc::new(wasm_offset + 2), + srcloc: FilePos::new(wasm_offset + 2), code_offset: 5, }, InstructionAddressMap { - srcloc: SourceLoc::default(), + srcloc: FilePos::default(), code_offset: 8, }, InstructionAddressMap { - srcloc: SourceLoc::new(wasm_offset + 7), + srcloc: FilePos::new(wasm_offset + 7), code_offset: 15, }, InstructionAddressMap { - srcloc: SourceLoc::default(), + srcloc: FilePos::default(), code_offset: 23, }, ] .into(), - start_srcloc: SourceLoc::new(wasm_offset), - end_srcloc: SourceLoc::new(wasm_offset + 10), + start_srcloc: FilePos::new(wasm_offset), + end_srcloc: FilePos::new(wasm_offset + 10), body_offset: 0, body_len: 30, } @@ -654,7 +660,10 @@ mod tests { fn create_simple_module(address_map: FunctionAddressMap) -> CompiledFunctions { PrimaryMap::from_iter(vec![CompiledFunction { - address_map, + info: FunctionInfo { + address_map, + ..Default::default() + }, ..Default::default() }]) } @@ -691,11 +700,11 @@ mod tests { // append instruction with same srcloc as input.instructions[0] let mut list = Vec::from(mem::take(&mut input.instructions)); list.push(InstructionAddressMap { - srcloc: SourceLoc::new(11 + 2), + srcloc: FilePos::new(11 + 2), code_offset: 23, }); list.push(InstructionAddressMap { - srcloc: SourceLoc::default(), + srcloc: FilePos::default(), code_offset: 26, }); input.instructions = list.into(); diff --git a/crates/debug/src/transform/attr.rs b/crates/cranelift/src/debug/transform/attr.rs similarity index 100% rename from crates/debug/src/transform/attr.rs rename to crates/cranelift/src/debug/transform/attr.rs diff --git a/crates/debug/src/transform/expression.rs b/crates/cranelift/src/debug/transform/expression.rs similarity index 96% rename from crates/debug/src/transform/expression.rs rename to crates/cranelift/src/debug/transform/expression.rs index e26e3571b2..2ae93352b3 100644 --- a/crates/debug/src/transform/expression.rs +++ b/crates/cranelift/src/debug/transform/expression.rs @@ -3,15 +3,14 @@ use anyhow::{Context, Error, Result}; use cranelift_codegen::ir::{LabelValueLoc, StackSlots, ValueLabel, ValueLoc}; use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::ValueLabelsRanges; +use cranelift_wasm::get_vmctx_value_label; use gimli::{self, write, Expression, Operation, Reader, ReaderOffset, X86_64}; use more_asserts::{assert_le, assert_lt}; use std::cmp::PartialEq; use std::collections::{HashMap, HashSet}; use std::hash::{Hash, Hasher}; use std::rc::Rc; -use wasmtime_environ::entity::EntityRef; -use wasmtime_environ::wasm::{get_vmctx_value_label, DefinedFuncIndex}; -use wasmtime_environ::ModuleMemoryOffset; +use wasmtime_environ::{DefinedFuncIndex, EntityRef, ModuleMemoryOffset}; #[derive(Debug)] pub struct FunctionFrameInfo<'a> { @@ -847,8 +846,9 @@ mod tests { compile_expression, AddressTransform, CompiledExpression, CompiledExpressionPart, FunctionFrameInfo, JumpTargetMarker, ValueLabel, ValueLabelsRanges, }; + use crate::CompiledFunction; use gimli::{self, constants, Encoding, EndianSlice, Expression, RunTimeEndian}; - use wasmtime_environ::CompiledFunction; + use wasmtime_environ::{FilePos, FunctionInfo}; macro_rules! dw_op { (DW_OP_WASM_location) => { @@ -906,7 +906,7 @@ mod tests { #[test] fn test_debug_parse_expressions() { - use wasmtime_environ::entity::EntityRef; + use cranelift_entity::EntityRef; let (val1, val3, val20) = (ValueLabel::new(1), ValueLabel::new(3), ValueLabel::new(20)); @@ -1176,37 +1176,39 @@ mod tests { } fn create_mock_address_transform() -> AddressTransform { - use wasmtime_environ::entity::PrimaryMap; - use wasmtime_environ::ir::SourceLoc; + use cranelift_entity::PrimaryMap; use wasmtime_environ::WasmFileInfo; use wasmtime_environ::{FunctionAddressMap, InstructionAddressMap}; let mut module_map = PrimaryMap::new(); let code_section_offset: u32 = 100; module_map.push(CompiledFunction { - address_map: FunctionAddressMap { - instructions: vec![ - InstructionAddressMap { - srcloc: SourceLoc::new(code_section_offset + 12), - code_offset: 5, - }, - InstructionAddressMap { - srcloc: SourceLoc::default(), - code_offset: 8, - }, - InstructionAddressMap { - srcloc: SourceLoc::new(code_section_offset + 17), - code_offset: 15, - }, - InstructionAddressMap { - srcloc: SourceLoc::default(), - code_offset: 23, - }, - ] - .into(), - start_srcloc: SourceLoc::new(code_section_offset + 10), - end_srcloc: SourceLoc::new(code_section_offset + 20), - body_offset: 0, - body_len: 30, + info: FunctionInfo { + address_map: FunctionAddressMap { + instructions: vec![ + InstructionAddressMap { + srcloc: FilePos::new(code_section_offset + 12), + code_offset: 5, + }, + InstructionAddressMap { + srcloc: FilePos::default(), + code_offset: 8, + }, + InstructionAddressMap { + srcloc: FilePos::new(code_section_offset + 17), + code_offset: 15, + }, + InstructionAddressMap { + srcloc: FilePos::default(), + code_offset: 23, + }, + ] + .into(), + start_srcloc: FilePos::new(code_section_offset + 10), + end_srcloc: FilePos::new(code_section_offset + 20), + body_offset: 0, + body_len: 30, + }, + ..Default::default() }, ..Default::default() }); @@ -1222,8 +1224,8 @@ mod tests { fn create_mock_value_ranges() -> (ValueLabelsRanges, (ValueLabel, ValueLabel, ValueLabel)) { use cranelift_codegen::ir::{LabelValueLoc, ValueLoc}; use cranelift_codegen::ValueLocRange; + use cranelift_entity::EntityRef; use std::collections::HashMap; - use wasmtime_environ::entity::EntityRef; let mut value_ranges = HashMap::new(); let value_0 = ValueLabel::new(0); let value_1 = ValueLabel::new(1); @@ -1266,9 +1268,7 @@ mod tests { fn test_debug_value_range_builder() { use super::ValueLabelRangesBuilder; use cranelift_codegen::ir::StackSlots; - use wasmtime_environ::entity::EntityRef; - use wasmtime_environ::wasm::DefinedFuncIndex; - use wasmtime_environ::ModuleMemoryOffset; + use wasmtime_environ::{DefinedFuncIndex, EntityRef, ModuleMemoryOffset}; let addr_tr = create_mock_address_transform(); let stack_slots = StackSlots::new(); diff --git a/crates/debug/src/transform/line_program.rs b/crates/cranelift/src/debug/transform/line_program.rs similarity index 99% rename from crates/debug/src/transform/line_program.rs rename to crates/cranelift/src/debug/transform/line_program.rs index a9b309bfe5..166c0c3dcf 100644 --- a/crates/debug/src/transform/line_program.rs +++ b/crates/cranelift/src/debug/transform/line_program.rs @@ -7,8 +7,7 @@ use gimli::{ DebuggingInformationEntry, LineEncoding, Unit, }; use more_asserts::assert_le; -use wasmtime_environ::entity::EntityRef; -use wasmtime_environ::wasm::DefinedFuncIndex; +use wasmtime_environ::{DefinedFuncIndex, EntityRef}; #[derive(Debug)] enum SavedLineProgramRow { diff --git a/crates/debug/src/transform/mod.rs b/crates/cranelift/src/debug/transform/mod.rs similarity index 96% rename from crates/debug/src/transform/mod.rs rename to crates/cranelift/src/debug/transform/mod.rs index a29a93823c..74b3283729 100644 --- a/crates/debug/src/transform/mod.rs +++ b/crates/cranelift/src/debug/transform/mod.rs @@ -1,7 +1,8 @@ use self::refs::DebugInfoRefsMap; use self::simulate::generate_simulated_dwarf; use self::unit::clone_unit; -use crate::gc::build_dependencies; +use crate::debug::gc::build_dependencies; +use crate::CompiledFunctions; use anyhow::Error; use cranelift_codegen::isa::TargetIsa; use gimli::{ @@ -10,7 +11,7 @@ use gimli::{ }; use std::collections::HashSet; use thiserror::Error; -use wasmtime_environ::{CompiledFunctions, DebugInfoData, ModuleMemoryOffset}; +use wasmtime_environ::{DebugInfoData, ModuleMemoryOffset}; pub use address_transform::AddressTransform; diff --git a/crates/debug/src/transform/range_info_builder.rs b/crates/cranelift/src/debug/transform/range_info_builder.rs similarity index 98% rename from crates/debug/src/transform/range_info_builder.rs rename to crates/cranelift/src/debug/transform/range_info_builder.rs index 13176b60b4..c412f32c71 100644 --- a/crates/debug/src/transform/range_info_builder.rs +++ b/crates/cranelift/src/debug/transform/range_info_builder.rs @@ -3,8 +3,7 @@ use super::{DebugInputContext, Reader}; use anyhow::Error; use gimli::{write, AttributeValue, DebuggingInformationEntry, RangeListsOffset, Unit}; use more_asserts::assert_lt; -use wasmtime_environ::entity::EntityRef; -use wasmtime_environ::wasm::DefinedFuncIndex; +use wasmtime_environ::{DefinedFuncIndex, EntityRef}; pub(crate) enum RangeInfoBuilder { Undefined, diff --git a/crates/debug/src/transform/refs.rs b/crates/cranelift/src/debug/transform/refs.rs similarity index 100% rename from crates/debug/src/transform/refs.rs rename to crates/cranelift/src/debug/transform/refs.rs diff --git a/crates/debug/src/transform/simulate.rs b/crates/cranelift/src/debug/transform/simulate.rs similarity index 98% rename from crates/debug/src/transform/simulate.rs rename to crates/cranelift/src/debug/transform/simulate.rs index e0af268d5c..cfe2649f8c 100644 --- a/crates/debug/src/transform/simulate.rs +++ b/crates/cranelift/src/debug/transform/simulate.rs @@ -1,18 +1,18 @@ use super::expression::{CompiledExpression, FunctionFrameInfo}; use super::utils::{add_internal_types, append_vmctx_info, get_function_frame_info}; use super::AddressTransform; +use crate::CompiledFunctions; use anyhow::{Context, Error}; use cranelift_codegen::isa::TargetIsa; +use cranelift_wasm::get_vmctx_value_label; use gimli::write; use gimli::{self, LineEncoding}; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use wasmparser::Type as WasmType; -use wasmtime_environ::entity::EntityRef; -use wasmtime_environ::wasm::{get_vmctx_value_label, DefinedFuncIndex}; use wasmtime_environ::{ - CompiledFunctions, DebugInfoData, FunctionMetadata, ModuleMemoryOffset, WasmFileInfo, + DebugInfoData, DefinedFuncIndex, EntityRef, FunctionMetadata, ModuleMemoryOffset, WasmFileInfo, }; const PRODUCER_NAME: &str = "wasmtime"; diff --git a/crates/debug/src/transform/unit.rs b/crates/cranelift/src/debug/transform/unit.rs similarity index 99% rename from crates/debug/src/transform/unit.rs rename to crates/cranelift/src/debug/transform/unit.rs index ae7ce94f49..c0c3e09bd6 100644 --- a/crates/debug/src/transform/unit.rs +++ b/crates/cranelift/src/debug/transform/unit.rs @@ -6,14 +6,14 @@ use super::range_info_builder::RangeInfoBuilder; use super::refs::{PendingDebugInfoRefs, PendingUnitRefs, UnitRefsMap}; use super::utils::{add_internal_types, append_vmctx_info, get_function_frame_info}; use super::{DebugInputContext, Reader, TransformError}; +use crate::CompiledFunctions; use anyhow::{Context, Error}; use cranelift_codegen::ir::Endianness; use cranelift_codegen::isa::TargetIsa; use gimli::write; use gimli::{AttributeValue, DebuggingInformationEntry, Unit}; use std::collections::HashSet; -use wasmtime_environ::wasm::DefinedFuncIndex; -use wasmtime_environ::{CompiledFunctions, ModuleMemoryOffset}; +use wasmtime_environ::{DefinedFuncIndex, ModuleMemoryOffset}; struct InheritedAttr { stack: Vec<(usize, T)>, diff --git a/crates/debug/src/transform/utils.rs b/crates/cranelift/src/debug/transform/utils.rs similarity index 98% rename from crates/debug/src/transform/utils.rs rename to crates/cranelift/src/debug/transform/utils.rs index 740586db4f..a89ee74306 100644 --- a/crates/debug/src/transform/utils.rs +++ b/crates/cranelift/src/debug/transform/utils.rs @@ -1,10 +1,10 @@ use super::address_transform::AddressTransform; use super::expression::{CompiledExpression, FunctionFrameInfo}; +use crate::CompiledFunctions; use anyhow::Error; use cranelift_codegen::isa::TargetIsa; use gimli::write; -use wasmtime_environ::wasm::DefinedFuncIndex; -use wasmtime_environ::{CompiledFunctions, ModuleMemoryOffset}; +use wasmtime_environ::{DefinedFuncIndex, ModuleMemoryOffset}; /// Adds internal Wasm utility types DIEs such as WebAssemblyPtr and /// WasmtimeVMContext. diff --git a/crates/debug/src/write_debuginfo.rs b/crates/cranelift/src/debug/write_debuginfo.rs similarity index 96% rename from crates/debug/src/write_debuginfo.rs rename to crates/cranelift/src/debug/write_debuginfo.rs index ff47471df4..c45271d6ea 100644 --- a/crates/debug/src/write_debuginfo.rs +++ b/crates/cranelift/src/debug/write_debuginfo.rs @@ -1,10 +1,11 @@ -pub use crate::transform::transform_dwarf; +pub use crate::debug::transform::transform_dwarf; +use crate::CompiledFunctions; use cranelift_codegen::ir::Endianness; use cranelift_codegen::isa::{unwind::UnwindInfo, TargetIsa}; +use cranelift_entity::EntityRef; use gimli::write::{Address, Dwarf, EndianVec, FrameTable, Result, Sections, Writer}; use gimli::{RunTimeEndian, SectionId}; -use wasmtime_environ::entity::EntityRef; -use wasmtime_environ::{CompiledFunctions, DebugInfoData, ModuleMemoryOffset}; +use wasmtime_environ::{DebugInfoData, ModuleMemoryOffset}; #[allow(missing_docs)] pub struct DwarfSection { diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs index 209a537853..177651ac5d 100644 --- a/crates/cranelift/src/func_environ.rs +++ b/crates/cranelift/src/func_environ.rs @@ -617,7 +617,7 @@ impl<'module_environment> TargetEnvironment for FuncEnvironment<'module_environm } fn reference_type(&self, ty: WasmType) -> ir::Type { - wasmtime_environ::reference_type(ty, self.pointer_type()) + crate::reference_type(ty, self.pointer_type()) } } @@ -671,7 +671,10 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m let bound_gv = func.create_global_value(ir::GlobalValueData::Load { base: ptr, offset: Offset32::new(current_elements_offset), - global_type: self.offsets.type_of_vmtable_definition_current_elements(), + global_type: ir::Type::int( + u16::from(self.offsets.size_of_vmtable_definition_current_elements()) * 8, + ) + .unwrap(), readonly: false, }); diff --git a/crates/cranelift/src/lib.rs b/crates/cranelift/src/lib.rs index 56eadf02e8..8792268f67 100644 --- a/crates/cranelift/src/lib.rs +++ b/crates/cranelift/src/lib.rs @@ -88,19 +88,67 @@ // also need to actually catch stack overflow, so for now 32k is chosen and it's // assume no valid stack pointer will ever be `usize::max_value() - 32k`. +use cranelift_codegen::binemit; use cranelift_codegen::ir; -use cranelift_codegen::isa::{CallConv, TargetIsa}; -use cranelift_wasm::{FuncIndex, WasmFuncType, WasmType}; +use cranelift_codegen::isa::{unwind::UnwindInfo, CallConv, TargetIsa}; +use cranelift_entity::PrimaryMap; +use cranelift_wasm::{DefinedFuncIndex, FuncIndex, WasmFuncType, WasmType}; use target_lexicon::CallingConvention; -use wasmtime_environ::{Module, TypeTables}; +use wasmtime_environ::{FunctionInfo, Module, TypeTables}; pub use builder::builder; mod builder; mod compiler; +mod debug; mod func_environ; mod obj; +type CompiledFunctions = PrimaryMap; + +/// Compiled function: machine code body, jump table offsets, and unwind information. +#[derive(Default)] +pub struct CompiledFunction { + /// The machine code for this function. + body: Vec, + + /// The jump tables offsets (in the body). + jt_offsets: ir::JumpTableOffsets, + + /// The unwind information. + unwind_info: Option, + + relocations: Vec, + value_labels_ranges: cranelift_codegen::ValueLabelsRanges, + stack_slots: ir::StackSlots, + + info: FunctionInfo, +} + +/// A record of a relocation to perform. +#[derive(Debug, Clone, PartialEq, Eq)] +struct Relocation { + /// The relocation code. + reloc: binemit::Reloc, + /// Relocation target. + reloc_target: RelocationTarget, + /// The offset where to apply the relocation. + offset: binemit::CodeOffset, + /// The addend to add to the relocation value. + addend: binemit::Addend, +} + +/// Destination function. Can be either user function or some special one, like `memory.grow`. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum RelocationTarget { + /// The user function index. + UserFunc(FuncIndex), + /// A compiler-generated libcall. + LibCall(ir::LibCall), + /// Jump table index. + JumpTable(FuncIndex, ir::JumpTable), +} + /// Creates a new cranelift `Signature` with no wasm params/results for the /// given calling convention. /// @@ -148,9 +196,7 @@ fn value_type(isa: &dyn TargetIsa, ty: WasmType) -> ir::types::Type { WasmType::F32 => ir::types::F32, WasmType::F64 => ir::types::F64, WasmType::V128 => ir::types::I8X16, - WasmType::FuncRef | WasmType::ExternRef => { - wasmtime_environ::reference_type(ty, isa.pointer_type()) - } + WasmType::FuncRef | WasmType::ExternRef => reference_type(ty, isa.pointer_type()), WasmType::ExnRef => unimplemented!(), } } @@ -199,3 +245,16 @@ fn func_signature( ); return sig; } + +/// Returns the reference type to use for the provided wasm type. +fn reference_type(wasm_ty: cranelift_wasm::WasmType, pointer_type: ir::Type) -> ir::Type { + match wasm_ty { + cranelift_wasm::WasmType::FuncRef => pointer_type, + cranelift_wasm::WasmType::ExternRef => match pointer_type { + ir::types::I32 => ir::types::R32, + ir::types::I64 => ir::types::R64, + _ => panic!("unsupported pointer type"), + }, + _ => panic!("unsupported Wasm reference type"), + } +} diff --git a/crates/cranelift/src/obj.rs b/crates/cranelift/src/obj.rs index 18fb0f4101..fe39ffe4a9 100644 --- a/crates/cranelift/src/obj.rs +++ b/crates/cranelift/src/obj.rs @@ -13,8 +13,8 @@ //! function body, the imported wasm function do not. The trampolines symbol //! names have format "_trampoline_N", where N is `SignatureIndex`. -#![allow(missing_docs)] - +use crate::debug::{DwarfSection, DwarfSectionRelocTarget}; +use crate::{CompiledFunction, Relocation, RelocationTarget}; use anyhow::Result; use cranelift_codegen::binemit::Reloc; use cranelift_codegen::ir::{JumpTableOffsets, LibCall}; @@ -34,11 +34,10 @@ use object::{ }; use std::collections::HashMap; use std::convert::TryFrom; -use wasmtime_debug::{DwarfSection, DwarfSectionRelocTarget}; -use wasmtime_environ::entity::{EntityRef, PrimaryMap}; use wasmtime_environ::obj; -use wasmtime_environ::wasm::{DefinedFuncIndex, FuncIndex, SignatureIndex}; -use wasmtime_environ::{CompiledFunction, Module, Relocation, RelocationTarget}; +use wasmtime_environ::{ + DefinedFuncIndex, EntityRef, FuncIndex, Module, PrimaryMap, SignatureIndex, +}; fn to_object_architecture( arch: target_lexicon::Architecture, diff --git a/crates/debug/.gitignore b/crates/debug/.gitignore deleted file mode 100644 index 4308d82204..0000000000 --- a/crates/debug/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -target/ -**/*.rs.bk -Cargo.lock diff --git a/crates/debug/Cargo.toml b/crates/debug/Cargo.toml deleted file mode 100644 index 5a29bcb2c3..0000000000 --- a/crates/debug/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "wasmtime-debug" -version = "0.29.0" -authors = ["The Wasmtime Project Developers"] -description = "Debug utils for WebAsssembly code in Cranelift" -license = "Apache-2.0 WITH LLVM-exception" -repository = "https://github.com/bytecodealliance/wasmtime" -documentation = "https://docs.rs/wasmtime-debug/" -categories = ["wasm"] -keywords = ["webassembly", "wasm", "debuginfo"] -edition = "2018" - -[dependencies] -gimli = "0.25.0" -wasmparser = "0.80" -object = { version = "0.26.0", default-features = false, features = ["read_core", "elf", "write"] } -wasmtime-environ = { path = "../environ", version = "0.29.0" } -target-lexicon = { version = "0.12.0", default-features = false } -anyhow = "1.0" -thiserror = "1.0.4" -more-asserts = "0.2.1" -cranelift-codegen = { path = "../../cranelift/codegen", version = "0.76.0" } - -[badges] -maintenance = { status = "actively-developed" } diff --git a/crates/debug/LICENSE b/crates/debug/LICENSE deleted file mode 100644 index f9d81955f4..0000000000 --- a/crates/debug/LICENSE +++ /dev/null @@ -1,220 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - ---- LLVM Exceptions to the Apache 2.0 License ---- - -As an exception, if, as a result of your compiling your source code, portions -of this Software are embedded into an Object form of such source code, you -may redistribute such embedded portions in such Object form without complying -with the conditions of Sections 4(a), 4(b) and 4(d) of the License. - -In addition, if you combine or link compiled forms of this Software with -software that is licensed under the GPLv2 ("Combined Software") and if a -court of competent jurisdiction determines that the patent provision (Section -3), the indemnity provision (Section 9) or other Section of the License -conflicts with the conditions of the GPLv2, you may retroactively and -prospectively choose to deem waived or otherwise exclude such Section(s) of -the License, but only in their entirety and only with respect to the Combined -Software. - diff --git a/crates/environ/Cargo.toml b/crates/environ/Cargo.toml index b8a5e9869b..375b73f467 100644 --- a/crates/environ/Cargo.toml +++ b/crates/environ/Cargo.toml @@ -12,9 +12,8 @@ edition = "2018" [dependencies] anyhow = "1.0" -cranelift-codegen = { path = "../../cranelift/codegen", version = "0.76.0", features = ["enable-serde"] } -cranelift-entity = { path = "../../cranelift/entity", version = "0.76.0", features = ["enable-serde"] } -cranelift-wasm = { path = "../../cranelift/wasm", version = "0.76.0", features = ["enable-serde"] } +cranelift-entity = { path = "../../cranelift/entity", version = "0.76.0" } +wasmtime-types = { path = "../types", version = "0.29.0" } wasmparser = "0.80" indexmap = { version = "1.0.2", features = ["serde-1"] } thiserror = "1.0.4" diff --git a/crates/environ/src/address_map.rs b/crates/environ/src/address_map.rs index 972ab0468a..23dfcd826c 100644 --- a/crates/environ/src/address_map.rs +++ b/crates/environ/src/address_map.rs @@ -1,14 +1,14 @@ //! Data structures to provide transformation of the source // addresses of a WebAssembly module into the native code. -use cranelift_codegen::ir; use serde::{Deserialize, Serialize}; /// Single source location to generated address mapping. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct InstructionAddressMap { - /// Where in the source this instruction comes from. - pub srcloc: ir::SourceLoc, + /// Where in the source wasm binary this instruction comes from, specified + /// in an offset of bytes from the front of the file. + pub srcloc: FilePos, /// Offset from the start of the function's compiled code to where this /// instruction is located, or the region where it starts. @@ -26,11 +26,13 @@ pub struct FunctionAddressMap { /// gap between it and the next item in the array. pub instructions: Box<[InstructionAddressMap]>, - /// Function start source location (normally declaration). - pub start_srcloc: ir::SourceLoc, + /// Function's initial offset in the source file, specified in bytes from + /// the front of the file. + pub start_srcloc: FilePos, - /// Function end source location. - pub end_srcloc: ir::SourceLoc, + /// Function's end offset in the source file, specified in bytes from + /// the front of the file. + pub end_srcloc: FilePos, /// Generated function body offset if applicable, otherwise 0. pub body_offset: usize, @@ -39,6 +41,40 @@ pub struct FunctionAddressMap { pub body_len: u32, } +/// A position within an original source file, +/// +/// This structure is used as a newtype wrapper around a 32-bit integer which +/// represents an offset within a file where a wasm instruction or function is +/// to be originally found. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct FilePos(u32); + +impl FilePos { + /// Create a new file position with the given offset. + pub fn new(pos: u32) -> FilePos { + assert!(pos != u32::MAX); + FilePos(pos) + } + + /// Returns the offset that this offset was created with. + /// + /// Note that the `Default` implementation will return `None` here, whereas + /// positions created with `FilePos::new` will return `Some`. + pub fn file_offset(self) -> Option { + if self.0 == u32::MAX { + None + } else { + Some(self.0) + } + } +} + +impl Default for FilePos { + fn default() -> FilePos { + FilePos(u32::MAX) + } +} + /// Memory definition offset in the VMContext structure. #[derive(Debug, Clone)] pub enum ModuleMemoryOffset { diff --git a/crates/environ/src/compilation.rs b/crates/environ/src/compilation.rs index 3211f9cc70..9037fedd3f 100644 --- a/crates/environ/src/compilation.rs +++ b/crates/environ/src/compilation.rs @@ -1,72 +1,79 @@ //! A `Compilation` contains the compiled function bodies for a WebAssembly //! module. -use crate::{FunctionAddressMap, FunctionBodyData, ModuleTranslation, Tunables, TypeTables}; +use crate::{ + DefinedFuncIndex, FunctionAddressMap, FunctionBodyData, ModuleTranslation, PrimaryMap, + StackMap, Tunables, TypeTables, WasmError, WasmFuncType, +}; use anyhow::Result; -use cranelift_codegen::{binemit, ir, isa::unwind::UnwindInfo}; -use cranelift_entity::PrimaryMap; -use cranelift_wasm::{DefinedFuncIndex, FuncIndex, WasmError, WasmFuncType}; use serde::{Deserialize, Serialize}; +use std::any::Any; use std::borrow::Cow; use std::collections::HashMap; use std::fmt; use thiserror::Error; +/// Information about a function, such as trap information, address map, +/// and stack maps. +#[derive(Serialize, Deserialize, Clone, Default)] #[allow(missing_docs)] -pub type CompiledFunctions = PrimaryMap; - -/// Compiled function: machine code body, jump table offsets, and unwind information. -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)] -#[allow(missing_docs)] -pub struct CompiledFunction { - /// The machine code for this function. - pub body: Vec, - - /// The jump tables offsets (in the body). - pub jt_offsets: ir::JumpTableOffsets, - - /// The unwind information. - pub unwind_info: Option, - - pub relocations: Vec, - pub address_map: FunctionAddressMap, - pub value_labels_ranges: cranelift_codegen::ValueLabelsRanges, - pub stack_slots: ir::StackSlots, +pub struct FunctionInfo { pub traps: Vec, + pub address_map: FunctionAddressMap, pub stack_maps: Vec, } -/// A record of a relocation to perform. -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] -pub struct Relocation { - /// The relocation code. - pub reloc: binemit::Reloc, - /// Relocation target. - pub reloc_target: RelocationTarget, - /// The offset where to apply the relocation. - pub offset: binemit::CodeOffset, - /// The addend to add to the relocation value. - pub addend: binemit::Addend, -} - -/// Destination function. Can be either user function or some special one, like `memory.grow`. -#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] -pub enum RelocationTarget { - /// The user function index. - UserFunc(FuncIndex), - /// A compiler-generated libcall. - LibCall(ir::LibCall), - /// Jump table index. - JumpTable(FuncIndex, ir::JumpTable), -} - /// Information about trap. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct TrapInformation { /// The offset of the trapping instruction in native code. It is relative to the beginning of the function. - pub code_offset: binemit::CodeOffset, + pub code_offset: u32, /// Code of the trap. - pub trap_code: ir::TrapCode, + pub trap_code: TrapCode, +} + +/// A trap code describing the reason for a trap. +/// +/// All trap instructions have an explicit trap code. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)] +pub enum TrapCode { + /// The current stack space was exhausted. + StackOverflow, + + /// A `heap_addr` instruction detected an out-of-bounds error. + /// + /// Note that not all out-of-bounds heap accesses are reported this way; + /// some are detected by a segmentation fault on the heap unmapped or + /// offset-guard pages. + HeapOutOfBounds, + + /// A wasm atomic operation was presented with a not-naturally-aligned linear-memory address. + HeapMisaligned, + + /// A `table_addr` instruction detected an out-of-bounds error. + TableOutOfBounds, + + /// Indirect call to a null table entry. + IndirectCallToNull, + + /// Signature mismatch on indirect call. + BadSignature, + + /// An integer arithmetic operation caused an overflow. + IntegerOverflow, + + /// An integer division by zero. + IntegerDivisionByZero, + + /// Failed float-to-int conversion. + BadConversionToInteger, + + /// Code that was supposed to have been unreachable was reached. + UnreachableCodeReached, + + /// Execution has potentially run too long and may be interrupted. + /// This trap is resumable. + Interrupt, } /// The offset within a function of a GC safepoint, and its associated stack @@ -75,10 +82,10 @@ pub struct TrapInformation { pub struct StackMapInformation { /// The offset of the GC safepoint within the function's native code. It is /// relative to the beginning of the function. - pub code_offset: binemit::CodeOffset, + pub code_offset: u32, /// The stack map for identifying live GC refs at the GC safepoint. - pub stack_map: binemit::StackMap, + pub stack_map: StackMap, } /// An error while compiling WebAssembly to machine code. @@ -175,7 +182,7 @@ pub trait Compiler: Send + Sync { data: FunctionBodyData<'_>, tunables: &Tunables, types: &TypeTables, - ) -> Result; + ) -> Result, CompileError>; /// Collects the results of compilation and emits an in-memory ELF object /// which is the serialized representation of all compiler artifacts. @@ -185,9 +192,9 @@ pub trait Compiler: Send + Sync { &self, module: &ModuleTranslation, types: &TypeTables, - funcs: &CompiledFunctions, + funcs: PrimaryMap>, emit_dwarf: bool, - ) -> Result>; + ) -> Result<(Vec, PrimaryMap)>; /// Emits a small ELF object file in-memory which has two functions for the /// host-to-wasm and wasm-to-host trampolines for the wasm type given. diff --git a/crates/environ/src/data_structures.rs b/crates/environ/src/data_structures.rs deleted file mode 100644 index 8c96ca1606..0000000000 --- a/crates/environ/src/data_structures.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![doc(hidden)] - -pub mod ir { - pub use cranelift_codegen::binemit::StackMap; - pub use cranelift_codegen::ir::{types, SourceLoc, TrapCode, Type}; -} - -pub mod entity { - pub use cranelift_entity::{packed_option, BoxedSlice, EntityRef, EntitySet, PrimaryMap}; -} - -pub mod wasm { - pub use cranelift_wasm::*; -} diff --git a/crates/environ/src/lib.rs b/crates/environ/src/lib.rs index 702786f5b0..2c14fe7e67 100644 --- a/crates/environ/src/lib.rs +++ b/crates/environ/src/lib.rs @@ -26,22 +26,28 @@ mod address_map; mod builtin; mod compilation; -mod data_structures; mod module; mod module_environ; pub mod obj; +mod stack_map; mod tunables; mod vmoffsets; pub use crate::address_map::*; pub use crate::builtin::*; pub use crate::compilation::*; -pub use crate::data_structures::*; pub use crate::module::*; pub use crate::module_environ::*; +pub use crate::stack_map::StackMap; pub use crate::tunables::Tunables; pub use crate::vmoffsets::*; +// Reexport all of these type-level since they're quite commonly used and it's +// much easier to refer to everything through one crate rather than importing +// one of three and making sure you're using the right one. +pub use cranelift_entity::*; +pub use wasmtime_types::*; + /// WebAssembly page sizes are defined to be 64KiB. pub const WASM_PAGE_SIZE: u32 = 0x10000; @@ -55,19 +61,6 @@ pub const WASM64_MAX_PAGES: u64 = 1 << 48; /// Version number of this crate. pub const VERSION: &str = env!("CARGO_PKG_VERSION"); -/// Returns the reference type to use for the provided wasm type. -pub fn reference_type(wasm_ty: cranelift_wasm::WasmType, pointer_type: ir::Type) -> ir::Type { - match wasm_ty { - cranelift_wasm::WasmType::FuncRef => pointer_type, - cranelift_wasm::WasmType::ExternRef => match pointer_type { - ir::types::I32 => ir::types::R32, - ir::types::I64 => ir::types::R64, - _ => panic!("unsupported pointer type"), - }, - _ => panic!("unsupported Wasm reference type"), - } -} - /// Iterates through all `LibCall` members and all runtime exported functions. #[macro_export] macro_rules! for_each_libcall { diff --git a/crates/environ/src/module.rs b/crates/environ/src/module.rs index f87e3f9884..4c00b799bc 100644 --- a/crates/environ/src/module.rs +++ b/crates/environ/src/module.rs @@ -1,13 +1,12 @@ //! Data structures for representing decoded wasm modules. -use crate::tunables::Tunables; -use cranelift_entity::{EntityRef, PrimaryMap}; -use cranelift_wasm::*; +use crate::{EntityRef, PrimaryMap, Tunables}; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; use std::sync::Arc; +use wasmtime_types::*; /// Implemenation styles for WebAssembly linear memory. #[derive(Debug, Clone, Hash, Serialize, Deserialize)] @@ -267,7 +266,7 @@ impl TableStyle { #[derive(Debug, Clone, Hash, Serialize, Deserialize)] pub struct TablePlan { /// The WebAssembly table description. - pub table: cranelift_wasm::Table, + pub table: Table, /// Our chosen implementation style. pub style: TableStyle, } diff --git a/crates/environ/src/module_environ.rs b/crates/environ/src/module_environ.rs index 85d1c056fa..1d72b4f046 100644 --- a/crates/environ/src/module_environ.rs +++ b/crates/environ/src/module_environ.rs @@ -2,15 +2,13 @@ use crate::module::{ Initializer, InstanceSignature, MemoryInitialization, MemoryInitializer, MemoryPlan, Module, ModuleSignature, ModuleType, ModuleUpvar, TableInitializer, TablePlan, TypeTables, }; -use crate::tunables::Tunables; -use cranelift_codegen::ir::immediates::V128Imm; -use cranelift_codegen::packed_option::ReservedValue; -use cranelift_entity::PrimaryMap; -use cranelift_wasm::{ - self, DataIndex, DefinedFuncIndex, ElemIndex, EntityIndex, EntityType, FuncIndex, Global, +use crate::{ + DataIndex, DefinedFuncIndex, ElemIndex, EntityIndex, EntityType, FuncIndex, Global, GlobalIndex, GlobalInit, InstanceIndex, InstanceTypeIndex, MemoryIndex, ModuleIndex, - ModuleTypeIndex, SignatureIndex, TableIndex, TypeIndex, WasmError, WasmFuncType, WasmResult, + ModuleTypeIndex, PrimaryMap, SignatureIndex, TableIndex, Tunables, TypeIndex, WasmError, + WasmFuncType, WasmResult, }; +use cranelift_entity::packed_option::ReservedValue; use std::collections::{hash_map::Entry, HashMap}; use std::convert::{TryFrom, TryInto}; use std::mem; @@ -396,7 +394,7 @@ impl<'data> ModuleEnvironment<'data> { Operator::F32Const { value } => GlobalInit::F32Const(value.bits()), Operator::F64Const { value } => GlobalInit::F64Const(value.bits()), Operator::V128Const { value } => { - GlobalInit::V128Const(V128Imm::from(value.bytes().to_vec().as_slice())) + GlobalInit::V128Const(u128::from_le_bytes(*value.bytes())) } Operator::RefNull { ty: _ } => GlobalInit::RefNullConst, Operator::RefFunc { function_index } => { diff --git a/crates/environ/src/obj.rs b/crates/environ/src/obj.rs index 10d8d6f171..73ea699993 100644 --- a/crates/environ/src/obj.rs +++ b/crates/environ/src/obj.rs @@ -1,8 +1,7 @@ //! Utilities for working with object files that operate as Wasmtime's //! serialization and intermediate format for compiled modules. -use cranelift_entity::EntityRef; -use cranelift_wasm::{FuncIndex, SignatureIndex}; +use crate::{EntityRef, FuncIndex, SignatureIndex}; const FUNCTION_PREFIX: &str = "_wasm_function_"; const TRAMPOLINE_PREFIX: &str = "_trampoline_"; diff --git a/crates/environ/src/stack_map.rs b/crates/environ/src/stack_map.rs new file mode 100644 index 0000000000..848f3de890 --- /dev/null +++ b/crates/environ/src/stack_map.rs @@ -0,0 +1,36 @@ +use serde::{Deserialize, Serialize}; + +/// A map for determining where live GC references live in a stack frame. +/// +/// Note that this is currently primarily documented as cranelift's +/// `binemit::StackMap`, so for detailed documentation about this please read +/// the docs over there. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct StackMap { + bits: Box<[u32]>, + mapped_words: u32, +} + +impl StackMap { + /// Creates a new `StackMap`, typically from a preexisting + /// `binemit::StackMap`. + pub fn new(mapped_words: u32, bits: impl Iterator) -> StackMap { + StackMap { + bits: bits.collect(), + mapped_words, + } + } + + /// Returns a specified bit. + pub fn get_bit(&self, bit_index: usize) -> bool { + assert!(bit_index < 32 * self.bits.len()); + let word_index = bit_index / 32; + let word_offset = bit_index % 32; + (self.bits[word_index] & (1 << word_offset)) != 0 + } + + /// Returns the number of words represented by this stack map. + pub fn mapped_words(&self) -> u32 { + self.mapped_words + } +} diff --git a/crates/environ/src/vmoffsets.rs b/crates/environ/src/vmoffsets.rs index c4d2bf113b..29519c6575 100644 --- a/crates/environ/src/vmoffsets.rs +++ b/crates/environ/src/vmoffsets.rs @@ -19,12 +19,9 @@ // builtins: VMBuiltinFunctionsArray, // } -use crate::module::Module; -use crate::BuiltinFunctionIndex; -use cranelift_codegen::ir; -use cranelift_wasm::{ - DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, GlobalIndex, MemoryIndex, - TableIndex, TypeIndex, +use crate::{ + BuiltinFunctionIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, + GlobalIndex, MemoryIndex, Module, TableIndex, TypeIndex, }; use more_asserts::assert_lt; use std::convert::TryFrom; @@ -375,12 +372,6 @@ impl VMOffsets

{ pub fn size_of_vmtable_definition(&self) -> u8 { 2 * self.pointer_size() } - - /// The type of the `current_elements` field. - #[inline] - pub fn type_of_vmtable_definition_current_elements(&self) -> ir::Type { - ir::Type::int(u16::from(self.size_of_vmtable_definition_current_elements()) * 8).unwrap() - } } /// Offsets for `VMMemoryImport`. diff --git a/crates/jit/src/code_memory.rs b/crates/jit/src/code_memory.rs index e704247eca..04fe5f07ba 100644 --- a/crates/jit/src/code_memory.rs +++ b/crates/jit/src/code_memory.rs @@ -6,7 +6,7 @@ use object::read::{File as ObjectFile, Object, ObjectSection, ObjectSymbol}; use std::collections::BTreeMap; use std::mem::ManuallyDrop; use wasmtime_environ::obj::{try_parse_func_name, try_parse_trampoline_name}; -use wasmtime_environ::wasm::{FuncIndex, SignatureIndex}; +use wasmtime_environ::{FuncIndex, SignatureIndex}; use wasmtime_runtime::{Mmap, VMFunctionBody}; struct CodeMemoryEntry { diff --git a/crates/jit/src/compiler.rs b/crates/jit/src/compiler.rs index 8dd013abb3..dab70ac5f6 100644 --- a/crates/jit/src/compiler.rs +++ b/crates/jit/src/compiler.rs @@ -9,8 +9,8 @@ use std::hash::{Hash, Hasher}; use std::mem; use wasmparser::WasmFeatures; use wasmtime_environ::{ - CompiledFunctions, Compiler as EnvCompiler, CompilerBuilder, ModuleTranslation, Tunables, - TypeTables, + Compiler as EnvCompiler, CompilerBuilder, DefinedFuncIndex, FunctionInfo, ModuleTranslation, + PrimaryMap, Tunables, TypeTables, }; /// Select which kind of compilation to use. @@ -72,7 +72,7 @@ fn _assert_compiler_send_sync() { #[allow(missing_docs)] pub struct Compilation { pub obj: Vec, - pub funcs: CompiledFunctions, + pub funcs: PrimaryMap, } impl Compiler { @@ -111,12 +111,12 @@ impl Compiler { .compile_function(translation, index, func, &self.tunables, types) })? .into_iter() - .collect::(); + .collect(); - let obj = self.compiler.emit_obj( + let (obj, funcs) = self.compiler.emit_obj( &translation, types, - &funcs, + funcs, self.tunables.generate_native_debuginfo, )?; diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index 3fe55df70c..1af8dd9276 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -12,13 +12,10 @@ use serde::{Deserialize, Serialize}; use std::ops::Range; use std::sync::Arc; use thiserror::Error; -use wasmtime_environ::entity::PrimaryMap; -use wasmtime_environ::wasm::{ - DefinedFuncIndex, InstanceTypeIndex, ModuleTypeIndex, SignatureIndex, WasmFuncType, -}; use wasmtime_environ::{ - CompileError, DebugInfoData, FunctionAddressMap, InstanceSignature, Module, ModuleEnvironment, - ModuleSignature, ModuleTranslation, StackMapInformation, TrapInformation, + CompileError, DebugInfoData, DefinedFuncIndex, FunctionInfo, InstanceSignature, + InstanceTypeIndex, Module, ModuleEnvironment, ModuleSignature, ModuleTranslation, + ModuleTypeIndex, PrimaryMap, SignatureIndex, StackMapInformation, WasmFuncType, }; use wasmtime_profiling::ProfilingAgent; use wasmtime_runtime::{GdbJitImageRegistration, InstantiationError, VMFunctionBody, VMTrampoline}; @@ -158,15 +155,6 @@ struct FinishedFunctions(PrimaryMap); unsafe impl Send for FinishedFunctions {} unsafe impl Sync for FinishedFunctions {} -/// Information about a function, such as trap information, address map, -/// and stack maps. -#[derive(Serialize, Deserialize, Clone)] -pub struct FunctionInfo { - pub traps: Vec, - pub address_map: FunctionAddressMap, - pub stack_maps: Vec, -} - /// This is intended to mirror the type tables in `wasmtime_environ`, except that /// it doesn't store the native signatures which are no longer needed past compilation. #[derive(Serialize, Deserialize)] diff --git a/crates/jit/src/link.rs b/crates/jit/src/link.rs index 25a8c80ce3..9f78c6f5fd 100644 --- a/crates/jit/src/link.rs +++ b/crates/jit/src/link.rs @@ -3,10 +3,8 @@ use object::read::{Object, ObjectSection, Relocation, RelocationTarget}; use object::{elf, File, ObjectSymbol, RelocationEncoding, RelocationKind}; use std::ptr::{read_unaligned, write_unaligned}; -use wasmtime_environ::entity::PrimaryMap; use wasmtime_environ::obj::try_parse_func_name; -use wasmtime_environ::wasm::DefinedFuncIndex; -use wasmtime_environ::Module; +use wasmtime_environ::{DefinedFuncIndex, Module, PrimaryMap}; use wasmtime_runtime::libcalls; use wasmtime_runtime::VMFunctionBody; diff --git a/crates/lightbeam/wasmtime/src/lib.rs b/crates/lightbeam/wasmtime/src/lib.rs index 7df603fbe4..c32e5ec5a0 100644 --- a/crates/lightbeam/wasmtime/src/lib.rs +++ b/crates/lightbeam/wasmtime/src/lib.rs @@ -8,15 +8,15 @@ use anyhow::Result; use cranelift_codegen::binemit; use cranelift_codegen::ir::{self, ExternalName}; +use std::any::Any; use std::collections::HashMap; -use wasmtime_environ::wasm::{ - DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, - GlobalIndex, MemoryIndex, TableIndex, TypeIndex, WasmFuncType, +use wasmtime_environ::{ + BuiltinFunctionIndex, CompileError, Compiler, FlagValue, FunctionBodyData, FunctionInfo, + Module, ModuleTranslation, PrimaryMap, TrapInformation, Tunables, TypeTables, VMOffsets, }; use wasmtime_environ::{ - BuiltinFunctionIndex, CompileError, CompiledFunction, CompiledFunctions, Compiler, FlagValue, - FunctionBodyData, Module, ModuleTranslation, Relocation, RelocationTarget, TrapInformation, - Tunables, TypeTables, VMOffsets, + DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, + GlobalIndex, MemoryIndex, TableIndex, TypeIndex, WasmFuncType, }; /// A compiler that compiles a WebAssembly module with Lightbeam, directly translating the Wasm file. @@ -30,7 +30,7 @@ impl Compiler for Lightbeam { _function_body: FunctionBodyData<'_>, _tunables: &Tunables, _types: &TypeTables, - ) -> Result { + ) -> Result, CompileError> { unimplemented!() // if tunables.generate_native_debuginfo { // return Err(CompileError::DebugInfoNotSupported); @@ -82,9 +82,9 @@ impl Compiler for Lightbeam { &self, _module: &ModuleTranslation, _types: &TypeTables, - _funcs: &CompiledFunctions, + _funcs: PrimaryMap>, _emit_dwarf: bool, - ) -> Result> { + ) -> Result<(Vec, PrimaryMap)> { unimplemented!() } @@ -109,34 +109,34 @@ impl Compiler for Lightbeam { struct RelocSink { /// Current function index. func_index: FuncIndex, - - /// Relocations recorded for the function. - func_relocs: Vec, + // /// Relocations recorded for the function. + // func_relocs: Vec, } impl binemit::RelocSink for RelocSink { fn reloc_external( &mut self, - offset: binemit::CodeOffset, + _offset: binemit::CodeOffset, _srcloc: ir::SourceLoc, - reloc: binemit::Reloc, - name: &ExternalName, - addend: binemit::Addend, + _reloc: binemit::Reloc, + _name: &ExternalName, + _addend: binemit::Addend, ) { - let reloc_target = if let ExternalName::User { namespace, index } = *name { - debug_assert_eq!(namespace, 0); - RelocationTarget::UserFunc(FuncIndex::from_u32(index)) - } else if let ExternalName::LibCall(libcall) = *name { - RelocationTarget::LibCall(libcall) - } else { - panic!("unrecognized external name") - }; - self.func_relocs.push(Relocation { - reloc, - reloc_target, - offset, - addend, - }); + unimplemented!() + // let reloc_target = if let ExternalName::User { namespace, index } = *name { + // debug_assert_eq!(namespace, 0); + // RelocationTarget::UserFunc(FuncIndex::from_u32(index)) + // } else if let ExternalName::LibCall(libcall) = *name { + // RelocationTarget::LibCall(libcall) + // } else { + // panic!("unrecognized external name") + // }; + // self.func_relocs.push(Relocation { + // reloc, + // reloc_target, + // offset, + // addend, + // }); } fn reloc_constant( @@ -149,13 +149,19 @@ impl binemit::RelocSink for RelocSink { // function code with correct relative offsets to the constant data. } - fn reloc_jt(&mut self, offset: binemit::CodeOffset, reloc: binemit::Reloc, jt: ir::JumpTable) { - self.func_relocs.push(Relocation { - reloc, - reloc_target: RelocationTarget::JumpTable(self.func_index, jt), - offset, - addend: 0, - }); + fn reloc_jt( + &mut self, + _offset: binemit::CodeOffset, + _reloc: binemit::Reloc, + _jt: ir::JumpTable, + ) { + unimplemented!() + // self.func_relocs.push(Relocation { + // reloc, + // reloc_target: RelocationTarget::JumpTable(self.func_index, jt), + // offset, + // addend: 0, + // }); } } @@ -164,7 +170,7 @@ impl RelocSink { fn new(func_index: FuncIndex) -> Self { Self { func_index, - func_relocs: Vec::new(), + // func_relocs: Vec::new(), } } } @@ -186,14 +192,15 @@ impl TrapSink { impl binemit::TrapSink for TrapSink { fn trap( &mut self, - code_offset: binemit::CodeOffset, + _code_offset: binemit::CodeOffset, _source_loc: ir::SourceLoc, - trap_code: ir::TrapCode, + _trap_code: ir::TrapCode, ) { - self.traps.push(TrapInformation { - code_offset, - trap_code, - }); + unimplemented!() + // self.traps.push(TrapInformation { + // code_offset, + // trap_code, + // }); } } diff --git a/crates/profiling/src/jitdump_disabled.rs b/crates/profiling/src/jitdump_disabled.rs index 5197ddb5b5..b8973ad025 100644 --- a/crates/profiling/src/jitdump_disabled.rs +++ b/crates/profiling/src/jitdump_disabled.rs @@ -1,8 +1,6 @@ use crate::ProfilingAgent; use anyhow::{bail, Result}; -use wasmtime_environ::entity::PrimaryMap; -use wasmtime_environ::wasm::DefinedFuncIndex; -use wasmtime_environ::Module; +use wasmtime_environ::{DefinedFuncIndex, Module, PrimaryMap}; use wasmtime_runtime::VMFunctionBody; /// Interface for driving the creation of jitdump files diff --git a/crates/profiling/src/jitdump_linux.rs b/crates/profiling/src/jitdump_linux.rs index d5d26be92b..24c14a74de 100644 --- a/crates/profiling/src/jitdump_linux.rs +++ b/crates/profiling/src/jitdump_linux.rs @@ -25,9 +25,7 @@ use std::ptr; use std::sync::Mutex; use std::{borrow, mem, process}; use target_lexicon::Architecture; -use wasmtime_environ::entity::PrimaryMap; -use wasmtime_environ::wasm::DefinedFuncIndex; -use wasmtime_environ::Module; +use wasmtime_environ::{DefinedFuncIndex, Module, PrimaryMap}; use wasmtime_runtime::VMFunctionBody; use object::elf; diff --git a/crates/profiling/src/lib.rs b/crates/profiling/src/lib.rs index a0e2a36ea5..ad4b17a9ba 100644 --- a/crates/profiling/src/lib.rs +++ b/crates/profiling/src/lib.rs @@ -1,8 +1,6 @@ use std::error::Error; use std::fmt; -use wasmtime_environ::entity::{EntityRef, PrimaryMap}; -use wasmtime_environ::wasm::DefinedFuncIndex; -use wasmtime_environ::Module; +use wasmtime_environ::{DefinedFuncIndex, EntityRef, Module, PrimaryMap}; use wasmtime_runtime::VMFunctionBody; cfg_if::cfg_if! { diff --git a/crates/profiling/src/vtune_disabled.rs b/crates/profiling/src/vtune_disabled.rs index 217e46ced1..cbd46fcdb0 100644 --- a/crates/profiling/src/vtune_disabled.rs +++ b/crates/profiling/src/vtune_disabled.rs @@ -1,8 +1,6 @@ use crate::ProfilingAgent; use anyhow::{bail, Result}; -use wasmtime_environ::entity::PrimaryMap; -use wasmtime_environ::wasm::DefinedFuncIndex; -use wasmtime_environ::Module; +use wasmtime_environ::{DefinedFuncIndex, Module, PrimaryMap}; use wasmtime_runtime::VMFunctionBody; /// Interface for driving vtune support diff --git a/crates/profiling/src/vtune_linux.rs b/crates/profiling/src/vtune_linux.rs index 8c20ca61ef..f53574f886 100644 --- a/crates/profiling/src/vtune_linux.rs +++ b/crates/profiling/src/vtune_linux.rs @@ -10,12 +10,12 @@ use crate::ProfilingAgent; use anyhow::Result; use core::ptr; +use cranelift_entity::PrimaryMap; +use cranelift_wasm_types::DefinedFuncIndex; use ittapi_rs::*; use std::collections::HashMap; use std::ffi::CString; use std::sync::Mutex; -use wasmtime_environ::entity::PrimaryMap; -use wasmtime_environ::wasm::DefinedFuncIndex; use wasmtime_environ::Module; use wasmtime_runtime::VMFunctionBody; diff --git a/crates/runtime/src/debug_builtins.rs b/crates/runtime/src/debug_builtins.rs index 8d685651b8..187b6f918d 100644 --- a/crates/runtime/src/debug_builtins.rs +++ b/crates/runtime/src/debug_builtins.rs @@ -2,8 +2,7 @@ use crate::instance::InstanceHandle; use crate::vmcontext::VMContext; -use wasmtime_environ::entity::EntityRef; -use wasmtime_environ::wasm::MemoryIndex; +use wasmtime_environ::{EntityRef, MemoryIndex}; static mut VMCTX_AND_MEMORY: (*mut VMContext, usize) = (std::ptr::null_mut(), 0); diff --git a/crates/runtime/src/export.rs b/crates/runtime/src/export.rs index f1934a812c..df883a3a94 100644 --- a/crates/runtime/src/export.rs +++ b/crates/runtime/src/export.rs @@ -2,8 +2,7 @@ use crate::vmcontext::{ VMCallerCheckedAnyfunc, VMContext, VMGlobalDefinition, VMMemoryDefinition, VMTableDefinition, }; use std::ptr::NonNull; -use wasmtime_environ::wasm::Global; -use wasmtime_environ::{MemoryPlan, TablePlan}; +use wasmtime_environ::{Global, MemoryPlan, TablePlan}; /// The value of an export passed from one instance to another. pub enum Export { diff --git a/crates/runtime/src/externref.rs b/crates/runtime/src/externref.rs index 55a8dae3e8..ecf20c505d 100644 --- a/crates/runtime/src/externref.rs +++ b/crates/runtime/src/externref.rs @@ -109,7 +109,7 @@ use std::ops::Deref; use std::ptr::{self, NonNull}; use std::sync::atomic::{self, AtomicUsize, Ordering}; use std::{alloc::Layout, sync::Arc}; -use wasmtime_environ::ir::StackMap; +use wasmtime_environ::StackMap; /// An external reference to some opaque data. /// diff --git a/crates/runtime/src/instance.rs b/crates/runtime/src/instance.rs index 1324b771fa..f735cb0198 100644 --- a/crates/runtime/src/instance.rs +++ b/crates/runtime/src/instance.rs @@ -22,12 +22,11 @@ use std::hash::Hash; use std::ptr::NonNull; use std::sync::Arc; use std::{mem, ptr, slice}; -use wasmtime_environ::entity::{packed_option::ReservedValue, EntityRef, EntitySet, PrimaryMap}; -use wasmtime_environ::wasm::{ - DataIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, ElemIndex, EntityIndex, - FuncIndex, GlobalIndex, MemoryIndex, TableIndex, WasmType, +use wasmtime_environ::{ + packed_option::ReservedValue, DataIndex, DefinedGlobalIndex, DefinedMemoryIndex, + DefinedTableIndex, ElemIndex, EntityIndex, EntityRef, EntitySet, FuncIndex, GlobalIndex, + HostPtr, MemoryIndex, Module, PrimaryMap, TableIndex, TrapCode, VMOffsets, WasmType, }; -use wasmtime_environ::{ir, HostPtr, Module, VMOffsets}; mod allocator; @@ -571,7 +570,7 @@ impl Instance { .and_then(|s| s.get(..usize::try_from(len).unwrap())) { Some(elements) => elements, - None => return Err(Trap::wasm(ir::TrapCode::TableOutOfBounds)), + None => return Err(Trap::wasm(TrapCode::TableOutOfBounds)), }; match table.element_type() { @@ -649,7 +648,7 @@ impl Instance { } fn validate_inbounds(&self, max: usize, ptr: u64, len: u64) -> Result { - let oob = || Trap::wasm(ir::TrapCode::HeapOutOfBounds); + let oob = || Trap::wasm(TrapCode::HeapOutOfBounds); let end = ptr .checked_add(len) .and_then(|i| usize::try_from(i).ok()) diff --git a/crates/runtime/src/instance/allocator.rs b/crates/runtime/src/instance/allocator.rs index a8b9d41b8a..b92afd85e5 100644 --- a/crates/runtime/src/instance/allocator.rs +++ b/crates/runtime/src/instance/allocator.rs @@ -17,13 +17,10 @@ use std::ptr::{self, NonNull}; use std::slice; use std::sync::Arc; use thiserror::Error; -use wasmtime_environ::entity::{EntityRef, EntitySet, PrimaryMap}; -use wasmtime_environ::wasm::{ - DefinedFuncIndex, DefinedMemoryIndex, DefinedTableIndex, GlobalInit, SignatureIndex, WasmType, -}; use wasmtime_environ::{ - ir, HostPtr, MemoryInitialization, MemoryInitializer, Module, ModuleType, TableInitializer, - VMOffsets, WASM_PAGE_SIZE, + DefinedFuncIndex, DefinedMemoryIndex, DefinedTableIndex, EntityRef, EntitySet, GlobalInit, + HostPtr, MemoryInitialization, MemoryInitializer, Module, ModuleType, PrimaryMap, + SignatureIndex, TableInitializer, TrapCode, VMOffsets, WasmType, WASM_PAGE_SIZE, }; mod pooling; @@ -408,7 +405,7 @@ fn initialize_instance( // the expected behavior of the bulk memory spec. if *out_of_bounds { return Err(InstantiationError::Trap(Trap::wasm( - ir::TrapCode::HeapOutOfBounds, + TrapCode::HeapOutOfBounds, ))); } } @@ -533,7 +530,7 @@ unsafe fn initialize_vmcontext_globals(instance: &Instance) { GlobalInit::I64Const(x) => *(*to).as_i64_mut() = x, GlobalInit::F32Const(x) => *(*to).as_f32_bits_mut() = x, GlobalInit::F64Const(x) => *(*to).as_f64_bits_mut() = x, - GlobalInit::V128Const(x) => *(*to).as_u128_bits_mut() = x.0, + GlobalInit::V128Const(x) => *(*to).as_u128_mut() = x, GlobalInit::GetGlobal(x) => { let from = if let Some(def_x) = module.defined_global_index(x) { instance.global(def_x) diff --git a/crates/runtime/src/instance/allocator/pooling.rs b/crates/runtime/src/instance/allocator/pooling.rs index 9a792bfbad..4030ab46ed 100644 --- a/crates/runtime/src/instance/allocator/pooling.rs +++ b/crates/runtime/src/instance/allocator/pooling.rs @@ -20,8 +20,8 @@ use std::marker; use std::mem; use std::sync::{Arc, Mutex}; use wasmtime_environ::{ - entity::{EntitySet, PrimaryMap}, - HostPtr, MemoryStyle, Module, Tunables, VMOffsets, VMOffsetsFields, WASM_PAGE_SIZE, + EntitySet, HostPtr, MemoryStyle, Module, PrimaryMap, Tunables, VMOffsets, VMOffsetsFields, + WASM_PAGE_SIZE, }; cfg_if::cfg_if! { @@ -1000,7 +1000,7 @@ unsafe impl InstanceAllocator for PoolingInstanceAllocator { // If there was an out of bounds access observed in initialization, return a trap if *out_of_bounds { return Err(InstantiationError::Trap(crate::traphandlers::Trap::wasm( - wasmtime_environ::ir::TrapCode::HeapOutOfBounds, + wasmtime_environ::TrapCode::HeapOutOfBounds, ))); } @@ -1050,9 +1050,8 @@ mod test { use super::*; use crate::{Imports, VMSharedSignatureIndex}; use wasmtime_environ::{ - entity::EntityRef, - wasm::{Global, GlobalInit, Memory, SignatureIndex, Table, WasmType}, - MemoryPlan, ModuleType, TablePlan, TableStyle, + EntityRef, Global, GlobalInit, Memory, MemoryPlan, ModuleType, SignatureIndex, Table, + TablePlan, TableStyle, WasmType, }; #[test] diff --git a/crates/runtime/src/instance/allocator/pooling/uffd.rs b/crates/runtime/src/instance/allocator/pooling/uffd.rs index 757bdb024d..3e7255353f 100644 --- a/crates/runtime/src/instance/allocator/pooling/uffd.rs +++ b/crates/runtime/src/instance/allocator/pooling/uffd.rs @@ -35,7 +35,7 @@ use crate::instance::Instance; use anyhow::{bail, Context, Result}; use std::thread; use userfaultfd::{Event, FeatureFlags, IoctlFlags, Uffd, UffdBuilder}; -use wasmtime_environ::{entity::EntityRef, wasm::DefinedMemoryIndex, MemoryInitialization}; +use wasmtime_environ::{DefinedMemoryIndex, EntityRef, MemoryInitialization}; const WASM_PAGE_SIZE: usize = wasmtime_environ::WASM_PAGE_SIZE as usize; @@ -441,9 +441,7 @@ mod test { PoolingAllocationStrategy, VMSharedSignatureIndex, }; use std::sync::Arc; - use wasmtime_environ::{ - entity::PrimaryMap, wasm::Memory, MemoryPlan, MemoryStyle, Module, Tunables, - }; + use wasmtime_environ::{Memory, MemoryPlan, MemoryStyle, Module, PrimaryMap, Tunables}; #[cfg(target_pointer_width = "64")] #[test] diff --git a/crates/runtime/src/lib.rs b/crates/runtime/src/lib.rs index cb98c61c0c..0be1abec77 100644 --- a/crates/runtime/src/lib.rs +++ b/crates/runtime/src/lib.rs @@ -62,28 +62,6 @@ pub use crate::vmcontext::{ /// Version number of this crate. pub const VERSION: &str = env!("CARGO_PKG_VERSION"); -/// The Cranelift IR type used for reference types for this target architecture. -pub fn ref_type() -> wasmtime_environ::ir::Type { - if cfg!(target_pointer_width = "32") { - wasmtime_environ::ir::types::R32 - } else if cfg!(target_pointer_width = "64") { - wasmtime_environ::ir::types::R64 - } else { - unreachable!() - } -} - -/// The Cranelift IR type used for pointer types for this target architecture. -pub fn pointer_type() -> wasmtime_environ::ir::Type { - if cfg!(target_pointer_width = "32") { - wasmtime_environ::ir::types::I32 - } else if cfg!(target_pointer_width = "64") { - wasmtime_environ::ir::types::I64 - } else { - unreachable!() - } -} - /// Dynamic runtime functionality needed by this crate throughout the execution /// of a wasm instance. /// diff --git a/crates/runtime/src/libcalls.rs b/crates/runtime/src/libcalls.rs index 17ee935faf..f307a4dbfe 100644 --- a/crates/runtime/src/libcalls.rs +++ b/crates/runtime/src/libcalls.rs @@ -64,8 +64,7 @@ use crate::vmcontext::{VMCallerCheckedAnyfunc, VMContext}; use backtrace::Backtrace; use std::mem; use std::ptr::{self, NonNull}; -use wasmtime_environ::ir::TrapCode; -use wasmtime_environ::wasm::{DataIndex, ElemIndex, GlobalIndex, MemoryIndex, TableIndex}; +use wasmtime_environ::{DataIndex, ElemIndex, GlobalIndex, MemoryIndex, TableIndex, TrapCode}; const TOINT_32: f32 = 1.0 / f32::EPSILON; const TOINT_64: f64 = 1.0 / f64::EPSILON; diff --git a/crates/runtime/src/table.rs b/crates/runtime/src/table.rs index d2dbcc5c56..c6e977d308 100644 --- a/crates/runtime/src/table.rs +++ b/crates/runtime/src/table.rs @@ -8,8 +8,7 @@ use anyhow::{bail, Result}; use std::convert::{TryFrom, TryInto}; use std::ops::Range; use std::ptr; -use wasmtime_environ::wasm::WasmType; -use wasmtime_environ::{ir, TablePlan}; +use wasmtime_environ::{TablePlan, TrapCode, WasmType}; /// An element going into or coming out of a table. /// @@ -237,7 +236,7 @@ impl Table { .and_then(|s| s.get_mut(..items.len())) { Some(elements) => elements, - None => return Err(Trap::wasm(ir::TrapCode::TableOutOfBounds)), + None => return Err(Trap::wasm(TrapCode::TableOutOfBounds)), }; for (item, slot) in items.zip(elements) { @@ -253,10 +252,10 @@ impl Table { let start = dst as usize; let end = start .checked_add(len as usize) - .ok_or_else(|| Trap::wasm(ir::TrapCode::TableOutOfBounds))?; + .ok_or_else(|| Trap::wasm(TrapCode::TableOutOfBounds))?; if end > self.size() as usize { - return Err(Trap::wasm(ir::TrapCode::TableOutOfBounds)); + return Err(Trap::wasm(TrapCode::TableOutOfBounds)); } debug_assert!(self.type_matches(&val)); @@ -379,7 +378,7 @@ impl Table { .checked_add(len) .map_or(true, |m| m > (*dst_table).size()) { - return Err(Trap::wasm(ir::TrapCode::TableOutOfBounds)); + return Err(Trap::wasm(TrapCode::TableOutOfBounds)); } debug_assert!( diff --git a/crates/runtime/src/traphandlers.rs b/crates/runtime/src/traphandlers.rs index 4153e9e178..e4c4faf6a9 100644 --- a/crates/runtime/src/traphandlers.rs +++ b/crates/runtime/src/traphandlers.rs @@ -10,7 +10,7 @@ use std::mem::MaybeUninit; use std::ptr; use std::sync::atomic::Ordering::SeqCst; use std::sync::Once; -use wasmtime_environ::ir; +use wasmtime_environ::TrapCode; pub use self::tls::{tls_eager_initialize, TlsRestore}; @@ -131,7 +131,7 @@ pub enum Trap { /// A trap raised from a wasm libcall Wasm { /// Code of the trap. - trap_code: ir::TrapCode, + trap_code: TrapCode, /// Native stack backtrace at the time the trap occurred backtrace: Backtrace, }, @@ -147,7 +147,7 @@ impl Trap { /// Construct a new Wasm trap with the given source location and trap code. /// /// Internally saves a backtrace when constructed. - pub fn wasm(trap_code: ir::TrapCode) -> Self { + pub fn wasm(trap_code: TrapCode) -> Self { let backtrace = Backtrace::new_unresolved(); Trap::Wasm { trap_code, diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml new file mode 100644 index 0000000000..d5cb416724 --- /dev/null +++ b/crates/types/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "wasmtime-types" +version = "0.29.0" +authors = ["The Wasmtime Project Developers"] +description = "WebAssembly type definitions for Cranelift" +license = "Apache-2.0 WITH LLVM-exception" +repository = "https://github.com/bytecodealliance/wasmtime" +documentation = "https://docs.rs/wasmtime-types" +edition = "2018" + +[dependencies] +cranelift-entity = { path = "../../cranelift/entity", version = "0.76.0", features = ['enable-serde'] } +serde = { version = "1.0.94", features = ["derive"] } +thiserror = "1.0.4" +wasmparser = { version = "0.80", default-features = false } diff --git a/crates/types/src/error.rs b/crates/types/src/error.rs new file mode 100644 index 0000000000..f88536fa5f --- /dev/null +++ b/crates/types/src/error.rs @@ -0,0 +1,59 @@ +use thiserror::Error; + +/// A WebAssembly translation error. +/// +/// When a WebAssembly function can't be translated, one of these error codes will be returned +/// to describe the failure. +#[derive(Error, Debug)] +pub enum WasmError { + /// The input WebAssembly code is invalid. + /// + /// This error code is used by a WebAssembly translator when it encounters invalid WebAssembly + /// code. This should never happen for validated WebAssembly code. + #[error("Invalid input WebAssembly code at offset {offset}: {message}")] + InvalidWebAssembly { + /// A string describing the validation error. + message: String, + /// The bytecode offset where the error occurred. + offset: usize, + }, + + /// A feature used by the WebAssembly code is not supported by the embedding environment. + /// + /// Embedding environments may have their own limitations and feature restrictions. + #[error("Unsupported feature: {0}")] + Unsupported(String), + + /// An implementation limit was exceeded. + /// + /// Cranelift can compile very large and complicated functions, but the [implementation has + /// limits][limits] that cause compilation to fail when they are exceeded. + /// + /// [limits]: https://github.com/bytecodealliance/wasmtime/blob/main/cranelift/docs/ir.md#implementation-limits + #[error("Implementation limit exceeded")] + ImplLimitExceeded, + + /// Any user-defined error. + #[error("User error: {0}")] + User(String), +} + +/// Return an `Err(WasmError::Unsupported(msg))` where `msg` the string built by calling `format!` +/// on the arguments to this macro. +#[macro_export] +macro_rules! wasm_unsupported { + ($($arg:tt)*) => { $crate::WasmError::Unsupported(format!($($arg)*)) } +} + +impl From for WasmError { + /// Convert from a `BinaryReaderError` to a `WasmError`. + fn from(e: wasmparser::BinaryReaderError) -> Self { + Self::InvalidWebAssembly { + message: e.message().into(), + offset: e.offset(), + } + } +} + +/// A convenient alias for a `Result` that uses `WasmError` as the error type. +pub type WasmResult = Result; diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs new file mode 100644 index 0000000000..6201b328d6 --- /dev/null +++ b/crates/types/src/lib.rs @@ -0,0 +1,337 @@ +//! Internal dependency of Wasmtime and Cranelift that defines types for +//! WebAssembly. + +pub use wasmparser; + +use cranelift_entity::entity_impl; + +use serde::{Deserialize, Serialize}; +use std::convert::{TryFrom, TryInto}; + +mod error; +pub use error::*; + +/// WebAssembly value type -- equivalent of `wasmparser`'s Type. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum WasmType { + /// I32 type + I32, + /// I64 type + I64, + /// F32 type + F32, + /// F64 type + F64, + /// V128 type + V128, + /// FuncRef type + FuncRef, + /// ExternRef type + ExternRef, + /// ExnRef type + ExnRef, +} + +impl TryFrom for WasmType { + type Error = WasmError; + fn try_from(ty: wasmparser::Type) -> Result { + use wasmparser::Type::*; + match ty { + I32 => Ok(WasmType::I32), + I64 => Ok(WasmType::I64), + F32 => Ok(WasmType::F32), + F64 => Ok(WasmType::F64), + V128 => Ok(WasmType::V128), + FuncRef => Ok(WasmType::FuncRef), + ExternRef => Ok(WasmType::ExternRef), + ExnRef => Ok(WasmType::ExnRef), + EmptyBlockType | Func => Err(WasmError::InvalidWebAssembly { + message: "unexpected value type".to_string(), + offset: 0, + }), + } + } +} + +impl From for wasmparser::Type { + fn from(ty: WasmType) -> wasmparser::Type { + match ty { + WasmType::I32 => wasmparser::Type::I32, + WasmType::I64 => wasmparser::Type::I64, + WasmType::F32 => wasmparser::Type::F32, + WasmType::F64 => wasmparser::Type::F64, + WasmType::V128 => wasmparser::Type::V128, + WasmType::FuncRef => wasmparser::Type::FuncRef, + WasmType::ExternRef => wasmparser::Type::ExternRef, + WasmType::ExnRef => wasmparser::Type::ExnRef, + } + } +} + +/// WebAssembly function type -- equivalent of `wasmparser`'s FuncType. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] +pub struct WasmFuncType { + /// Function params types. + pub params: Box<[WasmType]>, + /// Returns params types. + pub returns: Box<[WasmType]>, +} + +impl TryFrom for WasmFuncType { + type Error = WasmError; + fn try_from(ty: wasmparser::FuncType) -> Result { + Ok(Self { + params: ty + .params + .into_vec() + .into_iter() + .map(WasmType::try_from) + .collect::>()?, + returns: ty + .returns + .into_vec() + .into_iter() + .map(WasmType::try_from) + .collect::>()?, + }) + } +} + +/// Index type of a function (imported or defined) inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +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, Debug, Serialize, Deserialize)] +pub struct DefinedFuncIndex(u32); +entity_impl!(DefinedFuncIndex); + +/// Index type of a defined table inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct DefinedTableIndex(u32); +entity_impl!(DefinedTableIndex); + +/// Index type of a defined memory inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct DefinedMemoryIndex(u32); +entity_impl!(DefinedMemoryIndex); + +/// Index type of a defined global inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct DefinedGlobalIndex(u32); +entity_impl!(DefinedGlobalIndex); + +/// Index type of a table (imported or defined) inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct TableIndex(u32); +entity_impl!(TableIndex); + +/// Index type of a global variable (imported or defined) inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct GlobalIndex(u32); +entity_impl!(GlobalIndex); + +/// Index type of a linear memory (imported or defined) inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct MemoryIndex(u32); +entity_impl!(MemoryIndex); + +/// Index type of a signature (imported or defined) inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct SignatureIndex(u32); +entity_impl!(SignatureIndex); + +/// Index type of a passive data segment inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct DataIndex(u32); +entity_impl!(DataIndex); + +/// Index type of a passive element segment inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct ElemIndex(u32); +entity_impl!(ElemIndex); + +/// Index type of a type inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, 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, 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, Serialize, Deserialize)] +pub struct InstanceIndex(u32); +entity_impl!(InstanceIndex); + +/// Index type of an event inside the WebAssembly module. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct TagIndex(u32); +entity_impl!(TagIndex); + +/// Specialized index for just module types. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct ModuleTypeIndex(u32); +entity_impl!(ModuleTypeIndex); + +/// Specialized index for just instance types. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub struct InstanceTypeIndex(u32); +entity_impl!(InstanceTypeIndex); + +/// An index of an entity. +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, 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, Serialize, Deserialize)] +pub enum EntityType { + /// A global variable with the specified content type + Global(Global), + /// A linear memory with the specified limits + Memory(Memory), + /// An event definition. + Tag(Tag), + /// 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(SignatureIndex), + /// An instance where the index points to the type section and records a + /// instance's exports. + Instance(InstanceTypeIndex), + /// A module where the index points to the type section and records a + /// module's imports and exports. + Module(ModuleTypeIndex), +} + +/// A WebAssembly global. +/// +/// Note that we record both the original Wasm type and the Cranelift IR type +/// used to represent it. This is because multiple different kinds of Wasm types +/// might be represented with the same Cranelift IR type. For example, both a +/// Wasm `i64` and a `funcref` might be represented with a Cranelift `i64` on +/// 64-bit architectures, and when GC is not required for func refs. +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)] +pub struct Global { + /// The Wasm type of the value stored in the global. + pub wasm_ty: crate::WasmType, + /// A flag indicating whether the value may change at runtime. + pub mutability: bool, + /// The source of the initial value. + pub initializer: GlobalInit, +} + +/// Globals are initialized via the `const` operators or by referring to another import. +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)] +pub enum GlobalInit { + /// An `i32.const`. + I32Const(i32), + /// An `i64.const`. + I64Const(i64), + /// An `f32.const`. + F32Const(u32), + /// An `f64.const`. + F64Const(u64), + /// A `vconst`. + V128Const(u128), + /// A `global.get` of another global. + GetGlobal(GlobalIndex), + /// A `ref.null`. + RefNullConst, + /// A `ref.func `. + RefFunc(FuncIndex), + ///< The global is imported from, and thus initialized by, a different module. + Import, +} + +impl Global { + /// Creates a new `Global` type from wasmparser's representation. + pub fn new(ty: wasmparser::GlobalType, initializer: GlobalInit) -> WasmResult { + Ok(Global { + wasm_ty: ty.content_type.try_into()?, + mutability: ty.mutable, + initializer, + }) + } +} + +/// WebAssembly table. +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)] +pub struct Table { + /// The table elements' Wasm type. + pub wasm_ty: WasmType, + /// The minimum number of elements in the table. + pub minimum: u32, + /// The maximum number of elements in the table. + pub maximum: Option, +} + +impl TryFrom for Table { + type Error = WasmError; + + fn try_from(ty: wasmparser::TableType) -> WasmResult

{ + Ok(Table { + wasm_ty: ty.element_type.try_into()?, + minimum: ty.initial, + maximum: ty.maximum, + }) + } +} + +/// WebAssembly linear memory. +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)] +pub struct Memory { + /// The minimum number of pages in the memory. + pub minimum: u64, + /// The maximum number of pages in the memory. + pub maximum: Option, + /// Whether the memory may be shared between multiple threads. + pub shared: bool, + /// Whether or not this is a 64-bit memory + pub memory64: bool, +} + +impl From for Memory { + fn from(ty: wasmparser::MemoryType) -> Memory { + Memory { + minimum: ty.initial, + maximum: ty.maximum, + shared: ty.shared, + memory64: ty.memory64, + } + } +} + +/// WebAssembly event. +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)] +pub struct Tag { + /// The event signature type. + pub ty: TypeIndex, +} + +impl From for Tag { + fn from(ty: wasmparser::TagType) -> Tag { + Tag { + ty: TypeIndex::from_u32(ty.type_index), + } + } +} diff --git a/crates/wasmtime/src/externals.rs b/crates/wasmtime/src/externals.rs index adb6e19532..7971f34dcb 100644 --- a/crates/wasmtime/src/externals.rs +++ b/crates/wasmtime/src/externals.rs @@ -368,10 +368,7 @@ impl Global { Global(store.store_data_mut().insert(wasmtime_export)) } - pub(crate) fn wasmtime_ty<'a>( - &self, - data: &'a StoreData, - ) -> &'a wasmtime_environ::wasm::Global { + pub(crate) fn wasmtime_ty<'a>(&self, data: &'a StoreData) -> &'a wasmtime_environ::Global { &data[self.0].global } @@ -651,7 +648,7 @@ impl Table { Table(store.store_data_mut().insert(wasmtime_export)) } - pub(crate) fn wasmtime_ty<'a>(&self, data: &'a StoreData) -> &'a wasmtime_environ::wasm::Table { + pub(crate) fn wasmtime_ty<'a>(&self, data: &'a StoreData) -> &'a wasmtime_environ::Table { &data[self.0].table.table } diff --git a/crates/wasmtime/src/func.rs b/crates/wasmtime/src/func.rs index cedba59fbf..aa5c0e579e 100644 --- a/crates/wasmtime/src/func.rs +++ b/crates/wasmtime/src/func.rs @@ -15,7 +15,7 @@ use std::pin::Pin; use std::ptr::NonNull; use std::sync::atomic::Ordering::Relaxed; use std::sync::Arc; -use wasmtime_environ::wasm::{EntityIndex, FuncIndex}; +use wasmtime_environ::{EntityIndex, FuncIndex}; use wasmtime_runtime::{ raise_user_trap, ExportFunction, InstanceAllocator, InstanceHandle, OnDemandInstanceAllocator, VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport, VMSharedSignatureIndex, @@ -1135,7 +1135,7 @@ fn enter_wasm(store: &mut StoreContextMut<'_, T>) -> Result, Tr interrupts.stack_limit.store(usize::max_value(), Relaxed); return Err(Trap::new_wasm( None, - wasmtime_environ::ir::TrapCode::Interrupt, + wasmtime_environ::TrapCode::Interrupt, backtrace::Backtrace::new_unresolved(), )); } diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index bd3e6ebee6..0835a948f3 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -9,12 +9,10 @@ use crate::{ use anyhow::{anyhow, bail, Context, Error, Result}; use std::mem; use std::sync::Arc; -use wasmtime_environ::entity::PrimaryMap; -use wasmtime_environ::wasm::{ - EntityIndex, EntityType, FuncIndex, GlobalIndex, InstanceIndex, MemoryIndex, ModuleIndex, - TableIndex, +use wasmtime_environ::{ + EntityIndex, EntityType, FuncIndex, GlobalIndex, Initializer, InstanceIndex, MemoryIndex, + ModuleIndex, PrimaryMap, TableIndex, }; -use wasmtime_environ::Initializer; use wasmtime_jit::TypeTables; use wasmtime_runtime::{ Imports, InstanceAllocationRequest, InstantiationError, VMContext, VMFunctionBody, diff --git a/crates/wasmtime/src/memory.rs b/crates/wasmtime/src/memory.rs index cba5221498..6e8945005e 100644 --- a/crates/wasmtime/src/memory.rs +++ b/crates/wasmtime/src/memory.rs @@ -480,10 +480,7 @@ impl Memory { Memory(store.store_data_mut().insert(wasmtime_export)) } - pub(crate) fn wasmtime_ty<'a>( - &self, - store: &'a StoreData, - ) -> &'a wasmtime_environ::wasm::Memory { + pub(crate) fn wasmtime_ty<'a>(&self, store: &'a StoreData) -> &'a wasmtime_environ::Memory { &store[self.0].memory.memory } diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 85e2c04350..b523ec326a 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -10,8 +10,7 @@ use std::sync::Arc; use wasmparser::Validator; #[cfg(feature = "cache")] use wasmtime_cache::ModuleCacheEntry; -use wasmtime_environ::entity::PrimaryMap; -use wasmtime_environ::wasm::ModuleIndex; +use wasmtime_environ::{ModuleIndex, PrimaryMap}; use wasmtime_jit::{CompilationArtifacts, CompiledModule, TypeTables}; mod registry; diff --git a/crates/wasmtime/src/module/registry.rs b/crates/wasmtime/src/module/registry.rs index 18bc97a1de..0ff2e5073a 100644 --- a/crates/wasmtime/src/module/registry.rs +++ b/crates/wasmtime/src/module/registry.rs @@ -6,10 +6,7 @@ use std::{ sync::{Arc, RwLock}, }; use wasmtime_environ::{ - entity::EntityRef, - ir::{self, StackMap}, - wasm::DefinedFuncIndex, - FunctionAddressMap, TrapInformation, + DefinedFuncIndex, EntityRef, FilePos, FunctionAddressMap, StackMap, TrapInformation, }; use wasmtime_jit::CompiledModule; use wasmtime_runtime::{ModuleInfo, VMCallerCheckedAnyfunc, VMTrampoline}; @@ -339,10 +336,9 @@ impl GlobalRegisteredModule { // though so we can omit this check in release mode. debug_assert!(pos.is_some(), "failed to find instruction for {:x}", pc); - let instr = match pos { - Some(pos) => info.address_map.instructions[pos].srcloc, - None => info.address_map.start_srcloc, - }; + let instr = pos + .map(|i| info.address_map.instructions[i].srcloc) + .unwrap_or(info.address_map.start_srcloc); // Use our wasm-relative pc to symbolize this frame. If there's a // symbolication context (dwarf debug info) available then we can try to @@ -355,23 +351,25 @@ impl GlobalRegisteredModule { let mut symbols = Vec::new(); if let Some(s) = &self.module.symbolize_context().ok().and_then(|c| c) { - let to_lookup = (instr.bits() as u64) - s.code_section_offset(); - if let Ok(mut frames) = s.addr2line().find_frames(to_lookup) { - while let Ok(Some(frame)) = frames.next() { - symbols.push(FrameSymbol { - name: frame - .function - .as_ref() - .and_then(|l| l.raw_name().ok()) - .map(|s| s.to_string()), - file: frame - .location - .as_ref() - .and_then(|l| l.file) - .map(|s| s.to_string()), - line: frame.location.as_ref().and_then(|l| l.line), - column: frame.location.as_ref().and_then(|l| l.column), - }); + if let Some(offset) = instr.file_offset() { + let to_lookup = u64::from(offset) - s.code_section_offset(); + if let Ok(mut frames) = s.addr2line().find_frames(to_lookup) { + while let Ok(Some(frame)) = frames.next() { + symbols.push(FrameSymbol { + name: frame + .function + .as_ref() + .and_then(|l| l.raw_name().ok()) + .map(|s| s.to_string()), + file: frame + .location + .as_ref() + .and_then(|l| l.file) + .map(|s| s.to_string()), + line: frame.location.as_ref().and_then(|l| l.line), + column: frame.location.as_ref().and_then(|l| l.column), + }); + } } } } @@ -413,8 +411,8 @@ pub struct FrameInfo { module_name: Option, func_index: u32, func_name: Option, - func_start: ir::SourceLoc, - instr: ir::SourceLoc, + func_start: FilePos, + instr: FilePos, symbols: Vec, } @@ -464,7 +462,7 @@ impl FrameInfo { /// The offset here is the offset from the beginning of the original wasm /// module to the instruction that this frame points to. pub fn module_offset(&self) -> usize { - self.instr.bits() as usize + self.instr.file_offset().unwrap_or(u32::MAX) as usize } /// Returns the offset from the original wasm module's function to this @@ -474,7 +472,10 @@ impl FrameInfo { /// function of this frame (within the wasm module) to the instruction this /// frame points to. pub fn func_offset(&self) -> usize { - (self.instr.bits() - self.func_start.bits()) as usize + match self.instr.file_offset() { + Some(i) => (i - self.func_start.file_offset().unwrap()) as usize, + None => u32::MAX as usize, + } } /// Returns the debug symbols found, if any, for this function frame. diff --git a/crates/wasmtime/src/signatures.rs b/crates/wasmtime/src/signatures.rs index 0f4095c3b1..7805ada7a0 100644 --- a/crates/wasmtime/src/signatures.rs +++ b/crates/wasmtime/src/signatures.rs @@ -6,8 +6,7 @@ use std::{ sync::RwLock, }; use std::{convert::TryFrom, sync::Arc}; -use wasmtime_environ::entity::PrimaryMap; -use wasmtime_environ::wasm::{SignatureIndex, WasmFuncType}; +use wasmtime_environ::{PrimaryMap, SignatureIndex, WasmFuncType}; use wasmtime_runtime::{VMSharedSignatureIndex, VMTrampoline}; /// Represents a collection of shared signatures. diff --git a/crates/wasmtime/src/trampoline.rs b/crates/wasmtime/src/trampoline.rs index 8c70163ba9..1cd93931db 100644 --- a/crates/wasmtime/src/trampoline.rs +++ b/crates/wasmtime/src/trampoline.rs @@ -16,7 +16,9 @@ use crate::{GlobalType, MemoryType, TableType, Val}; use anyhow::Result; use std::any::Any; use std::sync::Arc; -use wasmtime_environ::{entity::PrimaryMap, wasm, Module}; +use wasmtime_environ::{ + DefinedFuncIndex, EntityIndex, GlobalIndex, MemoryIndex, Module, PrimaryMap, TableIndex, +}; use wasmtime_runtime::{ Imports, InstanceAllocationRequest, InstanceAllocator, OnDemandInstanceAllocator, VMFunctionBody, VMFunctionImport, VMSharedSignatureIndex, @@ -25,7 +27,7 @@ use wasmtime_runtime::{ fn create_handle( module: Module, store: &mut StoreOpaque<'_>, - finished_functions: PrimaryMap, + finished_functions: PrimaryMap, host_state: Box, func_imports: &[VMFunctionImport], shared_signature_id: Option, @@ -59,7 +61,7 @@ pub fn generate_global_export( val: Val, ) -> Result { let instance = create_global(store, gt, val)?; - let idx = wasm::EntityIndex::Global(wasm::GlobalIndex::from_u32(0)); + let idx = EntityIndex::Global(GlobalIndex::from_u32(0)); match store.instance(instance).lookup_by_declaration(&idx) { wasmtime_runtime::Export::Global(g) => Ok(g), _ => unreachable!(), @@ -71,7 +73,7 @@ pub fn generate_memory_export( m: &MemoryType, ) -> Result { let instance = create_memory(store, m)?; - let idx = wasm::EntityIndex::Memory(wasm::MemoryIndex::from_u32(0)); + let idx = EntityIndex::Memory(MemoryIndex::from_u32(0)); match store.instance(instance).lookup_by_declaration(&idx) { wasmtime_runtime::Export::Memory(m) => Ok(m), _ => unreachable!(), @@ -83,7 +85,7 @@ pub fn generate_table_export( t: &TableType, ) -> Result { let instance = create_table(store, t)?; - let idx = wasm::EntityIndex::Table(wasm::TableIndex::from_u32(0)); + let idx = EntityIndex::Table(TableIndex::from_u32(0)); match store.instance(instance).lookup_by_declaration(&idx) { wasmtime_runtime::Export::Table(t) => Ok(t), _ => unreachable!(), diff --git a/crates/wasmtime/src/trampoline/func.rs b/crates/wasmtime/src/trampoline/func.rs index 9cf91725da..c59de1eddb 100644 --- a/crates/wasmtime/src/trampoline/func.rs +++ b/crates/wasmtime/src/trampoline/func.rs @@ -5,9 +5,7 @@ use anyhow::Result; use std::any::Any; use std::panic::{self, AssertUnwindSafe}; use std::sync::Arc; -use wasmtime_environ::entity::PrimaryMap; -use wasmtime_environ::wasm::SignatureIndex; -use wasmtime_environ::{wasm, Module, ModuleType}; +use wasmtime_environ::{EntityIndex, Module, ModuleType, PrimaryMap, SignatureIndex}; use wasmtime_jit::CodeMemory; use wasmtime_runtime::{ Imports, InstanceAllocationRequest, InstanceAllocator, InstanceHandle, @@ -123,7 +121,7 @@ pub unsafe fn create_raw_function( let func_id = module.functions.push(sig_id); module .exports - .insert(String::new(), wasm::EntityIndex::Function(func_id)); + .insert(String::new(), EntityIndex::Function(func_id)); finished_functions.push(func); Ok( diff --git a/crates/wasmtime/src/trampoline/global.rs b/crates/wasmtime/src/trampoline/global.rs index 1f6080e229..4daf0b158a 100644 --- a/crates/wasmtime/src/trampoline/global.rs +++ b/crates/wasmtime/src/trampoline/global.rs @@ -2,10 +2,8 @@ use crate::store::{InstanceId, StoreOpaque}; use crate::trampoline::create_handle; use crate::{GlobalType, Mutability, Val}; use anyhow::Result; -use wasmtime_environ::entity::PrimaryMap; use wasmtime_environ::{ - wasm::{self, SignatureIndex}, - Module, ModuleType, + EntityIndex, Global, GlobalInit, Module, ModuleType, PrimaryMap, SignatureIndex, }; use wasmtime_runtime::VMFunctionImport; @@ -15,26 +13,26 @@ pub fn create_global(store: &mut StoreOpaque<'_>, gt: &GlobalType, val: Val) -> let mut externref_init = None; let mut shared_signature_id = None; - let global = wasm::Global { + let global = Global { wasm_ty: gt.content().to_wasm_type(), mutability: match gt.mutability() { Mutability::Const => false, Mutability::Var => true, }, initializer: match val { - Val::I32(i) => wasm::GlobalInit::I32Const(i), - Val::I64(i) => wasm::GlobalInit::I64Const(i), - Val::F32(f) => wasm::GlobalInit::F32Const(f), - Val::F64(f) => wasm::GlobalInit::F64Const(f), - Val::V128(i) => wasm::GlobalInit::V128Const(i.into()), - Val::ExternRef(None) | Val::FuncRef(None) => wasm::GlobalInit::RefNullConst, + Val::I32(i) => GlobalInit::I32Const(i), + Val::I64(i) => GlobalInit::I64Const(i), + Val::F32(f) => GlobalInit::F32Const(f), + Val::F64(f) => GlobalInit::F64Const(f), + Val::V128(i) => GlobalInit::V128Const(i.into()), + Val::ExternRef(None) | Val::FuncRef(None) => GlobalInit::RefNullConst, Val::ExternRef(Some(x)) => { // There is no `GlobalInit` variant for using an existing // `externref` that isn't an import (because Wasm can't create // an `externref` by itself). Therefore, initialize the global // as null, and then monkey patch it after instantiation below. externref_init = Some(x); - wasm::GlobalInit::RefNullConst + GlobalInit::RefNullConst } Val::FuncRef(Some(f)) => { // Add a function import to the stub module, and then initialize @@ -51,7 +49,7 @@ pub fn create_global(store: &mut StoreOpaque<'_>, gt: &GlobalType, val: Val) -> .push(wasmtime_environ::Initializer::Import { name: "".into(), field: None, - index: wasm::EntityIndex::Function(func_index), + index: EntityIndex::Function(func_index), }); func_imports.push(VMFunctionImport { @@ -59,7 +57,7 @@ pub fn create_global(store: &mut StoreOpaque<'_>, gt: &GlobalType, val: Val) -> vmctx: f.vmctx, }); - wasm::GlobalInit::RefFunc(func_index) + GlobalInit::RefFunc(func_index) } }, }; @@ -67,7 +65,7 @@ pub fn create_global(store: &mut StoreOpaque<'_>, gt: &GlobalType, val: Val) -> let global_id = module.globals.push(global); module .exports - .insert(String::new(), wasm::EntityIndex::Global(global_id)); + .insert(String::new(), EntityIndex::Global(global_id)); let id = create_handle( module, store, @@ -79,7 +77,7 @@ pub fn create_global(store: &mut StoreOpaque<'_>, gt: &GlobalType, val: Val) -> if let Some(x) = externref_init { let instance = store.instance(id); - match instance.lookup_by_declaration(&wasm::EntityIndex::Global(global_id)) { + match instance.lookup_by_declaration(&EntityIndex::Global(global_id)) { wasmtime_runtime::Export::Global(g) => unsafe { *(*g.definition).as_externref_mut() = Some(x.inner); }, diff --git a/crates/wasmtime/src/trampoline/memory.rs b/crates/wasmtime/src/trampoline/memory.rs index cc43aba6f1..85609ed543 100644 --- a/crates/wasmtime/src/trampoline/memory.rs +++ b/crates/wasmtime/src/trampoline/memory.rs @@ -5,8 +5,7 @@ use crate::MemoryType; use anyhow::{anyhow, Result}; use std::convert::TryFrom; use std::sync::Arc; -use wasmtime_environ::entity::PrimaryMap; -use wasmtime_environ::{wasm, MemoryPlan, MemoryStyle, Module, WASM_PAGE_SIZE}; +use wasmtime_environ::{EntityIndex, MemoryPlan, MemoryStyle, Module, PrimaryMap, WASM_PAGE_SIZE}; use wasmtime_runtime::{RuntimeLinearMemory, RuntimeMemoryCreator, VMMemoryDefinition}; pub fn create_memory(store: &mut StoreOpaque<'_>, memory: &MemoryType) -> Result { @@ -19,7 +18,7 @@ pub fn create_memory(store: &mut StoreOpaque<'_>, memory: &MemoryType) -> Result let memory_id = module.memory_plans.push(memory_plan); module .exports - .insert(String::new(), wasm::EntityIndex::Memory(memory_id)); + .insert(String::new(), EntityIndex::Memory(memory_id)); create_handle(module, store, PrimaryMap::new(), Box::new(()), &[], None) } diff --git a/crates/wasmtime/src/trampoline/table.rs b/crates/wasmtime/src/trampoline/table.rs index d7dadfbf41..1f57ba58e8 100644 --- a/crates/wasmtime/src/trampoline/table.rs +++ b/crates/wasmtime/src/trampoline/table.rs @@ -2,8 +2,7 @@ use crate::store::{InstanceId, StoreOpaque}; use crate::trampoline::create_handle; use crate::TableType; use anyhow::Result; -use wasmtime_environ::entity::PrimaryMap; -use wasmtime_environ::{wasm, Module}; +use wasmtime_environ::{EntityIndex, Module, PrimaryMap}; pub fn create_table(store: &mut StoreOpaque<'_>, table: &TableType) -> Result { let mut module = Module::new(); @@ -15,7 +14,7 @@ pub fn create_table(store: &mut StoreOpaque<'_>, table: &TableType) -> Result Self { + /// Panics if `code` is `EnvTrapCode::User`. + fn from_non_user(code: EnvTrapCode) -> Self { match code { - ir::TrapCode::StackOverflow => TrapCode::StackOverflow, - ir::TrapCode::HeapOutOfBounds => TrapCode::MemoryOutOfBounds, - ir::TrapCode::HeapMisaligned => TrapCode::HeapMisaligned, - ir::TrapCode::TableOutOfBounds => TrapCode::TableOutOfBounds, - ir::TrapCode::IndirectCallToNull => TrapCode::IndirectCallToNull, - ir::TrapCode::BadSignature => TrapCode::BadSignature, - ir::TrapCode::IntegerOverflow => TrapCode::IntegerOverflow, - ir::TrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero, - ir::TrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger, - ir::TrapCode::UnreachableCodeReached => TrapCode::UnreachableCodeReached, - ir::TrapCode::Interrupt => TrapCode::Interrupt, - ir::TrapCode::User(_) => panic!("Called `TrapCode::from_non_user` with user code"), + EnvTrapCode::StackOverflow => TrapCode::StackOverflow, + EnvTrapCode::HeapOutOfBounds => TrapCode::MemoryOutOfBounds, + EnvTrapCode::HeapMisaligned => TrapCode::HeapMisaligned, + EnvTrapCode::TableOutOfBounds => TrapCode::TableOutOfBounds, + EnvTrapCode::IndirectCallToNull => TrapCode::IndirectCallToNull, + EnvTrapCode::BadSignature => TrapCode::BadSignature, + EnvTrapCode::IntegerOverflow => TrapCode::IntegerOverflow, + EnvTrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero, + EnvTrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger, + EnvTrapCode::UnreachableCodeReached => TrapCode::UnreachableCodeReached, + EnvTrapCode::Interrupt => TrapCode::Interrupt, } } } @@ -175,10 +174,10 @@ impl Trap { modules .lookup_trap_info(pc) .map(|info| info.trap_code) - .unwrap_or(ir::TrapCode::StackOverflow) + .unwrap_or(EnvTrapCode::StackOverflow) }); - if maybe_interrupted && code == ir::TrapCode::StackOverflow { - code = ir::TrapCode::Interrupt; + if maybe_interrupted && code == EnvTrapCode::StackOverflow { + code = EnvTrapCode::Interrupt; } Trap::new_wasm(Some(pc), code, backtrace) } @@ -196,7 +195,7 @@ impl Trap { #[cold] // see Trap::new pub(crate) fn new_wasm( trap_pc: Option, - code: ir::TrapCode, + code: EnvTrapCode, backtrace: Backtrace, ) -> Self { let code = TrapCode::from_non_user(code); diff --git a/crates/wasmtime/src/types.rs b/crates/wasmtime/src/types.rs index 03d96109e2..d5cbab5be7 100644 --- a/crates/wasmtime/src/types.rs +++ b/crates/wasmtime/src/types.rs @@ -1,6 +1,5 @@ use std::fmt; -use wasmtime_environ::wasm; -use wasmtime_environ::wasm::{EntityType, WasmFuncType}; +use wasmtime_environ::{EntityType, Global, Memory, Table, WasmFuncType, WasmType}; use wasmtime_jit::TypeTables; pub(crate) mod matching; @@ -71,28 +70,28 @@ impl ValType { } } - pub(crate) fn to_wasm_type(&self) -> wasm::WasmType { + pub(crate) fn to_wasm_type(&self) -> WasmType { match self { - Self::I32 => wasm::WasmType::I32, - Self::I64 => wasm::WasmType::I64, - Self::F32 => wasm::WasmType::F32, - Self::F64 => wasm::WasmType::F64, - Self::V128 => wasm::WasmType::V128, - Self::FuncRef => wasm::WasmType::FuncRef, - Self::ExternRef => wasm::WasmType::ExternRef, + Self::I32 => WasmType::I32, + Self::I64 => WasmType::I64, + Self::F32 => WasmType::F32, + Self::F64 => WasmType::F64, + Self::V128 => WasmType::V128, + Self::FuncRef => WasmType::FuncRef, + Self::ExternRef => WasmType::ExternRef, } } - pub(crate) fn from_wasm_type(ty: &wasm::WasmType) -> Self { + pub(crate) fn from_wasm_type(ty: &WasmType) -> Self { match ty { - wasm::WasmType::I32 => Self::I32, - wasm::WasmType::I64 => Self::I64, - wasm::WasmType::F32 => Self::F32, - wasm::WasmType::F64 => Self::F64, - wasm::WasmType::V128 => Self::V128, - wasm::WasmType::FuncRef => Self::FuncRef, - wasm::WasmType::ExternRef => Self::ExternRef, - wasm::WasmType::ExnRef => unimplemented!(), + WasmType::I32 => Self::I32, + WasmType::I64 => Self::I64, + WasmType::F32 => Self::F32, + WasmType::F64 => Self::F64, + WasmType::V128 => Self::V128, + WasmType::FuncRef => Self::FuncRef, + WasmType::ExternRef => Self::ExternRef, + WasmType::ExnRef => unimplemented!(), } } } @@ -154,10 +153,7 @@ impl ExternType { (Instance(InstanceType) instance unwrap_instance) } - pub(crate) fn from_wasmtime( - types: &TypeTables, - ty: &wasmtime_environ::wasm::EntityType, - ) -> ExternType { + pub(crate) fn from_wasmtime(types: &TypeTables, ty: &EntityType) -> ExternType { match ty { EntityType::Function(idx) => { FuncType::from_wasm_func_type(types.wasm_signatures[*idx].clone()).into() @@ -249,11 +245,11 @@ impl FuncType { self.sig.returns.iter().map(ValType::from_wasm_type) } - pub(crate) fn as_wasm_func_type(&self) -> &wasm::WasmFuncType { + pub(crate) fn as_wasm_func_type(&self) -> &WasmFuncType { &self.sig } - pub(crate) fn from_wasm_func_type(sig: wasm::WasmFuncType) -> FuncType { + pub(crate) fn from_wasm_func_type(sig: WasmFuncType) -> FuncType { Self { sig } } } @@ -293,7 +289,7 @@ impl GlobalType { /// Returns `None` if the wasmtime global has a type that we can't /// represent, but that should only very rarely happen and indicate a bug. - pub(crate) fn from_wasmtime_global(global: &wasm::Global) -> GlobalType { + pub(crate) fn from_wasmtime_global(global: &Global) -> GlobalType { let ty = ValType::from_wasm_type(&global.wasm_ty); let mutability = if global.mutability { Mutability::Var @@ -313,7 +309,7 @@ impl GlobalType { /// which `call_indirect` can invoke other functions. #[derive(Debug, Clone, Hash, Eq, PartialEq)] pub struct TableType { - ty: wasm::Table, + ty: Table, } impl TableType { @@ -321,7 +317,7 @@ impl TableType { /// `element` and have the `limits` applied to its length. pub fn new(element: ValType, min: u32, max: Option) -> TableType { TableType { - ty: wasm::Table { + ty: Table { wasm_ty: element.to_wasm_type(), minimum: min, maximum: max, @@ -347,11 +343,11 @@ impl TableType { self.ty.maximum } - pub(crate) fn from_wasmtime_table(table: &wasm::Table) -> TableType { + pub(crate) fn from_wasmtime_table(table: &Table) -> TableType { TableType { ty: table.clone() } } - pub(crate) fn wasmtime_table(&self) -> &wasm::Table { + pub(crate) fn wasmtime_table(&self) -> &Table { &self.ty } } @@ -364,7 +360,7 @@ impl TableType { /// chunks of addressable memory. #[derive(Debug, Clone, Hash, Eq, PartialEq)] pub struct MemoryType { - ty: wasm::Memory, + ty: Memory, } impl MemoryType { @@ -375,7 +371,7 @@ impl MemoryType { /// WebAssembly pages, which are 64k. pub fn new(minimum: u32, maximum: Option) -> MemoryType { MemoryType { - ty: wasm::Memory { + ty: Memory { memory64: false, shared: false, minimum: minimum.into(), @@ -394,7 +390,7 @@ impl MemoryType { /// WebAssembly which is not standardized yet. pub fn new64(minimum: u64, maximum: Option) -> MemoryType { MemoryType { - ty: wasm::Memory { + ty: Memory { memory64: true, shared: false, minimum, @@ -430,11 +426,11 @@ impl MemoryType { self.ty.maximum } - pub(crate) fn from_wasmtime_memory(memory: &wasm::Memory) -> MemoryType { + pub(crate) fn from_wasmtime_memory(memory: &Memory) -> MemoryType { MemoryType { ty: memory.clone() } } - pub(crate) fn wasmtime_memory(&self) -> &wasm::Memory { + pub(crate) fn wasmtime_memory(&self) -> &Memory { &self.ty } } diff --git a/crates/wasmtime/src/types/matching.rs b/crates/wasmtime/src/types/matching.rs index 2fcc114f48..45b49564a2 100644 --- a/crates/wasmtime/src/types/matching.rs +++ b/crates/wasmtime/src/types/matching.rs @@ -3,7 +3,7 @@ use crate::linker::Definition; use crate::store::StoreInnermost; use crate::{signatures::SignatureCollection, Engine, Extern}; use anyhow::{bail, Context, Result}; -use wasmtime_environ::wasm::{ +use wasmtime_environ::{ EntityType, Global, InstanceTypeIndex, Memory, ModuleTypeIndex, SignatureIndex, Table, }; use wasmtime_jit::TypeTables; diff --git a/scripts/publish.rs b/scripts/publish.rs index 36299cbd42..3c891021e3 100644 --- a/scripts/publish.rs +++ b/scripts/publish.rs @@ -25,6 +25,7 @@ const CRATES_TO_PUBLISH: &[&str] = &[ "peepmatic-souper", // cranelift "cranelift-entity", + "wasmtime-types", "cranelift-bforest", "cranelift-codegen-shared", "cranelift-codegen-meta", @@ -48,9 +49,7 @@ const CRATES_TO_PUBLISH: &[&str] = &[ "wasmtime-fiber", "wasmtime-environ", "wasmtime-runtime", - "wasmtime-debug", "wasmtime-profiling", - "wasmtime-obj", "wasmtime-cranelift", "wasmtime-lightbeam", "wasmtime-jit",