Browse Source

Merge pull request #2558 from cfallin/pic-symbol-refs

x64: support PC-rel symbol references using the GOT when in PIC mode.
pull/2563/head
Chris Fallin 4 years ago
committed by GitHub
parent
commit
81bc811236
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 43
      cranelift/codegen/src/isa/x64/inst/emit.rs
  2. 44
      cranelift/codegen/src/isa/x64/inst/emit_tests.rs
  3. 7
      cranelift/codegen/src/isa/x64/inst/mod.rs

43
cranelift/codegen/src/isa/x64/inst/emit.rs

@ -2716,16 +2716,41 @@ pub(crate) fn emit(
}
Inst::LoadExtName { dst, name, offset } => {
// The full address can be encoded in the register, with a relocation.
// Generates: movabsq $name, %dst
let enc_dst = int_reg_enc(dst.to_reg());
sink.put1(0x48 | ((enc_dst >> 3) & 1));
sink.put1(0xB8 | (enc_dst & 7));
emit_reloc(sink, state, Reloc::Abs8, name, *offset);
if info.flags().emit_all_ones_funcaddrs() {
sink.put8(u64::max_value());
if info.flags().is_pic() {
// Generates: movq symbol@GOTPCREL(%rip), %dst
let enc_dst = int_reg_enc(dst.to_reg());
sink.put1(0x48 | ((enc_dst >> 3) & 1) << 2);
sink.put1(0x8B);
sink.put1(0x05 | ((enc_dst & 7) << 3));
emit_reloc(sink, state, Reloc::X86GOTPCRel4, name, -4);
sink.put4(0);
// Offset in the relocation above applies to the address of the *GOT entry*, not
// the loaded address; so we emit a separate add or sub instruction if needed.
if *offset < 0 {
assert!(*offset >= -i32::MAX as i64);
sink.put1(0x48 | ((enc_dst >> 3) & 1));
sink.put1(0x81);
sink.put1(0xe8 | (enc_dst & 7));
sink.put4((-*offset) as u32);
} else if *offset > 0 {
assert!(*offset <= i32::MAX as i64);
sink.put1(0x48 | ((enc_dst >> 3) & 1));
sink.put1(0x81);
sink.put1(0xc0 | (enc_dst & 7));
sink.put4(*offset as u32);
}
} else {
sink.put8(0);
// The full address can be encoded in the register, with a relocation.
// Generates: movabsq $name, %dst
let enc_dst = int_reg_enc(dst.to_reg());
sink.put1(0x48 | ((enc_dst >> 3) & 1));
sink.put1(0xB8 | (enc_dst & 7));
emit_reloc(sink, state, Reloc::Abs8, name, *offset);
if info.flags().emit_all_ones_funcaddrs() {
sink.put8(u64::max_value());
} else {
sink.put8(0);
}
}
}

44
cranelift/codegen/src/isa/x64/inst/emit_tests.rs

@ -2860,6 +2860,46 @@ fn test_x64_emit() {
"call *321(%r10,%rdx,4)",
));
// ========================================================
// LoadExtName
// N.B.: test harness below sets is_pic.
insns.push((
Inst::LoadExtName {
dst: Writable::from_reg(r11),
name: Box::new(ExternalName::User {
namespace: 0,
index: 0,
}),
offset: 0,
},
"4C8B1D00000000",
"load_ext_name u0:0+0, %r11",
));
insns.push((
Inst::LoadExtName {
dst: Writable::from_reg(r11),
name: Box::new(ExternalName::User {
namespace: 0,
index: 0,
}),
offset: 0x12345678,
},
"4C8B1D000000004981C378563412",
"load_ext_name u0:0+305419896, %r11",
));
insns.push((
Inst::LoadExtName {
dst: Writable::from_reg(r11),
name: Box::new(ExternalName::User {
namespace: 0,
index: 0,
}),
offset: -0x12345678,
},
"4C8B1D000000004981EB78563412",
"load_ext_name u0:0+-305419896, %r11",
));
// ========================================================
// Ret
insns.push((Inst::ret(), "C3", "ret"));
@ -3781,7 +3821,9 @@ fn test_x64_emit() {
// ========================================================
// Actually run the tests!
let flags = settings::Flags::new(settings::builder());
let mut flag_builder = settings::builder();
flag_builder.enable("is_pic").unwrap();
let flags = settings::Flags::new(flag_builder);
use crate::settings::Configurable;
let mut isa_flag_builder = x64::settings::builder();

7
cranelift/codegen/src/isa/x64/inst/mod.rs

@ -397,7 +397,10 @@ pub enum Inst {
/// An instruction that will always trigger the illegal instruction exception.
Ud2 { trap_code: TrapCode },
/// Loads an external symbol in a register, with a relocation: movabsq $name, dst
/// Loads an external symbol in a register, with a relocation:
///
/// movq $name@GOTPCREL(%rip), dst if PIC is enabled, or
/// movabsq $name, dst otherwise.
LoadExtName {
dst: Writable<Reg>,
name: Box<ExternalName>,
@ -1726,7 +1729,7 @@ impl PrettyPrint for Inst {
dst, name, offset, ..
} => format!(
"{} {}+{}, {}",
ljustify("movaps".into()),
ljustify("load_ext_name".into()),
name,
offset,
show_ireg_sized(dst.to_reg(), mb_rru, 8),

Loading…
Cancel
Save