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:
Alex Crichton
2021-08-16 09:55:39 -05:00
committed by GitHub
parent 7c0948fe0b
commit 0313e30d76
47 changed files with 1529 additions and 1384 deletions

View File

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

View File

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

View File

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