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:
@@ -2,7 +2,6 @@ test legalizer
|
||||
|
||||
; Pre-SSE 4.1, we need to use runtime library calls for floating point rounding operations.
|
||||
set is_pic
|
||||
set call_conv=system_v
|
||||
target x86_64
|
||||
|
||||
function %floor(f32) -> f32 {
|
||||
|
||||
@@ -11,6 +11,7 @@ cargo-fuzz = true
|
||||
cargo-fuzz = "*"
|
||||
binaryen = { git = "https://github.com/pepyakin/binaryen-rs.git" }
|
||||
libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" }
|
||||
cranelift-codegen = { path = "../lib/codegen" }
|
||||
cranelift-wasm = { path = "../lib/wasm" }
|
||||
cranelift-reader = { path = "../lib/reader" }
|
||||
target-lexicon = "0.0.3"
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate libfuzzer_sys;
|
||||
extern crate binaryen;
|
||||
extern crate cranelift_codegen;
|
||||
extern crate cranelift_wasm;
|
||||
#[macro_use]
|
||||
extern crate target_lexicon;
|
||||
use cranelift_wasm::{translate_module, DummyEnvironment};
|
||||
|
||||
use cranelift_codegen::{isa, settings};
|
||||
use cranelift_wasm::{translate_module, DummyEnvironment, ReturnMode};
|
||||
use std::str::FromStr;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
@@ -13,6 +17,9 @@ fuzz_target!(|data: &[u8]| {
|
||||
|
||||
let wasm = binaryen_module.write();
|
||||
|
||||
let mut dummy_environ = DummyEnvironment::with_triple(triple!("x86_64"));
|
||||
let flags = settings::Flags::new(settings::builder());
|
||||
let triple = triple!("x86_64");
|
||||
let isa = isa::lookup(triple).unwrap().finish(flags);
|
||||
let mut dummy_environ = DummyEnvironment::new(isa.frontend_config(), ReturnMode::NormalReturns);
|
||||
translate_module(&wasm, &mut dummy_environ).unwrap();
|
||||
});
|
||||
|
||||
@@ -106,11 +106,7 @@ fn handle_module(
|
||||
}
|
||||
};
|
||||
|
||||
let mut dummy_environ = DummyEnvironment::with_triple_flags(
|
||||
isa.triple().clone(),
|
||||
fisa.flags.clone(),
|
||||
ReturnMode::NormalReturns,
|
||||
);
|
||||
let mut dummy_environ = DummyEnvironment::new(isa.frontend_config(), ReturnMode::NormalReturns);
|
||||
translate_module(&module_binary, &mut dummy_environ).map_err(|e| e.to_string())?;
|
||||
|
||||
let _ = terminal.fg(term::color::GREEN);
|
||||
|
||||
@@ -27,30 +27,6 @@ enable_verifier = BoolSetting(
|
||||
""",
|
||||
default=True)
|
||||
|
||||
call_conv = EnumSetting(
|
||||
"""
|
||||
Default calling convention:
|
||||
|
||||
- fast: not-ABI-stable convention for best performance
|
||||
- cold: not-ABI-stable convention for infrequently executed code
|
||||
- system_v: System V-style convention used on many platforms
|
||||
- windows_fastcall: Windows "fastcall" convention, also used for
|
||||
x64 and ARM
|
||||
- baldrdash: SpiderMonkey WebAssembly convention
|
||||
- probestack: specialized convention for the probestack function
|
||||
|
||||
The default calling convention may be overridden by individual
|
||||
functions.
|
||||
""",
|
||||
|
||||
'fast',
|
||||
'cold',
|
||||
'system_v',
|
||||
'windows_fastcall',
|
||||
'baldrdash',
|
||||
'probestack'
|
||||
)
|
||||
|
||||
# Note that Cranelift doesn't currently need an is_pie flag, because PIE is
|
||||
# just PIC where symbols can't be pre-empted, which can be expressed with the
|
||||
# `colocated` flag on external functions and global values.
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
//! This module declares the data types used to represent external functions and call signatures.
|
||||
|
||||
use ir::{ArgumentLoc, ExternalName, SigRef, Type};
|
||||
use isa::{RegInfo, RegUnit};
|
||||
use settings::CallConv;
|
||||
use isa::{CallConv, RegInfo, RegUnit};
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use std::vec::Vec;
|
||||
|
||||
@@ -13,9 +13,8 @@ use ir::{
|
||||
};
|
||||
use ir::{EbbOffsets, InstEncodings, SourceLocs, StackSlots, ValueLocations};
|
||||
use ir::{JumpTableOffsets, JumpTables};
|
||||
use isa::{EncInfo, Encoding, Legalize, TargetIsa};
|
||||
use isa::{CallConv, EncInfo, Encoding, Legalize, TargetIsa};
|
||||
use regalloc::RegDiversions;
|
||||
use settings::CallConv;
|
||||
use std::fmt;
|
||||
use write::write_function;
|
||||
|
||||
|
||||
@@ -4,8 +4,7 @@ use ir::{
|
||||
types, AbiParam, ArgumentPurpose, ExtFuncData, ExternalName, FuncRef, Function, Inst, Opcode,
|
||||
Signature, Type,
|
||||
};
|
||||
use isa::{RegUnit, TargetIsa};
|
||||
use settings::CallConv;
|
||||
use isa::{CallConv, RegUnit, TargetIsa};
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -166,8 +165,7 @@ fn make_funcref_for_inst(
|
||||
inst: Inst,
|
||||
isa: &TargetIsa,
|
||||
) -> FuncRef {
|
||||
// Start with a fast calling convention. We'll give the ISA a chance to change it.
|
||||
let mut sig = Signature::new(isa.flags().call_conv());
|
||||
let mut sig = Signature::new(isa.default_call_conv());
|
||||
for &v in func.dfg.inst_args(inst) {
|
||||
sig.params.push(AbiParam::new(func.dfg.value_type(v)));
|
||||
}
|
||||
|
||||
74
lib/codegen/src/isa/call_conv.rs
Normal file
74
lib/codegen/src/isa/call_conv.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
use std::fmt;
|
||||
use std::str;
|
||||
use target_lexicon::{OperatingSystem, Triple};
|
||||
|
||||
/// Calling convention identifiers.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum CallConv {
|
||||
/// Best performance, not ABI-stable
|
||||
Fast,
|
||||
/// Smallest caller code size, not ABI-stable
|
||||
Cold,
|
||||
/// System V-style convention used on many platforms
|
||||
SystemV,
|
||||
/// Windows "fastcall" convention, also used for x64 and ARM
|
||||
WindowsFastcall,
|
||||
/// SpiderMonkey WebAssembly convention
|
||||
Baldrdash,
|
||||
/// Specialized convention for the probestack function
|
||||
Probestack,
|
||||
}
|
||||
|
||||
impl CallConv {
|
||||
/// Return the default calling convention for the given target triple.
|
||||
pub fn default_for_triple(triple: &Triple) -> Self {
|
||||
match triple.operating_system {
|
||||
OperatingSystem::Unknown
|
||||
| OperatingSystem::Bitrig
|
||||
| OperatingSystem::Cloudabi
|
||||
| OperatingSystem::Darwin
|
||||
| OperatingSystem::Dragonfly
|
||||
| OperatingSystem::Freebsd
|
||||
| OperatingSystem::Fuchsia
|
||||
| OperatingSystem::Haiku
|
||||
| OperatingSystem::Ios
|
||||
| OperatingSystem::L4re
|
||||
| OperatingSystem::Linux
|
||||
| OperatingSystem::Nebulet
|
||||
| OperatingSystem::Netbsd
|
||||
| OperatingSystem::Openbsd
|
||||
| OperatingSystem::Redox
|
||||
| OperatingSystem::Solaris => CallConv::SystemV,
|
||||
OperatingSystem::Windows => CallConv::WindowsFastcall,
|
||||
os => panic!("unsupported operating system: {}", os),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CallConv {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(match *self {
|
||||
CallConv::Fast => "fast",
|
||||
CallConv::Cold => "cold",
|
||||
CallConv::SystemV => "system_v",
|
||||
CallConv::WindowsFastcall => "windows_fastcall",
|
||||
CallConv::Baldrdash => "baldrdash",
|
||||
CallConv::Probestack => "probestack",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for CallConv {
|
||||
type Err = ();
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"fast" => Ok(CallConv::Fast),
|
||||
"cold" => Ok(CallConv::Cold),
|
||||
"system_v" => Ok(CallConv::SystemV),
|
||||
"windows_fastcall" => Ok(CallConv::WindowsFastcall),
|
||||
"baldrdash" => Ok(CallConv::Baldrdash),
|
||||
"probestack" => Ok(CallConv::Probestack),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@
|
||||
//! The configured target ISA trait object is a `Box<TargetIsa>` which can be used for multiple
|
||||
//! concurrent function compilations.
|
||||
|
||||
pub use isa::call_conv::CallConv;
|
||||
pub use isa::constraints::{BranchRange, ConstraintKind, OperandConstraint, RecipeConstraints};
|
||||
pub use isa::encoding::{base_size, EncInfo, Encoding};
|
||||
pub use isa::registers::{regs_overlap, RegClass, RegClassIndex, RegInfo, RegUnit};
|
||||
@@ -58,10 +59,10 @@ use isa::enc_tables::Encodings;
|
||||
use regalloc;
|
||||
use result::CodegenResult;
|
||||
use settings;
|
||||
use settings::{CallConv, SetResult};
|
||||
use settings::SetResult;
|
||||
use std::boxed::Box;
|
||||
use std::fmt;
|
||||
use target_lexicon::{Architecture, Triple};
|
||||
use target_lexicon::{Architecture, PointerWidth, Triple};
|
||||
use timing;
|
||||
|
||||
#[cfg(build_riscv)]
|
||||
@@ -76,6 +77,7 @@ mod arm32;
|
||||
#[cfg(build_arm64)]
|
||||
mod arm64;
|
||||
|
||||
mod call_conv;
|
||||
mod constraints;
|
||||
mod enc_tables;
|
||||
mod encoding;
|
||||
@@ -164,6 +166,34 @@ impl settings::Configurable for Builder {
|
||||
pub type Legalize =
|
||||
fn(ir::Inst, &mut ir::Function, &mut flowgraph::ControlFlowGraph, &TargetIsa) -> bool;
|
||||
|
||||
/// This struct provides information that a frontend may need to know about a target to
|
||||
/// produce Cranelift IR for the target.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct TargetFrontendConfig {
|
||||
/// The default calling convention of the target.
|
||||
pub default_call_conv: CallConv,
|
||||
|
||||
/// The pointer width of the target.
|
||||
pub pointer_width: PointerWidth,
|
||||
}
|
||||
|
||||
impl TargetFrontendConfig {
|
||||
/// Get the pointer type of this target.
|
||||
pub fn pointer_type(&self) -> ir::Type {
|
||||
ir::Type::int(u16::from(self.pointer_bits())).unwrap()
|
||||
}
|
||||
|
||||
/// Get the width of pointers on this target, in units of bits.
|
||||
pub fn pointer_bits(&self) -> u8 {
|
||||
self.pointer_width.bits()
|
||||
}
|
||||
|
||||
/// Get the width of pointers on this target, in units of bytes.
|
||||
pub fn pointer_bytes(&self) -> u8 {
|
||||
self.pointer_width.bytes()
|
||||
}
|
||||
}
|
||||
|
||||
/// Methods that are specialized to a target ISA. Implies a Display trait that shows the
|
||||
/// shared flags, as well as any isa-specific flags.
|
||||
pub trait TargetIsa: fmt::Display {
|
||||
@@ -176,19 +206,37 @@ pub trait TargetIsa: fmt::Display {
|
||||
/// Get the ISA-independent flags that were used to make this trait object.
|
||||
fn flags(&self) -> &settings::Flags;
|
||||
|
||||
/// Get the default calling convention of this target.
|
||||
fn default_call_conv(&self) -> CallConv {
|
||||
CallConv::default_for_triple(self.triple())
|
||||
}
|
||||
|
||||
/// Get the pointer type of this ISA.
|
||||
fn pointer_type(&self) -> ir::Type {
|
||||
ir::Type::int(u16::from(self.pointer_bits())).unwrap()
|
||||
}
|
||||
|
||||
/// Get the width of pointers on this ISA.
|
||||
fn pointer_width(&self) -> PointerWidth {
|
||||
self.triple().pointer_width().unwrap()
|
||||
}
|
||||
|
||||
/// Get the width of pointers on this ISA, in units of bits.
|
||||
fn pointer_bits(&self) -> u8 {
|
||||
self.triple().pointer_width().unwrap().bits()
|
||||
self.pointer_width().bits()
|
||||
}
|
||||
|
||||
/// Get the width of pointers on this ISA, in units of bytes.
|
||||
fn pointer_bytes(&self) -> u8 {
|
||||
self.triple().pointer_width().unwrap().bytes()
|
||||
self.pointer_width().bytes()
|
||||
}
|
||||
|
||||
/// Get the information needed by frontends producing Cranelift IR.
|
||||
fn frontend_config(&self) -> TargetFrontendConfig {
|
||||
TargetFrontendConfig {
|
||||
default_call_conv: self.default_call_conv(),
|
||||
pointer_width: self.pointer_width(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Does the CPU implement scalar comparisons using a CPU flags register?
|
||||
|
||||
@@ -10,10 +10,9 @@ use ir::{
|
||||
get_probestack_funcref, AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, InstBuilder,
|
||||
ValueLoc,
|
||||
};
|
||||
use isa::{RegClass, RegUnit, TargetIsa};
|
||||
use isa::{CallConv, RegClass, RegUnit, TargetIsa};
|
||||
use regalloc::RegisterSet;
|
||||
use result::CodegenResult;
|
||||
use settings::CallConv;
|
||||
use stack_layout::layout_stack;
|
||||
use std::i32;
|
||||
use target_lexicon::{PointerWidth, Triple};
|
||||
@@ -189,12 +188,12 @@ pub fn allocatable_registers(_func: &ir::Function, triple: &Triple) -> RegisterS
|
||||
}
|
||||
|
||||
/// Get the set of callee-saved registers.
|
||||
fn callee_saved_gprs(isa: &TargetIsa) -> &'static [RU] {
|
||||
fn callee_saved_gprs(isa: &TargetIsa, call_conv: CallConv) -> &'static [RU] {
|
||||
match isa.triple().pointer_width().unwrap() {
|
||||
PointerWidth::U16 => panic!(),
|
||||
PointerWidth::U32 => &[RU::rbx, RU::rsi, RU::rdi],
|
||||
PointerWidth::U64 => {
|
||||
if isa.flags().call_conv() == CallConv::WindowsFastcall {
|
||||
if call_conv == CallConv::WindowsFastcall {
|
||||
// "registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15 are considered nonvolatile
|
||||
// and must be saved and restored by a function that uses them."
|
||||
// as per https://msdn.microsoft.com/en-us/library/6t169e9c.aspx
|
||||
@@ -219,7 +218,7 @@ fn callee_saved_gprs(isa: &TargetIsa) -> &'static [RU] {
|
||||
/// Get the set of callee-saved registers that are used.
|
||||
fn callee_saved_gprs_used(isa: &TargetIsa, func: &ir::Function) -> RegisterSet {
|
||||
let mut all_callee_saved = RegisterSet::empty();
|
||||
for reg in callee_saved_gprs(isa) {
|
||||
for reg in callee_saved_gprs(isa, func.signature.call_conv) {
|
||||
all_callee_saved.free(GPR, *reg as RegUnit);
|
||||
}
|
||||
|
||||
|
||||
@@ -372,7 +372,6 @@ mod tests {
|
||||
"[shared]\n\
|
||||
opt_level = \"default\"\n\
|
||||
enable_verifier = true\n\
|
||||
call_conv = \"fast\"\n\
|
||||
is_pic = false\n\
|
||||
colocated_libcalls = false\n\
|
||||
avoid_div_traps = false\n\
|
||||
|
||||
@@ -9,7 +9,7 @@ use cranelift_codegen::ir::{
|
||||
JumpTable, JumpTableData, LibCall, MemFlags, SigRef, Signature, StackSlot, StackSlotData, Type,
|
||||
Value,
|
||||
};
|
||||
use cranelift_codegen::isa::TargetIsa;
|
||||
use cranelift_codegen::isa::{TargetFrontendConfig, TargetIsa};
|
||||
use cranelift_codegen::packed_option::PackedOption;
|
||||
use ssa::{Block, SSABuilder, SideEffects};
|
||||
use std::vec::Vec;
|
||||
@@ -550,10 +550,16 @@ impl<'a> FunctionBuilder<'a> {
|
||||
/// won't overlap onto `dest`. If `dest` and `src` overlap, the behavior is
|
||||
/// undefined. Applications in which `dest` and `src` might overlap should
|
||||
/// use `call_memmove` instead.
|
||||
pub fn call_memcpy(&mut self, isa: &TargetIsa, dest: Value, src: Value, size: Value) {
|
||||
let pointer_type = isa.pointer_type();
|
||||
pub fn call_memcpy(
|
||||
&mut self,
|
||||
config: &TargetFrontendConfig,
|
||||
dest: Value,
|
||||
src: Value,
|
||||
size: Value,
|
||||
) {
|
||||
let pointer_type = config.pointer_type();
|
||||
let signature = {
|
||||
let mut s = Signature::new(isa.flags().call_conv());
|
||||
let mut s = Signature::new(config.default_call_conv);
|
||||
s.params.push(AbiParam::new(pointer_type));
|
||||
s.params.push(AbiParam::new(pointer_type));
|
||||
s.params.push(AbiParam::new(pointer_type));
|
||||
@@ -572,7 +578,7 @@ impl<'a> FunctionBuilder<'a> {
|
||||
/// Optimised memcpy for small copys.
|
||||
pub fn emit_small_memcpy(
|
||||
&mut self,
|
||||
isa: &TargetIsa,
|
||||
config: &TargetFrontendConfig,
|
||||
dest: Value,
|
||||
src: Value,
|
||||
size: u64,
|
||||
@@ -594,8 +600,8 @@ impl<'a> FunctionBuilder<'a> {
|
||||
let load_and_store_amount = size / access_size;
|
||||
|
||||
if load_and_store_amount > THRESHOLD {
|
||||
let size_value = self.ins().iconst(isa.pointer_type(), size as i64);
|
||||
self.call_memcpy(isa, dest, src, size_value);
|
||||
let size_value = self.ins().iconst(config.pointer_type(), size as i64);
|
||||
self.call_memcpy(config, dest, src, size_value);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -613,10 +619,16 @@ impl<'a> FunctionBuilder<'a> {
|
||||
/// Calls libc.memset
|
||||
///
|
||||
/// Writes `size` bytes of value `ch` to memory starting at `buffer`.
|
||||
pub fn call_memset(&mut self, isa: &TargetIsa, buffer: Value, ch: Value, size: Value) {
|
||||
let pointer_type = isa.pointer_type();
|
||||
pub fn call_memset(
|
||||
&mut self,
|
||||
config: &TargetFrontendConfig,
|
||||
buffer: Value,
|
||||
ch: Value,
|
||||
size: Value,
|
||||
) {
|
||||
let pointer_type = config.pointer_type();
|
||||
let signature = {
|
||||
let mut s = Signature::new(isa.flags().call_conv());
|
||||
let mut s = Signature::new(config.default_call_conv);
|
||||
s.params.push(AbiParam::new(pointer_type));
|
||||
s.params.push(AbiParam::new(types::I32));
|
||||
s.params.push(AbiParam::new(pointer_type));
|
||||
@@ -638,7 +650,7 @@ impl<'a> FunctionBuilder<'a> {
|
||||
/// Writes `size` bytes of value `ch` to memory starting at `buffer`.
|
||||
pub fn emit_small_memset(
|
||||
&mut self,
|
||||
isa: &TargetIsa,
|
||||
config: &TargetFrontendConfig,
|
||||
buffer: Value,
|
||||
ch: u32,
|
||||
size: u64,
|
||||
@@ -660,8 +672,8 @@ impl<'a> FunctionBuilder<'a> {
|
||||
|
||||
if load_and_store_amount > THRESHOLD {
|
||||
let ch = self.ins().iconst(types::I32, ch as i64);
|
||||
let size = self.ins().iconst(isa.pointer_type(), size as i64);
|
||||
self.call_memset(isa, buffer, ch, size);
|
||||
let size = self.ins().iconst(config.pointer_type(), size as i64);
|
||||
self.call_memset(config, buffer, ch, size);
|
||||
} else {
|
||||
let mut flags = MemFlags::new();
|
||||
flags.set_aligned();
|
||||
@@ -691,10 +703,16 @@ impl<'a> FunctionBuilder<'a> {
|
||||
///
|
||||
/// Copies `size` bytes from memory starting at `source` to memory starting
|
||||
/// at `dest`. `source` is always read before writing to `dest`.
|
||||
pub fn call_memmove(&mut self, isa: &TargetIsa, dest: Value, source: Value, size: Value) {
|
||||
let pointer_type = isa.pointer_type();
|
||||
pub fn call_memmove(
|
||||
&mut self,
|
||||
config: &TargetFrontendConfig,
|
||||
dest: Value,
|
||||
source: Value,
|
||||
size: Value,
|
||||
) {
|
||||
let pointer_type = config.pointer_type();
|
||||
let signature = {
|
||||
let mut s = Signature::new(isa.flags().call_conv());
|
||||
let mut s = Signature::new(config.default_call_conv);
|
||||
s.params.push(AbiParam::new(pointer_type));
|
||||
s.params.push(AbiParam::new(pointer_type));
|
||||
s.params.push(AbiParam::new(pointer_type));
|
||||
@@ -713,7 +731,7 @@ impl<'a> FunctionBuilder<'a> {
|
||||
/// Optimised memmove for small moves.
|
||||
pub fn emit_small_memmove(
|
||||
&mut self,
|
||||
isa: &TargetIsa,
|
||||
config: &TargetFrontendConfig,
|
||||
dest: Value,
|
||||
src: Value,
|
||||
size: u64,
|
||||
@@ -735,8 +753,8 @@ impl<'a> FunctionBuilder<'a> {
|
||||
let load_and_store_amount = size / access_size;
|
||||
|
||||
if load_and_store_amount > THRESHOLD {
|
||||
let size_value = self.ins().iconst(isa.pointer_type(), size as i64);
|
||||
self.call_memmove(isa, dest, src, size_value);
|
||||
let size_value = self.ins().iconst(config.pointer_type(), size as i64);
|
||||
self.call_memmove(config, dest, src, size_value);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -798,8 +816,8 @@ mod tests {
|
||||
use cranelift_codegen::entity::EntityRef;
|
||||
use cranelift_codegen::ir::types::*;
|
||||
use cranelift_codegen::ir::{AbiParam, ExternalName, Function, InstBuilder, Signature};
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use cranelift_codegen::settings;
|
||||
use cranelift_codegen::settings::CallConv;
|
||||
use cranelift_codegen::verifier::verify_function;
|
||||
use frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||
use std::string::ToString;
|
||||
@@ -923,7 +941,7 @@ mod tests {
|
||||
.map(|b| b.finish(shared_flags))
|
||||
.expect("This test requires arm support.");
|
||||
|
||||
let mut sig = Signature::new(target.flags().call_conv());
|
||||
let mut sig = Signature::new(target.default_call_conv());
|
||||
sig.returns.push(AbiParam::new(I32));
|
||||
|
||||
let mut fn_ctx = FunctionBuilderContext::new();
|
||||
@@ -944,7 +962,7 @@ mod tests {
|
||||
let src = builder.use_var(x);
|
||||
let dest = builder.use_var(y);
|
||||
let size = builder.use_var(y);
|
||||
builder.call_memcpy(&*target, dest, src, size);
|
||||
builder.call_memcpy(&target.frontend_config(), dest, src, size);
|
||||
builder.ins().return_(&[size]);
|
||||
|
||||
builder.seal_all_blocks();
|
||||
@@ -953,8 +971,8 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
func.display(None).to_string(),
|
||||
"function %sample() -> i32 fast {
|
||||
sig0 = (i32, i32, i32) fast
|
||||
"function %sample() -> i32 system_v {
|
||||
sig0 = (i32, i32, i32) system_v
|
||||
fn0 = %Memcpy sig0
|
||||
|
||||
ebb0:
|
||||
|
||||
@@ -68,7 +68,8 @@
|
||||
//! use cranelift_codegen::entity::EntityRef;
|
||||
//! use cranelift_codegen::ir::types::*;
|
||||
//! use cranelift_codegen::ir::{AbiParam, ExternalName, Function, InstBuilder, Signature};
|
||||
//! use cranelift_codegen::settings::{self, CallConv};
|
||||
//! use cranelift_codegen::isa::CallConv;
|
||||
//! use cranelift_codegen::settings;
|
||||
//! use cranelift_codegen::verifier::verify_function;
|
||||
//! use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
|
||||
//!
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// shared with `DataContext`?
|
||||
|
||||
use cranelift_codegen::entity::{EntityRef, PrimaryMap};
|
||||
use cranelift_codegen::{binemit, ir, CodegenError, Context};
|
||||
use cranelift_codegen::{binemit, ir, isa, CodegenError, Context};
|
||||
use data_context::DataContext;
|
||||
use std::borrow::ToOwned;
|
||||
use std::collections::HashMap;
|
||||
@@ -340,9 +340,10 @@ where
|
||||
self.names.get(name).cloned()
|
||||
}
|
||||
|
||||
/// Return then pointer type for the current target.
|
||||
pub fn pointer_type(&self) -> ir::types::Type {
|
||||
self.backend.isa().pointer_type()
|
||||
/// Return the target information needed by frontends to produce Cranelift IR
|
||||
/// for the current target.
|
||||
pub fn target_config(&self) -> isa::TargetFrontendConfig {
|
||||
self.backend.isa().frontend_config()
|
||||
}
|
||||
|
||||
/// Create a new `Context` initialized for use with this `Module`.
|
||||
@@ -351,7 +352,7 @@ where
|
||||
/// convention for the `TargetIsa`.
|
||||
pub fn make_context(&self) -> Context {
|
||||
let mut ctx = Context::new();
|
||||
ctx.func.signature.call_conv = self.backend.isa().flags().call_conv();
|
||||
ctx.func.signature.call_conv = self.backend.isa().default_call_conv();
|
||||
ctx
|
||||
}
|
||||
|
||||
@@ -361,14 +362,14 @@ where
|
||||
/// convention for the `TargetIsa`.
|
||||
pub fn clear_context(&self, ctx: &mut Context) {
|
||||
ctx.clear();
|
||||
ctx.func.signature.call_conv = self.backend.isa().flags().call_conv();
|
||||
ctx.func.signature.call_conv = self.backend.isa().default_call_conv();
|
||||
}
|
||||
|
||||
/// Create a new empty `Signature` with the default calling convention for
|
||||
/// the `TargetIsa`, to which parameter and return types can be added for
|
||||
/// declaring a function to be called by this `Module`.
|
||||
pub fn make_signature(&self) -> ir::Signature {
|
||||
ir::Signature::new(self.backend.isa().flags().call_conv())
|
||||
ir::Signature::new(self.backend.isa().default_call_conv())
|
||||
}
|
||||
|
||||
/// Clear the given `Signature` and reset for use with a new function.
|
||||
@@ -376,7 +377,7 @@ where
|
||||
/// This ensures that the `Signature` is initialized with the default
|
||||
/// calling convention for the `TargetIsa`.
|
||||
pub fn clear_signature(&self, sig: &mut ir::Signature) {
|
||||
sig.clear(self.backend.isa().flags().call_conv());
|
||||
sig.clear(self.backend.isa().default_call_conv());
|
||||
}
|
||||
|
||||
/// Declare a function in this module.
|
||||
|
||||
@@ -37,26 +37,16 @@ extern crate raw_cpuid;
|
||||
extern crate target_lexicon;
|
||||
|
||||
use cranelift_codegen::isa;
|
||||
use cranelift_codegen::settings::{self, Configurable};
|
||||
use cranelift_codegen::settings::Configurable;
|
||||
use target_lexicon::Triple;
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
use raw_cpuid::CpuId;
|
||||
|
||||
/// Return `settings` and `isa` builders configured for the current host
|
||||
/// Return an `isa` builder configured for the current host
|
||||
/// machine, or `Err(())` if the host machine is not supported
|
||||
/// in the current configuration.
|
||||
pub fn builders() -> Result<(settings::Builder, isa::Builder), &'static str> {
|
||||
let mut flag_builder = settings::builder();
|
||||
|
||||
if cfg!(any(unix, target_os = "nebulet")) {
|
||||
flag_builder.set("call_conv", "system_v").unwrap();
|
||||
} else if cfg!(windows) {
|
||||
flag_builder.set("call_conv", "windows_fastcall").unwrap();
|
||||
} else {
|
||||
return Err("unrecognized environment");
|
||||
}
|
||||
|
||||
pub fn builder() -> Result<isa::Builder, &'static str> {
|
||||
let mut isa_builder = isa::lookup(Triple::host()).map_err(|err| match err {
|
||||
isa::LookupError::SupportDisabled => "support for architecture disabled at compile time",
|
||||
isa::LookupError::Unsupported => "unsupported architecture",
|
||||
@@ -66,7 +56,7 @@ pub fn builders() -> Result<(settings::Builder, isa::Builder), &'static str> {
|
||||
parse_x86_cpuid(&mut isa_builder)?;
|
||||
}
|
||||
|
||||
Ok((flag_builder, isa_builder))
|
||||
Ok(isa_builder)
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
@@ -108,3 +98,32 @@ fn parse_x86_cpuid(isa_builder: &mut isa::Builder) -> Result<(), &'static str> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::builder;
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use cranelift_codegen::settings;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
if let Ok(isa_builder) = builder() {
|
||||
let flag_builder = settings::builder();
|
||||
let isa = isa_builder.finish(settings::Flags::new(flag_builder));
|
||||
if cfg!(any(unix, target_os = "nebulet")) {
|
||||
assert_eq!(isa.default_call_conv(), CallConv::SystemV);
|
||||
} else if cfg!(windows) {
|
||||
assert_eq!(isa.default_call_conv(), CallConv::WindowsFastcall);
|
||||
}
|
||||
if cfg!(target_pointer_width = "64") {
|
||||
assert_eq!(isa.pointer_bits(), 64);
|
||||
}
|
||||
if cfg!(target_pointer_width = "32") {
|
||||
assert_eq!(isa.pointer_bits(), 32);
|
||||
}
|
||||
if cfg!(target_pointer_width = "16") {
|
||||
assert_eq!(isa.pointer_bits(), 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,8 @@ use cranelift_codegen::ir::{
|
||||
Opcode, SigRef, Signature, StackSlot, StackSlotData, StackSlotKind, Table, TableData, Type,
|
||||
Value, ValueLoc,
|
||||
};
|
||||
use cranelift_codegen::isa::{self, Encoding, RegUnit, TargetIsa};
|
||||
use cranelift_codegen::isa::{self, CallConv, Encoding, RegUnit, TargetIsa};
|
||||
use cranelift_codegen::packed_option::ReservedValue;
|
||||
use cranelift_codegen::settings::CallConv;
|
||||
use cranelift_codegen::{settings, timing};
|
||||
use error::{Location, ParseError, ParseResult};
|
||||
use isaspec;
|
||||
@@ -2562,7 +2561,7 @@ mod tests {
|
||||
use cranelift_codegen::ir::types;
|
||||
use cranelift_codegen::ir::StackSlotKind;
|
||||
use cranelift_codegen::ir::{ArgumentExtension, ArgumentPurpose};
|
||||
use cranelift_codegen::settings::CallConv;
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use error::ParseError;
|
||||
use isaspec::IsaSpec;
|
||||
use testfile::{Comment, Details};
|
||||
|
||||
@@ -26,8 +26,9 @@ pub struct SimpleJITBuilder {
|
||||
impl SimpleJITBuilder {
|
||||
/// Create a new `SimpleJITBuilder`.
|
||||
pub fn new() -> Self {
|
||||
let (flag_builder, isa_builder) = cranelift_native::builders().unwrap_or_else(|_| {
|
||||
panic!("host machine is not a supported target");
|
||||
let flag_builder = settings::builder();
|
||||
let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
|
||||
panic!("host machine is not supported: {}", msg);
|
||||
});
|
||||
let isa = isa_builder.finish(settings::Flags::new(flag_builder));
|
||||
Self::with_isa(isa)
|
||||
|
||||
@@ -5,7 +5,7 @@ extern crate cranelift_module;
|
||||
extern crate cranelift_simplejit;
|
||||
|
||||
use cranelift_codegen::ir::*;
|
||||
use cranelift_codegen::settings::*;
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use cranelift_codegen::Context;
|
||||
use cranelift_entity::EntityRef;
|
||||
use cranelift_frontend::*;
|
||||
|
||||
@@ -46,7 +46,7 @@ pub mod prelude {
|
||||
MemFlags, Signature, StackSlotData, StackSlotKind, TrapCode, Type, Value,
|
||||
};
|
||||
pub use codegen::isa;
|
||||
pub use codegen::settings::{self, CallConv, Configurable};
|
||||
pub use codegen::settings::{self, Configurable};
|
||||
|
||||
pub use frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
|
||||
}
|
||||
|
||||
@@ -17,15 +17,15 @@ cranelift-frontend = { path = "../frontend", version = "0.22.0", default-feature
|
||||
hashmap_core = { version = "0.1.9", optional = true }
|
||||
failure = { version = "0.1.1", default-features = false, features = ["derive"] }
|
||||
failure_derive = { version = "0.1.1", default-features = false }
|
||||
target-lexicon = { version = "0.0.3", default-features = false }
|
||||
log = { version = "0.4.4", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
wabt = "0.6.0"
|
||||
target-lexicon = "0.0.3"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = ["cranelift-codegen/std", "cranelift-frontend/std", "wasmparser/std", "target-lexicon/std"]
|
||||
std = ["cranelift-codegen/std", "cranelift-frontend/std", "wasmparser/std"]
|
||||
core = ["hashmap_core", "cranelift-codegen/core", "cranelift-frontend/core", "wasmparser/core"]
|
||||
|
||||
[badges]
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -75,14 +75,12 @@ fn handle_module(path: &Path, flags: &Flags, return_mode: ReturnMode) {
|
||||
None | Some(&_) => panic!("the file extension for {:?} is not wasm or wat", path),
|
||||
},
|
||||
};
|
||||
let mut dummy_environ =
|
||||
DummyEnvironment::with_triple_flags(triple!("riscv64"), flags.clone(), return_mode);
|
||||
let triple = triple!("riscv64");
|
||||
let isa = isa::lookup(triple).unwrap().finish(flags.clone());
|
||||
let mut dummy_environ = DummyEnvironment::new(isa.frontend_config(), return_mode);
|
||||
|
||||
translate_module(&data, &mut dummy_environ).unwrap();
|
||||
|
||||
let isa = isa::lookup(dummy_environ.info.triple)
|
||||
.unwrap()
|
||||
.finish(dummy_environ.info.flags);
|
||||
for func in dummy_environ.info.function_bodies.values() {
|
||||
verifier::verify_function(func, &*isa)
|
||||
.map_err(|errors| panic!(pretty_verifier_error(func, Some(&*isa), None, errors)))
|
||||
|
||||
Reference in New Issue
Block a user