Remove wasmtime-environ's dependency on cranelift-codegen (#3199)

* Move `CompiledFunction` into wasmtime-cranelift

This commit moves the `wasmtime_environ::CompiledFunction` type into the
`wasmtime-cranelift` crate. This type has lots of Cranelift-specific
pieces of compilation and doesn't need to be generated by all Wasmtime
compilers. This replaces the usage in the `Compiler` trait with a
`Box<Any>` type that each compiler can select. Each compiler must still
produce a `FunctionInfo`, however, which is shared information we'll
deserialize for each module.

The `wasmtime-debug` crate is also folded into the `wasmtime-cranelift`
crate as a result of this commit. One possibility was to move the
`CompiledFunction` commit into its own crate and have `wasmtime-debug`
depend on that, but since `wasmtime-debug` is Cranelift-specific at this
time it didn't seem like it was too too necessary to keep it separate.
If `wasmtime-debug` supports other backends in the future we can
recreate a new crate, perhaps with it refactored to not depend on
Cranelift.

* Move wasmtime_environ::reference_type

This now belongs in wasmtime-cranelift and nowhere else

* Remove `Type` reexport in wasmtime-environ

One less dependency on `cranelift-codegen`!

* Remove `types` reexport from `wasmtime-environ`

Less cranelift!

* Remove `SourceLoc` from wasmtime-environ

Change the `srcloc`, `start_srcloc`, and `end_srcloc` fields to a custom
`FilePos` type instead of `ir::SourceLoc`. These are only used in a few
places so there's not much to lose from an extra abstraction for these
leaf use cases outside of cranelift.

* Remove wasmtime-environ's dep on cranelift's `StackMap`

This commit "clones" the `StackMap` data structure in to
`wasmtime-environ` to have an independent representation that that
chosen by Cranelift. This allows Wasmtime to decouple this runtime
dependency of stack map information and let the two evolve
independently, if necessary.

An alternative would be to refactor cranelift's implementation into a
separate crate and have wasmtime depend on that but it seemed a bit like
overkill to do so and easier to clone just a few lines for this.

* Define code offsets in wasmtime-environ with `u32`

Don't use Cranelift's `binemit::CodeOffset` alias to define this field
type since the `wasmtime-environ` crate will be losing the
`cranelift-codegen` dependency soon.

* Commit to using `cranelift-entity` in Wasmtime

This commit removes the reexport of `cranelift-entity` from the
`wasmtime-environ` crate and instead directly depends on the
`cranelift-entity` crate in all referencing crates. The original reason
for the reexport was to make cranelift version bumps easier since it's
less versions to change, but nowadays we have a script to do that.
Otherwise this encourages crates to use whatever they want from
`cranelift-entity` since  we'll always depend on the whole crate.

It's expected that the `cranelift-entity` crate will continue to be a
lean crate in dependencies and suitable for use at both runtime and
compile time. Consequently there's no need to avoid its usage in
Wasmtime at runtime, since "remove Cranelift at compile time" is
primarily about the `cranelift-codegen` crate.

* Remove most uses of `cranelift-codegen` in `wasmtime-environ`

There's only one final use remaining, which is the reexport of
`TrapCode`, which will get handled later.

* Limit the glob-reexport of `cranelift_wasm`

This commit removes the glob reexport of `cranelift-wasm` from the
`wasmtime-environ` crate. This is intended to explicitly define what
we're reexporting and is a transitionary step to curtail the amount of
dependencies taken on `cranelift-wasm` throughout the codebase. For
example some functions used by debuginfo mapping are better imported
directly from the crate since they're Cranelift-specific. Note that
this is intended to be a temporary state affairs, soon this reexport
will be gone entirely.

Additionally this commit reduces imports from `cranelift_wasm` and also
primarily imports from `crate::wasm` within `wasmtime-environ` to get a
better sense of what's imported from where and what will need to be
shared.

* Extract types from cranelift-wasm to cranelift-wasm-types

This commit creates a new crate called `cranelift-wasm-types` and
extracts type definitions from the `cranelift-wasm` crate into this new
crate. The purpose of this crate is to be a shared definition of wasm
types that can be shared both by compilers (like Cranelift) as well as
wasm runtimes (e.g. Wasmtime). This new `cranelift-wasm-types` crate
doesn't depend on `cranelift-codegen` and is the final step in severing
the unconditional dependency from Wasmtime to `cranelift-codegen`.

The final refactoring in this commit is to then reexport this crate from
`wasmtime-environ`, delete the `cranelift-codegen` dependency, and then
update all `use` paths to point to these new types.

The main change of substance here is that the `TrapCode` enum is
mirrored from Cranelift into this `cranelift-wasm-types` crate. While
this unfortunately results in three definitions (one more which is
non-exhaustive in Wasmtime itself) it's hopefully not too onerous and
ideally something we can patch up in the future.

* Get lightbeam compiling

* Remove unnecessary dependency

* Fix compile with uffd

* Update publish script

* Fix more uffd tests

* Rename cranelift-wasm-types to wasmtime-types

This reflects the purpose a bit more where it's types specifically
intended for Wasmtime and its support.

* Fix publish script
This commit is contained in:
Alex Crichton
2021-08-18 13:14:52 -05:00
committed by GitHub
parent 02ecfed7a0
commit 87c33c2969
85 changed files with 1062 additions and 1232 deletions

31
Cargo.lock generated
View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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};

View File

@@ -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};

View File

@@ -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,
};

View File

@@ -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<wasmparser::Type> for WasmType {
type Error = WasmError;
fn try_from(ty: wasmparser::Type) -> Result<Self, Self::Error> {
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<WasmType> 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<wasmparser::FuncType> for WasmFuncType {
type Error = WasmError;
fn try_from(ty: wasmparser::FuncType) -> Result<Self, Self::Error> {
Ok(Self {
params: ty
.params
.into_vec()
.into_iter()
.map(WasmType::try_from)
.collect::<Result<_, Self::Error>>()?,
returns: ty
.returns
.into_vec()
.into_iter()
.map(WasmType::try_from)
.collect::<Result<_, Self::Error>>()?,
})
}
}
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<BinaryReaderError> 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<T> = Result<T, WasmError>;
/// How to return from functions.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ReturnMode {

View File

@@ -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};

View File

@@ -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

View File

@@ -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};

View File

@@ -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 } => {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 <index>`.
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<Global> {
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<u32>,
}
impl TryFrom<wasmparser::TableType> for Table {
type Error = WasmError;
fn try_from(ty: wasmparser::TableType) -> WasmResult<Table> {
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<u64>,
/// 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<wasmparser::MemoryType> 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<wasmparser::TagType> 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<PE: TargetEnvironment + ?Sized>(
ty: wasmparser::Type,

View File

@@ -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"]

View File

@@ -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<CompiledFunction, CompileError> {
) -> Result<Box<dyn Any + Send>, 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<DefinedFuncIndex, Box<dyn Any + Send>>,
emit_dwarf: bool,
) -> Result<Vec<u8>> {
) -> Result<(Vec<u8>, PrimaryMap<DefinedFuncIndex, FunctionInfo>)> {
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<Vec<u8>> {
@@ -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,

View File

@@ -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;

View File

@@ -1,4 +1,4 @@
use crate::transform::AddressTransform;
use crate::debug::transform::AddressTransform;
use gimli::constants;
use gimli::read;
use gimli::{Reader, UnitSectionOffset};

View File

@@ -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<DefinedFuncIndex, FunctionMap> {
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();

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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,

View File

@@ -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";

View File

@@ -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<T> {
stack: Vec<(usize, T)>,

View File

@@ -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.

View File

@@ -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 {

View File

@@ -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,
});

View File

@@ -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<DefinedFuncIndex, CompiledFunction>;
/// Compiled function: machine code body, jump table offsets, and unwind information.
#[derive(Default)]
pub struct CompiledFunction {
/// The machine code for this function.
body: Vec<u8>,
/// The jump tables offsets (in the body).
jt_offsets: ir::JumpTableOffsets,
/// The unwind information.
unwind_info: Option<UnwindInfo>,
relocations: Vec<Relocation>,
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"),
}
}

View File

@@ -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,

View File

@@ -1,3 +0,0 @@
target/
**/*.rs.bk
Cargo.lock

View File

@@ -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" }

View File

@@ -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.

View File

@@ -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"

View File

@@ -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<u32> {
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 {

View File

@@ -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<DefinedFuncIndex, CompiledFunction>;
/// 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<u8>,
/// The jump tables offsets (in the body).
pub jt_offsets: ir::JumpTableOffsets,
/// The unwind information.
pub unwind_info: Option<UnwindInfo>,
pub relocations: Vec<Relocation>,
pub address_map: FunctionAddressMap,
pub value_labels_ranges: cranelift_codegen::ValueLabelsRanges,
pub stack_slots: ir::StackSlots,
pub struct FunctionInfo {
pub traps: Vec<TrapInformation>,
pub address_map: FunctionAddressMap,
pub stack_maps: Vec<StackMapInformation>,
}
/// 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<CompiledFunction, CompileError>;
) -> Result<Box<dyn Any + Send>, 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<DefinedFuncIndex, Box<dyn Any + Send>>,
emit_dwarf: bool,
) -> Result<Vec<u8>>;
) -> Result<(Vec<u8>, PrimaryMap<DefinedFuncIndex, FunctionInfo>)>;
/// 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.

View File

@@ -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::*;
}

View File

@@ -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 {

View File

@@ -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,
}

View File

@@ -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 } => {

View File

@@ -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_";

View File

@@ -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<Item = u32>) -> 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
}
}

View File

@@ -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<P: PtrSize> VMOffsets<P> {
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`.

View File

@@ -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 {

View File

@@ -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<u8>,
pub funcs: CompiledFunctions,
pub funcs: PrimaryMap<DefinedFuncIndex, FunctionInfo>,
}
impl Compiler {
@@ -111,12 +111,12 @@ impl Compiler {
.compile_function(translation, index, func, &self.tunables, types)
})?
.into_iter()
.collect::<CompiledFunctions>();
.collect();
let obj = self.compiler.emit_obj(
let (obj, funcs) = self.compiler.emit_obj(
&translation,
types,
&funcs,
funcs,
self.tunables.generate_native_debuginfo,
)?;

View File

@@ -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<DefinedFuncIndex, *mut [VMFunctionBody]>);
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<TrapInformation>,
pub address_map: FunctionAddressMap,
pub stack_maps: Vec<StackMapInformation>,
}
/// 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)]

View File

@@ -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;

View File

@@ -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<CompiledFunction, CompileError> {
) -> Result<Box<dyn Any + Send>, 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<DefinedFuncIndex, Box<dyn Any + Send>>,
_emit_dwarf: bool,
) -> Result<Vec<u8>> {
) -> Result<(Vec<u8>, PrimaryMap<DefinedFuncIndex, FunctionInfo>)> {
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<Relocation>,
// /// Relocations recorded for the function.
// func_relocs: Vec<Relocation>,
}
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,
// });
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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! {

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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.
///

View File

@@ -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<usize, Trap> {
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())

View File

@@ -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)

View File

@@ -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]

View File

@@ -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]

View File

@@ -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.
///

View File

@@ -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;

View File

@@ -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!(

View File

@@ -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,

15
crates/types/Cargo.toml Normal file
View File

@@ -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 }

59
crates/types/src/error.rs Normal file
View File

@@ -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<wasmparser::BinaryReaderError> 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<T> = Result<T, WasmError>;

337
crates/types/src/lib.rs Normal file
View File

@@ -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<wasmparser::Type> for WasmType {
type Error = WasmError;
fn try_from(ty: wasmparser::Type) -> Result<Self, Self::Error> {
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<WasmType> 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<wasmparser::FuncType> for WasmFuncType {
type Error = WasmError;
fn try_from(ty: wasmparser::FuncType) -> Result<Self, Self::Error> {
Ok(Self {
params: ty
.params
.into_vec()
.into_iter()
.map(WasmType::try_from)
.collect::<Result<_, Self::Error>>()?,
returns: ty
.returns
.into_vec()
.into_iter()
.map(WasmType::try_from)
.collect::<Result<_, Self::Error>>()?,
})
}
}
/// 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 <index>`.
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<Global> {
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<u32>,
}
impl TryFrom<wasmparser::TableType> for Table {
type Error = WasmError;
fn try_from(ty: wasmparser::TableType) -> WasmResult<Table> {
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<u64>,
/// 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<wasmparser::MemoryType> 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<wasmparser::TagType> for Tag {
fn from(ty: wasmparser::TagType) -> Tag {
Tag {
ty: TypeIndex::from_u32(ty.type_index),
}
}
}

View File

@@ -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
}

View File

@@ -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<T>(store: &mut StoreContextMut<'_, T>) -> Result<Option<usize>, 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(),
));
}

View File

@@ -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,

View File

@@ -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
}

View File

@@ -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;

View File

@@ -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<String>,
func_index: u32,
func_name: Option<String>,
func_start: ir::SourceLoc,
instr: ir::SourceLoc,
func_start: FilePos,
instr: FilePos,
symbols: Vec<FrameSymbol>,
}
@@ -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.

View File

@@ -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.

View File

@@ -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<wasm::DefinedFuncIndex, *mut [VMFunctionBody]>,
finished_functions: PrimaryMap<DefinedFuncIndex, *mut [VMFunctionBody]>,
host_state: Box<dyn Any + Send + Sync>,
func_imports: &[VMFunctionImport],
shared_signature_id: Option<VMSharedSignatureIndex>,
@@ -59,7 +61,7 @@ pub fn generate_global_export(
val: Val,
) -> Result<wasmtime_runtime::ExportGlobal> {
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<wasmtime_runtime::ExportMemory> {
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<wasmtime_runtime::ExportTable> {
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!(),

View File

@@ -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(

View File

@@ -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);
},

View File

@@ -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<InstanceId> {
@@ -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)
}

View File

@@ -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<InstanceId> {
let mut module = Module::new();
@@ -15,7 +14,7 @@ pub fn create_table(store: &mut StoreOpaque<'_>, table: &TableType) -> Result<In
// TODO: can this `exports.insert` get removed?
module
.exports
.insert(String::new(), wasm::EntityIndex::Table(table_id));
.insert(String::new(), EntityIndex::Table(table_id));
create_handle(module, store, PrimaryMap::new(), Box::new(()), &[], None)
}

View File

@@ -3,7 +3,7 @@ use crate::FrameInfo;
use backtrace::Backtrace;
use std::fmt;
use std::sync::Arc;
use wasmtime_environ::ir;
use wasmtime_environ::TrapCode as EnvTrapCode;
/// A struct representing an aborted instruction execution, with a message
/// indicating the cause.
@@ -88,21 +88,20 @@ pub enum TrapCode {
}
impl TrapCode {
/// Panics if `code` is `ir::TrapCode::User`.
fn from_non_user(code: ir::TrapCode) -> 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<usize>,
code: ir::TrapCode,
code: EnvTrapCode,
backtrace: Backtrace,
) -> Self {
let code = TrapCode::from_non_user(code);

View File

@@ -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<u32>) -> 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<u32>) -> 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<u64>) -> 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
}
}

View File

@@ -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;

View File

@@ -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",