Introduce a TargetFrontendConfig type. (#570)
* Introduce a `TargetFrontendConfig` type. `TargetFrontendConfig` is information specific to the target which is provided to frontends to allow them to produce Cranelift IR for the target. Currently this includes the pointer size and the default calling convention. The default calling convention is now inferred from the target, rather than being a setting. cranelift-native is now just a provider of target information, rather than also being a provider of settings, which gives it a clearer role. And instead of having cranelift-frontend routines require the whole `TargetIsa`, just require the `TargetFrontendConfig`, and add a way to get the `TargetFrontendConfig` from a `Module`. Fixes #529. Fixes #555.
This commit is contained in:
@@ -5,13 +5,12 @@ use cranelift_codegen::cursor::FuncCursor;
|
||||
use cranelift_codegen::ir::immediates::{Imm64, Offset32};
|
||||
use cranelift_codegen::ir::types::*;
|
||||
use cranelift_codegen::ir::{self, InstBuilder};
|
||||
use cranelift_codegen::settings;
|
||||
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||
use cranelift_entity::{EntityRef, PrimaryMap};
|
||||
use environ::{FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, WasmResult};
|
||||
use func_translator::FuncTranslator;
|
||||
use std::string::String;
|
||||
use std::vec::Vec;
|
||||
use target_lexicon::Triple;
|
||||
use translation_utils::{
|
||||
DefinedFuncIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table,
|
||||
TableIndex,
|
||||
@@ -44,11 +43,8 @@ impl<T> Exportable<T> {
|
||||
/// `DummyEnvironment` to allow it to be borrowed separately from the
|
||||
/// `FuncTranslator` field.
|
||||
pub struct DummyModuleInfo {
|
||||
/// Target description.
|
||||
pub triple: Triple,
|
||||
|
||||
/// Compilation setting flags.
|
||||
pub flags: settings::Flags,
|
||||
/// Target description relevant to frontends producing Cranelift IR.
|
||||
config: TargetFrontendConfig,
|
||||
|
||||
/// Signatures as provided by `declare_signature`.
|
||||
pub signatures: PrimaryMap<SignatureIndex, ir::Signature>,
|
||||
@@ -76,11 +72,10 @@ pub struct DummyModuleInfo {
|
||||
}
|
||||
|
||||
impl DummyModuleInfo {
|
||||
/// Allocates the data structures with the given flags.
|
||||
pub fn with_triple_flags(triple: Triple, flags: settings::Flags) -> Self {
|
||||
/// Creates a new `DummyModuleInfo` instance.
|
||||
pub fn new(config: TargetFrontendConfig) -> Self {
|
||||
Self {
|
||||
triple,
|
||||
flags,
|
||||
config,
|
||||
signatures: PrimaryMap::new(),
|
||||
imported_funcs: Vec::new(),
|
||||
functions: PrimaryMap::new(),
|
||||
@@ -111,23 +106,10 @@ pub struct DummyEnvironment {
|
||||
}
|
||||
|
||||
impl DummyEnvironment {
|
||||
/// Allocates the data structures with default flags.
|
||||
pub fn with_triple(triple: Triple) -> Self {
|
||||
Self::with_triple_flags(
|
||||
triple,
|
||||
settings::Flags::new(settings::builder()),
|
||||
ReturnMode::NormalReturns,
|
||||
)
|
||||
}
|
||||
|
||||
/// Allocates the data structures with the given triple.
|
||||
pub fn with_triple_flags(
|
||||
triple: Triple,
|
||||
flags: settings::Flags,
|
||||
return_mode: ReturnMode,
|
||||
) -> Self {
|
||||
/// Creates a new `DummyEnvironment` instance.
|
||||
pub fn new(config: TargetFrontendConfig, return_mode: ReturnMode) -> Self {
|
||||
Self {
|
||||
info: DummyModuleInfo::with_triple_flags(triple, flags),
|
||||
info: DummyModuleInfo::new(config),
|
||||
trans: FuncTranslator::new(),
|
||||
func_bytecode_sizes: Vec::new(),
|
||||
return_mode,
|
||||
@@ -169,12 +151,8 @@ impl<'dummy_environment> DummyFuncEnvironment<'dummy_environment> {
|
||||
}
|
||||
|
||||
impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environment> {
|
||||
fn triple(&self) -> &Triple {
|
||||
&self.mod_info.triple
|
||||
}
|
||||
|
||||
fn flags(&self) -> &settings::Flags {
|
||||
&self.mod_info.flags
|
||||
fn target_config(&self) -> TargetFrontendConfig {
|
||||
self.mod_info.config
|
||||
}
|
||||
|
||||
fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalVariable {
|
||||
@@ -348,8 +326,8 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
||||
}
|
||||
|
||||
impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
||||
fn flags(&self) -> &settings::Flags {
|
||||
&self.info.flags
|
||||
fn target_config(&self) -> &TargetFrontendConfig {
|
||||
&self.info.config
|
||||
}
|
||||
|
||||
fn get_func_name(&self, func_index: FuncIndex) -> ir::ExternalName {
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
//! traits `FunctionEnvironment` and `ModuleEnvironment`.
|
||||
use cranelift_codegen::cursor::FuncCursor;
|
||||
use cranelift_codegen::ir::{self, InstBuilder};
|
||||
use cranelift_codegen::settings::Flags;
|
||||
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||
use std::vec::Vec;
|
||||
use target_lexicon::Triple;
|
||||
use translation_utils::{
|
||||
FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex,
|
||||
};
|
||||
@@ -89,22 +88,19 @@ pub enum ReturnMode {
|
||||
/// IR. The function environment provides information about the WebAssembly module as well as the
|
||||
/// runtime environment.
|
||||
pub trait FuncEnvironment {
|
||||
/// Get the triple for the current compilation.
|
||||
fn triple(&self) -> &Triple;
|
||||
|
||||
/// Get the flags for the current compilation.
|
||||
fn flags(&self) -> &Flags;
|
||||
/// Get the information needed to produce Cranelift IR for the given target.
|
||||
fn target_config(&self) -> TargetFrontendConfig;
|
||||
|
||||
/// Get the Cranelift integer type to use for native pointers.
|
||||
///
|
||||
/// This returns `I64` for 64-bit architectures and `I32` for 32-bit architectures.
|
||||
fn pointer_type(&self) -> ir::Type {
|
||||
ir::Type::int(u16::from(self.triple().pointer_width().unwrap().bits())).unwrap()
|
||||
ir::Type::int(u16::from(self.target_config().pointer_bits())).unwrap()
|
||||
}
|
||||
|
||||
/// Get the size of a native pointer, in bytes.
|
||||
fn pointer_bytes(&self) -> u8 {
|
||||
self.triple().pointer_width().unwrap().bytes()
|
||||
self.target_config().pointer_bytes()
|
||||
}
|
||||
|
||||
/// Set up the necessary preamble definitions in `func` to access the global variable
|
||||
@@ -239,8 +235,8 @@ pub trait FuncEnvironment {
|
||||
/// [`translate_module`](fn.translate_module.html) function. These methods should not be called
|
||||
/// by the user, they are only for `cranelift-wasm` internal use.
|
||||
pub trait ModuleEnvironment<'data> {
|
||||
/// Get the flags for the current compilation.
|
||||
fn flags(&self) -> &Flags;
|
||||
/// Get the information needed to produce Cranelift IR for the current target.
|
||||
fn target_config(&self) -> &TargetFrontendConfig;
|
||||
|
||||
/// Return the name for the given function index.
|
||||
fn get_func_name(&self, func_index: FuncIndex) -> ir::ExternalName;
|
||||
|
||||
@@ -236,11 +236,11 @@ fn cur_srcloc(reader: &BinaryReader) -> ir::SourceLoc {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::FuncTranslator;
|
||||
use super::{FuncTranslator, ReturnMode};
|
||||
use cranelift_codegen::ir::types::I32;
|
||||
use cranelift_codegen::{ir, Context};
|
||||
use environ::{DummyEnvironment, FuncEnvironment};
|
||||
use target_lexicon::Triple;
|
||||
use cranelift_codegen::{ir, isa, settings, Context};
|
||||
use environ::DummyEnvironment;
|
||||
use target_lexicon::PointerWidth;
|
||||
|
||||
#[test]
|
||||
fn small1() {
|
||||
@@ -258,7 +258,15 @@ mod tests {
|
||||
];
|
||||
|
||||
let mut trans = FuncTranslator::new();
|
||||
let runtime = DummyEnvironment::with_triple(Triple::default());
|
||||
let flags = settings::Flags::new(settings::builder());
|
||||
let runtime = DummyEnvironment::new(
|
||||
isa::TargetFrontendConfig {
|
||||
default_call_conv: isa::CallConv::Fast,
|
||||
pointer_width: PointerWidth::U64,
|
||||
},
|
||||
ReturnMode::NormalReturns,
|
||||
);
|
||||
|
||||
let mut ctx = Context::new();
|
||||
|
||||
ctx.func.name = ir::ExternalName::testcase("small1");
|
||||
@@ -269,7 +277,7 @@ mod tests {
|
||||
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())
|
||||
.unwrap();
|
||||
debug!("{}", ctx.func.display(None));
|
||||
ctx.verify(runtime.func_env().flags()).unwrap();
|
||||
ctx.verify(&flags).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -289,7 +297,14 @@ mod tests {
|
||||
];
|
||||
|
||||
let mut trans = FuncTranslator::new();
|
||||
let runtime = DummyEnvironment::with_triple(Triple::default());
|
||||
let flags = settings::Flags::new(settings::builder());
|
||||
let runtime = DummyEnvironment::new(
|
||||
isa::TargetFrontendConfig {
|
||||
default_call_conv: isa::CallConv::Fast,
|
||||
pointer_width: PointerWidth::U64,
|
||||
},
|
||||
ReturnMode::NormalReturns,
|
||||
);
|
||||
let mut ctx = Context::new();
|
||||
|
||||
ctx.func.name = ir::ExternalName::testcase("small2");
|
||||
@@ -300,7 +315,7 @@ mod tests {
|
||||
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())
|
||||
.unwrap();
|
||||
debug!("{}", ctx.func.display(None));
|
||||
ctx.verify(runtime.func_env().flags()).unwrap();
|
||||
ctx.verify(&flags).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -329,7 +344,14 @@ mod tests {
|
||||
];
|
||||
|
||||
let mut trans = FuncTranslator::new();
|
||||
let runtime = DummyEnvironment::with_triple(Triple::default());
|
||||
let flags = settings::Flags::new(settings::builder());
|
||||
let runtime = DummyEnvironment::new(
|
||||
isa::TargetFrontendConfig {
|
||||
default_call_conv: isa::CallConv::Fast,
|
||||
pointer_width: PointerWidth::U64,
|
||||
},
|
||||
ReturnMode::NormalReturns,
|
||||
);
|
||||
let mut ctx = Context::new();
|
||||
|
||||
ctx.func.name = ir::ExternalName::testcase("infloop");
|
||||
@@ -339,6 +361,6 @@ mod tests {
|
||||
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())
|
||||
.unwrap();
|
||||
debug!("{}", ctx.func.display(None));
|
||||
ctx.verify(runtime.func_env().flags()).unwrap();
|
||||
ctx.verify(&flags).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ extern crate cranelift_codegen;
|
||||
#[macro_use]
|
||||
extern crate cranelift_entity;
|
||||
extern crate cranelift_frontend;
|
||||
#[cfg(test)]
|
||||
extern crate target_lexicon;
|
||||
extern crate wasmparser;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ pub fn parse_function_signatures(
|
||||
ref params,
|
||||
ref returns,
|
||||
}) => {
|
||||
let mut sig = Signature::new(environ.flags().call_conv());
|
||||
let mut sig = Signature::new(environ.target_config().default_call_conv);
|
||||
sig.params.extend(params.iter().map(|ty| {
|
||||
let cret_arg: ir::Type = type_to_type(*ty)
|
||||
.expect("only numeric types are supported in function signatures");
|
||||
|
||||
Reference in New Issue
Block a user