From 88b30ff386aa04a680912ad0f1ad17bbd417957e Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Tue, 12 Dec 2017 11:57:25 -0800 Subject: [PATCH] refactor Reloc to an enum of every architecture's reloc types https://github.com/stoklund/cretonne/pull/206#issuecomment-350905016 --- cranelift/src/filetest/binemit.rs | 18 ++++----------- lib/cretonne/meta/isa/intel/recipes.py | 14 +++++------ lib/cretonne/meta/isa/riscv/recipes.py | 2 +- lib/cretonne/src/binemit/mod.rs | 32 ++++++++++++++++++++++++-- lib/cretonne/src/isa/arm32/binemit.rs | 2 -- lib/cretonne/src/isa/arm32/mod.rs | 4 ---- lib/cretonne/src/isa/arm64/binemit.rs | 2 -- lib/cretonne/src/isa/arm64/mod.rs | 4 ---- lib/cretonne/src/isa/intel/binemit.rs | 20 ---------------- lib/cretonne/src/isa/intel/mod.rs | 4 ---- lib/cretonne/src/isa/mod.rs | 6 ----- lib/cretonne/src/isa/riscv/binemit.rs | 14 ----------- lib/cretonne/src/isa/riscv/mod.rs | 4 ---- 13 files changed, 43 insertions(+), 83 deletions(-) diff --git a/cranelift/src/filetest/binemit.rs b/cranelift/src/filetest/binemit.rs index 9c19533c64..24de3d7e69 100644 --- a/cranelift/src/filetest/binemit.rs +++ b/cranelift/src/filetest/binemit.rs @@ -9,7 +9,6 @@ use std::fmt::Write; use cretonne::binemit; use cretonne::ir; use cretonne::ir::entities::AnyEntity; -use cretonne::isa::TargetIsa; use cretonne::regalloc::RegDiversions; use cton_reader::TestCommand; use filetest::subtest::{SubTest, Context, Result}; @@ -28,16 +27,14 @@ pub fn subtest(parsed: &TestCommand) -> Result> { // Code sink that generates text. struct TextSink { - rnames: &'static [&'static str], offset: binemit::CodeOffset, text: String, } impl TextSink { /// Create a new empty TextSink. - pub fn new(isa: &TargetIsa) -> Self { + pub fn new() -> Self { Self { - rnames: isa.reloc_names(), offset: 0, text: String::new(), } @@ -72,25 +69,20 @@ impl binemit::CodeSink for TextSink { } fn reloc_ebb(&mut self, reloc: binemit::Reloc, ebb_offset: binemit::CodeOffset) { - write!( - self.text, - "{}({}) ", - self.rnames[reloc.0 as usize], - ebb_offset - ).unwrap(); + write!(self.text, "{}({}) ", reloc, ebb_offset).unwrap(); } fn reloc_external(&mut self, reloc: binemit::Reloc, name: &ir::ExternalName) { write!( self.text, "{}({}) ", - self.rnames[reloc.0 as usize], + reloc, name, ).unwrap(); } fn reloc_jt(&mut self, reloc: binemit::Reloc, jt: ir::JumpTable) { - write!(self.text, "{}({}) ", self.rnames[reloc.0 as usize], jt).unwrap(); + write!(self.text, "{}({}) ", reloc, jt).unwrap(); } } @@ -191,7 +183,7 @@ impl SubTest for TestBinEmit { } // Now emit all instructions. - let mut sink = TextSink::new(isa); + let mut sink = TextSink::new(); for ebb in func.layout.ebbs() { divert.clear(); // Correct header offsets should have been computed by `relax_branches()`. diff --git a/lib/cretonne/meta/isa/intel/recipes.py b/lib/cretonne/meta/isa/intel/recipes.py index a970b342aa..2afd7be588 100644 --- a/lib/cretonne/meta/isa/intel/recipes.py +++ b/lib/cretonne/meta/isa/intel/recipes.py @@ -521,7 +521,7 @@ fnaddr4 = TailRecipe( 'fnaddr4', FuncAddr, size=4, ins=(), outs=GPR, emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); - sink.reloc_external(RelocKind::Abs4.into(), + sink.reloc_external(Reloc::IntelAbs4, &func.dfg.ext_funcs[func_ref].name); sink.put4(0); ''') @@ -531,7 +531,7 @@ fnaddr8 = TailRecipe( 'fnaddr8', FuncAddr, size=8, ins=(), outs=GPR, emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); - sink.reloc_external(RelocKind::Abs8.into(), + sink.reloc_external(Reloc::IntelAbs8, &func.dfg.ext_funcs[func_ref].name); sink.put8(0); ''') @@ -541,7 +541,7 @@ allones_fnaddr4 = TailRecipe( 'allones_fnaddr4', FuncAddr, size=4, ins=(), outs=GPR, emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); - sink.reloc_external(RelocKind::Abs4.into(), + sink.reloc_external(Reloc::IntelAbs4, &func.dfg.ext_funcs[func_ref].name); // Write the immediate as `!0` for the benefit of BaldrMonkey. sink.put4(!0); @@ -552,7 +552,7 @@ allones_fnaddr8 = TailRecipe( 'allones_fnaddr8', FuncAddr, size=8, ins=(), outs=GPR, emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); - sink.reloc_external(RelocKind::Abs8.into(), + sink.reloc_external(Reloc::IntelAbs8, &func.dfg.ext_funcs[func_ref].name); // Write the immediate as `!0` for the benefit of BaldrMonkey. sink.put8(!0); @@ -563,7 +563,7 @@ gvaddr4 = TailRecipe( 'gvaddr4', UnaryGlobalVar, size=4, ins=(), outs=GPR, emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); - sink.reloc_external(RelocKind::Abs4.into(), + sink.reloc_external(Reloc::IntelAbs4, &func.global_vars[global_var].symbol_name()); sink.put4(0); ''') @@ -573,7 +573,7 @@ gvaddr8 = TailRecipe( 'gvaddr8', UnaryGlobalVar, size=8, ins=(), outs=GPR, emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); - sink.reloc_external(RelocKind::Abs8.into(), + sink.reloc_external(Reloc::IntelAbs8, &func.global_vars[global_var].symbol_name()); sink.put8(0); ''') @@ -848,7 +848,7 @@ call_id = TailRecipe( 'call_id', Call, size=4, ins=(), outs=(), emit=''' PUT_OP(bits, BASE_REX, sink); - sink.reloc_external(RelocKind::PCRel4.into(), + sink.reloc_external(Reloc::IntelPCRel4, &func.dfg.ext_funcs[func_ref].name); sink.put4(0); ''') diff --git a/lib/cretonne/meta/isa/riscv/recipes.py b/lib/cretonne/meta/isa/riscv/recipes.py index 6874f95c36..1fbba83036 100644 --- a/lib/cretonne/meta/isa/riscv/recipes.py +++ b/lib/cretonne/meta/isa/riscv/recipes.py @@ -183,7 +183,7 @@ UJ = EncRecipe( UJcall = EncRecipe( 'UJcall', Call, size=4, ins=(), outs=(), emit=''' - sink.reloc_external(RelocKind::Call.into(), + sink.reloc_external(Reloc::RiscvCall, &func.dfg.ext_funcs[func_ref].name); // rd=%x1 is the standard link register. put_uj(bits, 0, 1, sink); diff --git a/lib/cretonne/src/binemit/mod.rs b/lib/cretonne/src/binemit/mod.rs index f216fe6514..7851e491a5 100644 --- a/lib/cretonne/src/binemit/mod.rs +++ b/lib/cretonne/src/binemit/mod.rs @@ -11,6 +11,7 @@ pub use self::memorysink::{MemoryCodeSink, RelocSink}; use ir::{ExternalName, JumpTable, Function, Inst}; use regalloc::RegDiversions; +use std::fmt; /// Offset in bytes from the beginning of the function. /// @@ -18,8 +19,35 @@ use regalloc::RegDiversions; /// depends on the *host* platform, not the *target* platform. pub type CodeOffset = u32; -/// Relocation kinds depend on the current ISA. -pub struct Reloc(pub u16); +/// Relocation kinds for every ISA +#[derive(Debug)] +pub enum Reloc { + /// Intel PC-relative 4-byte + IntelPCRel4, + /// Intel absolute 4-byte + IntelAbs4, + /// Intel absolute 8-byte + IntelAbs8, + /// Arm32 call target + Arm32Call, + /// Arm64 call target + Arm64Call, + /// RISC-V call target + RiscvCall, +} + +impl fmt::Display for Reloc { + /// Display trait implementation drops the arch, since its used in contexts where the arch is + /// already unambigious, e.g. cton syntax with isa specified. In other contexts, use Debug. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Reloc::IntelPCRel4 => write!(f, "{}", "PCRel4"), + Reloc::IntelAbs4 => write!(f, "{}", "Abs4"), + Reloc::IntelAbs8 => write!(f, "{}", "Abs8"), + Reloc::Arm32Call | Reloc::Arm64Call | Reloc::RiscvCall => write!(f, "{}", "Call"), + } + } +} /// Abstract interface for adding bytes to the code segment. /// diff --git a/lib/cretonne/src/isa/arm32/binemit.rs b/lib/cretonne/src/isa/arm32/binemit.rs index bbae03432c..78fa2fd657 100644 --- a/lib/cretonne/src/isa/arm32/binemit.rs +++ b/lib/cretonne/src/isa/arm32/binemit.rs @@ -5,5 +5,3 @@ use ir::{Function, Inst}; use regalloc::RegDiversions; include!(concat!(env!("OUT_DIR"), "/binemit-arm32.rs")); - -pub static RELOC_NAMES: [&'static str; 1] = ["Call"]; diff --git a/lib/cretonne/src/isa/arm32/mod.rs b/lib/cretonne/src/isa/arm32/mod.rs index 552e159ca1..49987f1e18 100644 --- a/lib/cretonne/src/isa/arm32/mod.rs +++ b/lib/cretonne/src/isa/arm32/mod.rs @@ -107,8 +107,4 @@ impl TargetIsa for Isa { fn emit_function(&self, func: &ir::Function, sink: &mut MemoryCodeSink) { emit_function(func, binemit::emit_inst, sink) } - - fn reloc_names(&self) -> &'static [&'static str] { - &binemit::RELOC_NAMES - } } diff --git a/lib/cretonne/src/isa/arm64/binemit.rs b/lib/cretonne/src/isa/arm64/binemit.rs index ecff1662bc..a4b79cda55 100644 --- a/lib/cretonne/src/isa/arm64/binemit.rs +++ b/lib/cretonne/src/isa/arm64/binemit.rs @@ -5,5 +5,3 @@ use ir::{Function, Inst}; use regalloc::RegDiversions; include!(concat!(env!("OUT_DIR"), "/binemit-arm64.rs")); - -pub static RELOC_NAMES: [&'static str; 1] = ["Call"]; diff --git a/lib/cretonne/src/isa/arm64/mod.rs b/lib/cretonne/src/isa/arm64/mod.rs index 88086b233e..f8e7737c31 100644 --- a/lib/cretonne/src/isa/arm64/mod.rs +++ b/lib/cretonne/src/isa/arm64/mod.rs @@ -100,8 +100,4 @@ impl TargetIsa for Isa { fn emit_function(&self, func: &ir::Function, sink: &mut MemoryCodeSink) { emit_function(func, binemit::emit_inst, sink) } - - fn reloc_names(&self) -> &'static [&'static str] { - &binemit::RELOC_NAMES - } } diff --git a/lib/cretonne/src/isa/intel/binemit.rs b/lib/cretonne/src/isa/intel/binemit.rs index f1dcdce095..ba93ce296e 100644 --- a/lib/cretonne/src/isa/intel/binemit.rs +++ b/lib/cretonne/src/isa/intel/binemit.rs @@ -9,26 +9,6 @@ use super::registers::RU; include!(concat!(env!("OUT_DIR"), "/binemit-intel.rs")); -/// Intel relocations. -pub enum RelocKind { - /// A 4-byte relative function reference. Based from relocation + 4 bytes. - PCRel4, - - /// A 4-byte absolute function reference. - Abs4, - - /// An 8-byte absolute function reference. - Abs8, -} - -pub static RELOC_NAMES: [&'static str; 3] = ["PCRel4", "Abs4", "Abs8"]; - -impl Into for RelocKind { - fn into(self) -> Reloc { - Reloc(self as u16) - } -} - // Convert a stack base to the corresponding register. fn stk_base(base: StackBase) -> RegUnit { let ru = match base { diff --git a/lib/cretonne/src/isa/intel/mod.rs b/lib/cretonne/src/isa/intel/mod.rs index b4ca044c2f..3123e7f0cb 100644 --- a/lib/cretonne/src/isa/intel/mod.rs +++ b/lib/cretonne/src/isa/intel/mod.rs @@ -111,10 +111,6 @@ impl TargetIsa for Isa { emit_function(func, binemit::emit_inst, sink) } - fn reloc_names(&self) -> &'static [&'static str] { - &binemit::RELOC_NAMES - } - fn prologue_epilogue(&self, func: &mut ir::Function) -> result::CtonResult { let _tt = timing::prologue_epilogue(); abi::prologue_epilogue(func, self) diff --git a/lib/cretonne/src/isa/mod.rs b/lib/cretonne/src/isa/mod.rs index ccfced715e..1fdaa79f09 100644 --- a/lib/cretonne/src/isa/mod.rs +++ b/lib/cretonne/src/isa/mod.rs @@ -272,10 +272,4 @@ pub trait TargetIsa { /// /// This is more performant than calling `emit_inst` for each instruction. fn emit_function(&self, func: &ir::Function, sink: &mut binemit::MemoryCodeSink); - - /// Get a static array of names associated with relocations in this ISA. - /// - /// This array can be indexed by the contents of `binemit::Reloc` objects passed to a - /// `CodeSink`. - fn reloc_names(&self) -> &'static [&'static str]; } diff --git a/lib/cretonne/src/isa/riscv/binemit.rs b/lib/cretonne/src/isa/riscv/binemit.rs index a6a633a524..c20b1ca004 100644 --- a/lib/cretonne/src/isa/riscv/binemit.rs +++ b/lib/cretonne/src/isa/riscv/binemit.rs @@ -9,20 +9,6 @@ use std::u32; include!(concat!(env!("OUT_DIR"), "/binemit-riscv.rs")); -/// RISC-V relocation kinds. -pub enum RelocKind { - /// A jal call to a function. - Call, -} - -pub static RELOC_NAMES: [&'static str; 1] = ["Call"]; - -impl Into for RelocKind { - fn into(self) -> Reloc { - Reloc(self as u16) - } -} - /// R-type instructions. /// /// 31 24 19 14 11 6 diff --git a/lib/cretonne/src/isa/riscv/mod.rs b/lib/cretonne/src/isa/riscv/mod.rs index 1cb76aef41..790a788a24 100644 --- a/lib/cretonne/src/isa/riscv/mod.rs +++ b/lib/cretonne/src/isa/riscv/mod.rs @@ -107,10 +107,6 @@ impl TargetIsa for Isa { fn emit_function(&self, func: &ir::Function, sink: &mut MemoryCodeSink) { emit_function(func, binemit::emit_inst, sink) } - - fn reloc_names(&self) -> &'static [&'static str] { - &binemit::RELOC_NAMES - } } #[cfg(test)]