Skip to content

Commit

Permalink
Align IntelGOTPCRel4 with R_X86_64_GOTPCREL.
Browse files Browse the repository at this point in the history
Add an addend field to reloc_external, and use it to move the
responsibility for accounting for the difference between the end of an
instruction (where the PC is considered to be in PC-relative on intel)
and the beginning of the immediate field into the encoding code.

Specifically, this makes IntelGOTPCRel4 directly correspond to
R_X86_64_GOTPCREL, instead of also carrying an implicit `- 4`.
  • Loading branch information
sunfishcode committed Dec 15, 2017
1 parent a6ed884 commit dbb9163
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 26 deletions.
12 changes: 6 additions & 6 deletions filetests/isa/intel/binary64-pic.cton
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
34 changes: 24 additions & 10 deletions lib/cretonne/meta/isa/intel/recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,8 @@ def floatccs(iform):
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);
''')

Expand All @@ -532,7 +533,8 @@ def floatccs(iform):
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);
''')

Expand All @@ -542,7 +544,8 @@ def floatccs(iform):
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);
''')
Expand All @@ -553,7 +556,8 @@ def floatccs(iform):
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);
''')
Expand All @@ -565,8 +569,11 @@ def floatccs(iform):
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);
''')

Expand All @@ -577,7 +584,8 @@ def floatccs(iform):
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);
''')

Expand All @@ -587,7 +595,8 @@ def floatccs(iform):
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);
''')

Expand All @@ -597,8 +606,11 @@ def floatccs(iform):
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);
''')

Expand Down Expand Up @@ -874,7 +886,8 @@ def floatccs(iform):
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);
''')

Expand All @@ -883,7 +896,8 @@ def floatccs(iform):
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);
''')

Expand Down
3 changes: 2 additions & 1 deletion lib/cretonne/meta/isa/riscv/recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ def LUI():
'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);
''')
Expand Down
8 changes: 4 additions & 4 deletions lib/cretonne/src/binemit/memorysink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
7 changes: 5 additions & 2 deletions lib/cretonne/src/binemit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 18 additions & 2 deletions src/filetest/binemit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 7 additions & 1 deletion src/filetest/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
}

0 comments on commit dbb9163

Please sign in to comment.