Remove dependency on TargetIsa from Wasmtime crates (#3178)
This commit started off by deleting the `cranelift_codegen::settings` reexport in the `wasmtime-environ` crate and then basically played whack-a-mole until everything compiled again. The main result of this is that the `wasmtime-*` family of crates have generally less of a dependency on the `TargetIsa` trait and type from Cranelift. While the dependency isn't entirely severed yet this is at least a significant start. This commit is intended to be largely refactorings, no functional changes are intended here. The refactorings are: * A `CompilerBuilder` trait has been added to `wasmtime_environ` which server as an abstraction used to create compilers and configure them in a uniform fashion. The `wasmtime::Config` type now uses this instead of cranelift-specific settings. The `wasmtime-jit` crate exports the ability to create a compiler builder from a `CompilationStrategy`, which only works for Cranelift right now. In a cranelift-less build of Wasmtime this is expected to return a trait object that fails all requests to compile. * The `Compiler` trait in the `wasmtime_environ` crate has been souped up with a number of methods that Wasmtime and other crates needed. * The `wasmtime-debug` crate is now moved entirely behind the `wasmtime-cranelift` crate. * The `wasmtime-cranelift` crate is now only depended on by the `wasmtime-jit` crate. * Wasm types in `cranelift-wasm` no longer contain their IR type, instead they only contain the `WasmType`. This is required to get everything to align correctly but will also be required in a future refactoring where the types used by `cranelift-wasm` will be extracted to a separate crate. * I moved around a fair bit of code in `wasmtime-cranelift`. * Some gdb-specific jit-specific code has moved from `wasmtime-debug` to `wasmtime-jit`.
This commit is contained in:
@@ -2,10 +2,14 @@
|
||||
//! module.
|
||||
|
||||
use crate::{FunctionAddressMap, FunctionBodyData, ModuleTranslation, Tunables, TypeTables};
|
||||
use cranelift_codegen::{binemit, ir, isa, isa::unwind::UnwindInfo};
|
||||
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::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use thiserror::Error;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
@@ -93,37 +97,173 @@ pub enum CompileError {
|
||||
DebugInfoNotSupported,
|
||||
}
|
||||
|
||||
/// An implementation of a compiler from parsed WebAssembly module to native
|
||||
/// code.
|
||||
/// Abstract trait representing the ability to create a `Compiler` below.
|
||||
///
|
||||
/// This is used in Wasmtime to separate compiler implementations, currently
|
||||
/// mostly used to separate Cranelift from Wasmtime itself.
|
||||
pub trait CompilerBuilder: Send + Sync + fmt::Debug {
|
||||
/// Like the `Clone` trait, but for the boxed trait object.
|
||||
fn clone(&self) -> Box<dyn CompilerBuilder>;
|
||||
|
||||
/// Sets the target of compilation to the target specified.
|
||||
fn target(&mut self, target: target_lexicon::Triple) -> Result<()>;
|
||||
|
||||
/// Returns the currently configured target triple that compilation will
|
||||
/// produce artifacts for.
|
||||
fn triple(&self) -> &target_lexicon::Triple;
|
||||
|
||||
/// Compiler-specific method to configure various settings in the compiler
|
||||
/// itself.
|
||||
///
|
||||
/// This is expected to be defined per-compiler. Compilers should return
|
||||
/// errors for unknown names/values.
|
||||
fn set(&mut self, name: &str, val: &str) -> Result<()>;
|
||||
|
||||
/// Compiler-specific method for configuring settings.
|
||||
///
|
||||
/// Same as [`CompilerBuilder::set`] except for enabling boolean flags.
|
||||
/// Currently cranelift uses this to sometimes enable a family of settings.
|
||||
fn enable(&mut self, name: &str) -> Result<()>;
|
||||
|
||||
/// Returns a list of all possible settings that can be configured with
|
||||
/// [`CompilerBuilder::set`] and [`CompilerBuilder::enable`].
|
||||
fn settings(&self) -> Vec<Setting>;
|
||||
|
||||
/// Builds a new [`Compiler`] object from this configuration.
|
||||
fn build(&self) -> Box<dyn Compiler>;
|
||||
}
|
||||
|
||||
/// Description of compiler settings returned by [`CompilerBuilder::settings`].
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Setting {
|
||||
/// The name of the setting.
|
||||
pub name: &'static str,
|
||||
/// The description of the setting.
|
||||
pub description: &'static str,
|
||||
/// The kind of the setting.
|
||||
pub kind: SettingKind,
|
||||
/// The supported values of the setting (for enum values).
|
||||
pub values: Option<&'static [&'static str]>,
|
||||
}
|
||||
|
||||
/// Different kinds of [`Setting`] values that can be configured in a
|
||||
/// [`CompilerBuilder`]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum SettingKind {
|
||||
/// The setting is an enumeration, meaning it's one of a set of values.
|
||||
Enum,
|
||||
/// The setting is a number.
|
||||
Num,
|
||||
/// The setting is a boolean.
|
||||
Bool,
|
||||
/// The setting is a preset.
|
||||
Preset,
|
||||
}
|
||||
|
||||
/// An implementation of a compiler which can compile WebAssembly functions to
|
||||
/// machine code and perform other miscellaneous tasks needed by the JIT runtime.
|
||||
pub trait Compiler: Send + Sync {
|
||||
/// Compile a function with the given `TargetIsa`.
|
||||
/// Compiles the function `index` within `translation`.
|
||||
///
|
||||
/// The body of the function is available in `data` and configuration
|
||||
/// values are also passed in via `tunables`. Type information in
|
||||
/// `translation` is all relative to `types`.
|
||||
fn compile_function(
|
||||
&self,
|
||||
translation: &ModuleTranslation<'_>,
|
||||
index: DefinedFuncIndex,
|
||||
data: FunctionBodyData<'_>,
|
||||
isa: &dyn isa::TargetIsa,
|
||||
tunables: &Tunables,
|
||||
types: &TypeTables,
|
||||
) -> Result<CompiledFunction, CompileError>;
|
||||
|
||||
/// Creates a trampoline which the host can use to enter wasm. The
|
||||
/// trampoline has type `VMTrampoline` and will call a function of type `ty`
|
||||
/// specified.
|
||||
fn host_to_wasm_trampoline(
|
||||
&self,
|
||||
isa: &dyn isa::TargetIsa,
|
||||
ty: &WasmFuncType,
|
||||
) -> Result<CompiledFunction, CompileError>;
|
||||
/// Creates a trampoline which the host can use to enter wasm.
|
||||
///
|
||||
/// The generated trampoline will have the type `VMTrampoline` and will
|
||||
/// call a function of type `ty` specified.
|
||||
fn host_to_wasm_trampoline(&self, ty: &WasmFuncType) -> Result<CompiledFunction, CompileError>;
|
||||
|
||||
/// Creates a trampoline suitable for a wasm module to import.
|
||||
///
|
||||
/// The trampoline has the type specified by `ty` and will call the function
|
||||
/// `host_fn` which has type `VMTrampoline`.
|
||||
/// `host_fn` which has type `VMTrampoline`. Note that `host_fn` is
|
||||
/// directly embedded into the generated code so this is not suitable for a
|
||||
/// cached value or if `host_fn` does not live as long as the compiled
|
||||
/// function.
|
||||
///
|
||||
/// This is primarily used for `Func::new` in `wasmtime`.
|
||||
fn wasm_to_host_trampoline(
|
||||
&self,
|
||||
isa: &dyn isa::TargetIsa,
|
||||
ty: &WasmFuncType,
|
||||
host_fn: usize,
|
||||
) -> Result<CompiledFunction, CompileError>;
|
||||
|
||||
/// Creates DWARF debugging data for a compilation unit.
|
||||
///
|
||||
/// This function maps DWARF information found in a wasm module to native
|
||||
/// DWARF debugging information. This is currently implemented by the
|
||||
/// `wasmtime-debug` crate.
|
||||
fn emit_dwarf(
|
||||
&self,
|
||||
debuginfo_data: &crate::DebugInfoData,
|
||||
funcs: &CompiledFunctions,
|
||||
memory_offset: &crate::ModuleMemoryOffset,
|
||||
) -> Result<Vec<DwarfSection>>;
|
||||
|
||||
/// Returns the target triple that this compiler is compiling for.
|
||||
fn triple(&self) -> &target_lexicon::Triple;
|
||||
|
||||
/// If supported by the target creates a SystemV CIE used for dwarf
|
||||
/// unwinding information.
|
||||
fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry>;
|
||||
|
||||
/// Returns a list of configured settings for this compiler.
|
||||
fn flags(&self) -> HashMap<String, FlagValue>;
|
||||
|
||||
/// Same as [`Compiler::flags`], but ISA-specific (a cranelift-ism)
|
||||
fn isa_flags(&self) -> HashMap<String, FlagValue>;
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub struct DwarfSection {
|
||||
pub name: &'static str,
|
||||
pub body: Vec<u8>,
|
||||
pub relocs: Vec<DwarfSectionReloc>,
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone)]
|
||||
pub struct DwarfSectionReloc {
|
||||
pub target: DwarfSectionRelocTarget,
|
||||
pub offset: u32,
|
||||
pub addend: i32,
|
||||
pub size: u8,
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone)]
|
||||
pub enum DwarfSectionRelocTarget {
|
||||
Func(usize),
|
||||
Section(&'static str),
|
||||
}
|
||||
|
||||
/// Value of a configured setting for a [`Compiler`]
|
||||
#[derive(Serialize, Deserialize, Hash, Eq, PartialEq)]
|
||||
pub enum FlagValue {
|
||||
/// Name of the value that has been configured for this setting.
|
||||
Enum(Cow<'static, str>),
|
||||
/// The numerical value of the configured settings.
|
||||
Num(u8),
|
||||
/// Whether the setting is on or off.
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
impl fmt::Display for FlagValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::Enum(v) => v.fmt(f),
|
||||
Self::Num(v) => v.fmt(f),
|
||||
Self::Bool(v) => v.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,6 @@ pub mod ir {
|
||||
pub use cranelift_codegen::{ValueLabelsRanges, ValueLocRange};
|
||||
}
|
||||
|
||||
pub mod settings {
|
||||
pub use cranelift_codegen::settings::{
|
||||
builder, Builder, Configurable, Flags, OptLevel, SetError, Setting, SettingKind, Value,
|
||||
};
|
||||
}
|
||||
|
||||
pub mod isa {
|
||||
pub use cranelift_codegen::isa::{
|
||||
lookup, unwind, Builder, CallConv, RegUnit, TargetFrontendConfig, TargetIsa,
|
||||
|
||||
@@ -3,15 +3,13 @@ use crate::module::{
|
||||
ModuleSignature, ModuleType, ModuleUpvar, TableInitializer, TablePlan, TypeTables,
|
||||
};
|
||||
use crate::tunables::Tunables;
|
||||
use cranelift_codegen::ir;
|
||||
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||
use cranelift_codegen::packed_option::ReservedValue;
|
||||
use cranelift_entity::PrimaryMap;
|
||||
use cranelift_wasm::{
|
||||
self, translate_module, Alias, DataIndex, DefinedFuncIndex, ElemIndex, EntityIndex, EntityType,
|
||||
FuncIndex, Global, GlobalIndex, GlobalInit, InstanceIndex, InstanceTypeIndex, Memory,
|
||||
MemoryIndex, ModuleIndex, ModuleTypeIndex, SignatureIndex, Table, TableIndex,
|
||||
TargetEnvironment, TypeIndex, WasmError, WasmFuncType, WasmResult,
|
||||
MemoryIndex, ModuleIndex, ModuleTypeIndex, SignatureIndex, Table, TableIndex, TypeIndex,
|
||||
WasmError, WasmFuncType, WasmResult,
|
||||
};
|
||||
use std::collections::{hash_map::Entry, HashMap};
|
||||
use std::convert::TryFrom;
|
||||
@@ -45,7 +43,6 @@ pub struct ModuleEnvironment<'data> {
|
||||
|
||||
// Various bits and pieces of configuration
|
||||
features: WasmFeatures,
|
||||
target_config: TargetFrontendConfig,
|
||||
tunables: Tunables,
|
||||
first_module: bool,
|
||||
}
|
||||
@@ -134,18 +131,13 @@ pub struct FunctionMetadata {
|
||||
|
||||
impl<'data> ModuleEnvironment<'data> {
|
||||
/// Allocates the environment data structures.
|
||||
pub fn new(
|
||||
target_config: TargetFrontendConfig,
|
||||
tunables: &Tunables,
|
||||
features: &WasmFeatures,
|
||||
) -> Self {
|
||||
pub fn new(tunables: &Tunables, features: &WasmFeatures) -> Self {
|
||||
Self {
|
||||
result: ModuleTranslation::default(),
|
||||
results: Vec::with_capacity(1),
|
||||
in_progress: Vec::new(),
|
||||
modules_to_be: 1,
|
||||
types: Default::default(),
|
||||
target_config,
|
||||
tunables: tunables.clone(),
|
||||
features: *features,
|
||||
first_module: true,
|
||||
@@ -153,10 +145,6 @@ impl<'data> ModuleEnvironment<'data> {
|
||||
}
|
||||
}
|
||||
|
||||
fn pointer_type(&self) -> ir::Type {
|
||||
self.target_config.pointer_type()
|
||||
}
|
||||
|
||||
/// Translate a wasm module using this environment.
|
||||
///
|
||||
/// This consumes the `ModuleEnvironment` and produces a list of
|
||||
@@ -378,16 +366,6 @@ impl<'data> ModuleEnvironment<'data> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'data> TargetEnvironment for ModuleEnvironment<'data> {
|
||||
fn target_config(&self) -> TargetFrontendConfig {
|
||||
self.target_config
|
||||
}
|
||||
|
||||
fn reference_type(&self, ty: cranelift_wasm::WasmType) -> ir::Type {
|
||||
crate::reference_type(ty, self.pointer_type())
|
||||
}
|
||||
}
|
||||
|
||||
/// This trait is useful for `translate_module` because it tells how to translate
|
||||
/// environment-dependent wasm instructions. These functions should not be called by the user.
|
||||
impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data> {
|
||||
|
||||
Reference in New Issue
Block a user