diff --git a/cranelift/filetests/isa/intel/binary64-pic.cton b/cranelift/filetests/isa/intel/binary64-pic.cton index 50a0361ebf..70dc7bed42 100644 --- a/cranelift/filetests/isa/intel/binary64-pic.cton +++ b/cranelift/filetests/isa/intel/binary64-pic.cton @@ -30,11 +30,11 @@ ebb0: call fn0() ; bin: e8 PLTRel4(%foo) 00000000 ; asm: mov 0x0(%rip), %rax - [-,%rax] v0 = func_addr.i64 fn0 ; bin: 48 8b 05 GOTPCRel4(%foo) 00000000 + [-,%rax] v0 = func_addr.i64 fn0 ; bin: 48 8b 05 GOTPCRel4(%foo-4) 00000000 ; asm: mov 0x0(%rip), %rsi - [-,%rsi] v1 = func_addr.i64 fn0 ; bin: 48 8b 35 GOTPCRel4(%foo) 00000000 + [-,%rsi] v1 = func_addr.i64 fn0 ; bin: 48 8b 35 GOTPCRel4(%foo-4) 00000000 ; asm: mov 0x0(%rip), %r10 - [-,%r10] v2 = func_addr.i64 fn0 ; bin: 4c 8b 15 GOTPCRel4(%foo) 00000000 + [-,%r10] v2 = func_addr.i64 fn0 ; bin: 4c 8b 15 GOTPCRel4(%foo-4) 00000000 ; asm: call *%rax call_indirect sig0, v0() ; bin: ff d0 @@ -44,11 +44,11 @@ ebb0: call_indirect sig0, v2() ; bin: 41 ff d2 ; asm: mov 0x0(%rip), %rcx - [-,%rcx] v3 = globalsym_addr.i64 gv0 ; bin: 48 8b 0d GOTPCRel4(%some_gv) 00000000 + [-,%rcx] v3 = globalsym_addr.i64 gv0 ; bin: 48 8b 0d GOTPCRel4(%some_gv-4) 00000000 ; asm: mov 0x0(%rip), %rsi - [-,%rsi] v4 = globalsym_addr.i64 gv0 ; bin: 48 8b 35 GOTPCRel4(%some_gv) 00000000 + [-,%rsi] v4 = globalsym_addr.i64 gv0 ; bin: 48 8b 35 GOTPCRel4(%some_gv-4) 00000000 ; asm: mov 0x0(%rip), %r10 - [-,%r10] v5 = globalsym_addr.i64 gv0 ; bin: 4c 8b 15 GOTPCRel4(%some_gv) 00000000 + [-,%r10] v5 = globalsym_addr.i64 gv0 ; bin: 4c 8b 15 GOTPCRel4(%some_gv-4) 00000000 return } diff --git a/cranelift/src/filetest/binemit.rs b/cranelift/src/filetest/binemit.rs index 24de3d7e69..c51f4b613d 100644 --- a/cranelift/src/filetest/binemit.rs +++ b/cranelift/src/filetest/binemit.rs @@ -72,13 +72,29 @@ impl binemit::CodeSink for TextSink { write!(self.text, "{}({}) ", reloc, ebb_offset).unwrap(); } - fn reloc_external(&mut self, reloc: binemit::Reloc, name: &ir::ExternalName) { + fn reloc_external( + &mut self, + reloc: binemit::Reloc, + name: &ir::ExternalName, + addend: binemit::Addend, + ) { write!( self.text, - "{}({}) ", + "{}({}", reloc, name, ).unwrap(); + if addend != 0 { + write!( + self.text, + "{:+}", + addend, + ).unwrap(); + } + write!( + self.text, + ") ", + ).unwrap(); } fn reloc_jt(&mut self, reloc: binemit::Reloc, jt: ir::JumpTable) { diff --git a/cranelift/src/filetest/compile.rs b/cranelift/src/filetest/compile.rs index 0e271b7db4..8c8db46591 100644 --- a/cranelift/src/filetest/compile.rs +++ b/cranelift/src/filetest/compile.rs @@ -103,6 +103,12 @@ impl binemit::CodeSink for SizeSink { } fn reloc_ebb(&mut self, _reloc: binemit::Reloc, _ebb_offset: binemit::CodeOffset) {} - fn reloc_external(&mut self, _reloc: binemit::Reloc, _name: &ir::ExternalName) {} + fn reloc_external( + &mut self, + _reloc: binemit::Reloc, + _name: &ir::ExternalName, + _addend: binemit::Addend, + ) { + } fn reloc_jt(&mut self, _reloc: binemit::Reloc, _jt: ir::JumpTable) {} } diff --git a/lib/cretonne/meta/isa/intel/recipes.py b/lib/cretonne/meta/isa/intel/recipes.py index 0ed5431e8d..fb7b993c80 100644 --- a/lib/cretonne/meta/isa/intel/recipes.py +++ b/lib/cretonne/meta/isa/intel/recipes.py @@ -522,7 +522,8 @@ fnaddr4 = TailRecipe( emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); sink.reloc_external(Reloc::IntelAbs4, - &func.dfg.ext_funcs[func_ref].name); + &func.dfg.ext_funcs[func_ref].name, + 0); sink.put4(0); ''') @@ -532,7 +533,8 @@ fnaddr8 = TailRecipe( emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); sink.reloc_external(Reloc::IntelAbs8, - &func.dfg.ext_funcs[func_ref].name); + &func.dfg.ext_funcs[func_ref].name, + 0); sink.put8(0); ''') @@ -542,7 +544,8 @@ allones_fnaddr4 = TailRecipe( emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); sink.reloc_external(Reloc::IntelAbs4, - &func.dfg.ext_funcs[func_ref].name); + &func.dfg.ext_funcs[func_ref].name, + 0); // Write the immediate as `!0` for the benefit of BaldrMonkey. sink.put4(!0); ''') @@ -553,7 +556,8 @@ allones_fnaddr8 = TailRecipe( emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); sink.reloc_external(Reloc::IntelAbs8, - &func.dfg.ext_funcs[func_ref].name); + &func.dfg.ext_funcs[func_ref].name, + 0); // Write the immediate as `!0` for the benefit of BaldrMonkey. sink.put8(!0); ''') @@ -565,8 +569,11 @@ got_fnaddr8 = TailRecipe( emit=''' PUT_OP(bits, rex2(0, out_reg0), sink); modrm_riprel(out_reg0, sink); + // The addend adjusts for the difference between the end of the + // instruction and the beginning of the immediate field. sink.reloc_external(Reloc::IntelGOTPCRel4, - &func.dfg.ext_funcs[func_ref].name); + &func.dfg.ext_funcs[func_ref].name, + -4); sink.put4(0); ''') @@ -577,7 +584,8 @@ gvaddr4 = TailRecipe( emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); sink.reloc_external(Reloc::IntelAbs4, - &func.global_vars[global_var].symbol_name()); + &func.global_vars[global_var].symbol_name(), + 0); sink.put4(0); ''') @@ -587,7 +595,8 @@ gvaddr8 = TailRecipe( emit=''' PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); sink.reloc_external(Reloc::IntelAbs8, - &func.global_vars[global_var].symbol_name()); + &func.global_vars[global_var].symbol_name(), + 0); sink.put8(0); ''') @@ -597,8 +606,11 @@ got_gvaddr8 = TailRecipe( emit=''' PUT_OP(bits, rex2(0, out_reg0), sink); modrm_rm(5, out_reg0, sink); + // The addend adjusts for the difference between the end of the + // instruction and the beginning of the immediate field. sink.reloc_external(Reloc::IntelGOTPCRel4, - &func.global_vars[global_var].symbol_name()); + &func.global_vars[global_var].symbol_name(), + -4); sink.put4(0); ''') @@ -874,7 +886,8 @@ call_id = TailRecipe( emit=''' PUT_OP(bits, BASE_REX, sink); sink.reloc_external(Reloc::IntelPCRel4, - &func.dfg.ext_funcs[func_ref].name); + &func.dfg.ext_funcs[func_ref].name, + 0); sink.put4(0); ''') @@ -883,7 +896,8 @@ call_plt_id = TailRecipe( emit=''' PUT_OP(bits, BASE_REX, sink); sink.reloc_external(Reloc::IntelPLTRel4, - &func.dfg.ext_funcs[func_ref].name); + &func.dfg.ext_funcs[func_ref].name, + 0); sink.put4(0); ''') diff --git a/lib/cretonne/meta/isa/riscv/recipes.py b/lib/cretonne/meta/isa/riscv/recipes.py index 1fbba83036..c657c7de47 100644 --- a/lib/cretonne/meta/isa/riscv/recipes.py +++ b/lib/cretonne/meta/isa/riscv/recipes.py @@ -184,7 +184,8 @@ UJcall = EncRecipe( 'UJcall', Call, size=4, ins=(), outs=(), emit=''' sink.reloc_external(Reloc::RiscvCall, - &func.dfg.ext_funcs[func_ref].name); + &func.dfg.ext_funcs[func_ref].name, + 0); // rd=%x1 is the standard link register. put_uj(bits, 0, 1, sink); ''') diff --git a/lib/cretonne/src/binemit/memorysink.rs b/lib/cretonne/src/binemit/memorysink.rs index 92766b2d56..1d6758afe6 100644 --- a/lib/cretonne/src/binemit/memorysink.rs +++ b/lib/cretonne/src/binemit/memorysink.rs @@ -15,7 +15,7 @@ //! `CodeSink::put*` methods, so the performance impact of the virtual callbacks is less severe. use ir::{ExternalName, JumpTable}; -use super::{CodeSink, CodeOffset, Reloc}; +use super::{CodeSink, CodeOffset, Reloc, Addend}; use std::ptr::write_unaligned; /// A `CodeSink` that writes binary machine code directly into memory. @@ -52,7 +52,7 @@ pub trait RelocSink { fn reloc_ebb(&mut self, CodeOffset, Reloc, CodeOffset); /// Add a relocation referencing an external symbol at the current offset. - fn reloc_external(&mut self, CodeOffset, Reloc, &ExternalName); + fn reloc_external(&mut self, CodeOffset, Reloc, &ExternalName, Addend); /// Add a relocation referencing a jump table. fn reloc_jt(&mut self, CodeOffset, Reloc, JumpTable); @@ -96,9 +96,9 @@ impl<'a> CodeSink for MemoryCodeSink<'a> { self.relocs.reloc_ebb(ofs, rel, ebb_offset); } - fn reloc_external(&mut self, rel: Reloc, name: &ExternalName) { + fn reloc_external(&mut self, rel: Reloc, name: &ExternalName, addend: Addend) { let ofs = self.offset(); - self.relocs.reloc_external(ofs, rel, name); + self.relocs.reloc_external(ofs, rel, name, addend); } fn reloc_jt(&mut self, rel: Reloc, jt: JumpTable) { diff --git a/lib/cretonne/src/binemit/mod.rs b/lib/cretonne/src/binemit/mod.rs index 9814b2727f..fe6262cb70 100644 --- a/lib/cretonne/src/binemit/mod.rs +++ b/lib/cretonne/src/binemit/mod.rs @@ -19,6 +19,9 @@ use std::fmt; /// depends on the *host* platform, not the *target* platform. pub type CodeOffset = u32; +/// Addend to add to the symbol value. +pub type Addend = i64; + /// Relocation kinds for every ISA #[derive(Debug)] pub enum Reloc { @@ -78,8 +81,8 @@ pub trait CodeSink { /// Add a relocation referencing an EBB at the current offset. fn reloc_ebb(&mut self, Reloc, CodeOffset); - /// Add a relocation referencing an external symbol at the current offset. - fn reloc_external(&mut self, Reloc, &ExternalName); + /// Add a relocation referencing an external symbol plus the addend at the current offset. + fn reloc_external(&mut self, Reloc, &ExternalName, Addend); /// Add a relocation referencing a jump table. fn reloc_jt(&mut self, Reloc, JumpTable);