Skip to content

Commit 652f21e

Browse files
authored
Merge pull request #3026 from afonso360/aarch64-elf-tls
aarch64: Implement TLS ELF GD Relocations
2 parents 7d47ba1 + b8ad99e commit 652f21e

File tree

6 files changed

+129
-3
lines changed

6 files changed

+129
-3
lines changed

cranelift/codegen/src/binemit/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@ pub enum Reloc {
6868

6969
/// Mach-O x86_64 32 bit signed PC relative offset to a `__thread_vars` entry.
7070
MachOX86_64Tlv,
71+
72+
/// AArch64 TLS GD
73+
/// Set an ADRP immediate field to the top 21 bits of the final address. Checks for overflow.
74+
/// This is equivalent to `R_AARCH64_TLSGD_ADR_PAGE21` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#relocations-for-thread-local-storage)
75+
Aarch64TlsGdAdrPage21,
76+
77+
/// AArch64 TLS GD
78+
/// Set the add immediate field to the low 12 bits of the final address. Does not check for overflow.
79+
/// This is equivalent to `R_AARCH64_TLSGD_ADD_LO12_NC` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#relocations-for-thread-local-storage)
80+
Aarch64TlsGdAddLo12Nc,
7181
}
7282

7383
impl fmt::Display for Reloc {
@@ -87,6 +97,8 @@ impl fmt::Display for Reloc {
8797

8898
Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"),
8999
Self::MachOX86_64Tlv => write!(f, "MachOX86_64Tlv"),
100+
Self::Aarch64TlsGdAdrPage21 => write!(f, "Aarch64TlsGdAdrPage21"),
101+
Self::Aarch64TlsGdAddLo12Nc => write!(f, "Aarch64TlsGdAddLo12Nc"),
90102
}
91103
}
92104
}

cranelift/codegen/src/isa/aarch64/inst/emit.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::binemit::{CodeOffset, Reloc, StackMap};
44
use crate::ir::constant::ConstantData;
55
use crate::ir::types::*;
6-
use crate::ir::{MemFlags, TrapCode};
6+
use crate::ir::{LibCall, MemFlags, TrapCode};
77
use crate::isa::aarch64::inst::*;
88
use crate::machinst::ty_bits;
99

@@ -2563,6 +2563,32 @@ impl MachInstEmit for Inst {
25632563
sink.bind_label(jump_around_label);
25642564
}
25652565
}
2566+
2567+
&Inst::ElfTlsGetAddr { ref symbol } => {
2568+
// This is the instruction sequence that GCC emits for ELF GD TLS Relocations in aarch64
2569+
// See: https://gcc.godbolt.org/z/KhMh5Gvra
2570+
2571+
// adrp x0, <label>
2572+
sink.add_reloc(state.cur_srcloc(), Reloc::Aarch64TlsGdAdrPage21, symbol, 0);
2573+
sink.put4(0x90000000);
2574+
2575+
// add x0, x0, <label>
2576+
sink.add_reloc(state.cur_srcloc(), Reloc::Aarch64TlsGdAddLo12Nc, symbol, 0);
2577+
sink.put4(0x91000000);
2578+
2579+
// bl __tls_get_addr
2580+
sink.add_reloc(
2581+
state.cur_srcloc(),
2582+
Reloc::Arm64Call,
2583+
&ExternalName::LibCall(LibCall::ElfTlsGetAddr),
2584+
0,
2585+
);
2586+
sink.put4(0x94000000);
2587+
2588+
// nop
2589+
sink.put4(0xd503201f);
2590+
}
2591+
25662592
&Inst::ValueLabelMarker { .. } => {
25672593
// Nothing; this is only used to compute debug info.
25682594
}

cranelift/codegen/src/isa/aarch64/inst/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub mod args;
3030
pub use self::args::*;
3131
pub mod emit;
3232
pub use self::emit::*;
33+
use crate::isa::aarch64::abi::AArch64MachineDeps;
34+
3335
pub mod unwind;
3436

3537
#[cfg(test)]
@@ -1276,6 +1278,11 @@ pub enum Inst {
12761278
needed_space: CodeOffset,
12771279
},
12781280

1281+
/// A call to the `ElfTlsGetAddr` libcall. Returns address of TLS symbol in x0.
1282+
ElfTlsGetAddr {
1283+
symbol: ExternalName,
1284+
},
1285+
12791286
/// A definition of a value label.
12801287
ValueLabelMarker {
12811288
reg: Reg,
@@ -2150,6 +2157,12 @@ fn aarch64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
21502157
&Inst::ValueLabelMarker { reg, .. } => {
21512158
collector.add_use(reg);
21522159
}
2160+
2161+
&Inst::ElfTlsGetAddr { .. } => {
2162+
for reg in AArch64MachineDeps::get_regs_clobbered_by_call(CallConv::SystemV) {
2163+
collector.add_def(reg);
2164+
}
2165+
}
21532166
&Inst::Unwind { .. } => {}
21542167
&Inst::EmitIsland { .. } => {}
21552168
}
@@ -2959,6 +2972,7 @@ fn aarch64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
29592972
}
29602973
&mut Inst::VirtualSPOffsetAdj { .. } => {}
29612974
&mut Inst::EmitIsland { .. } => {}
2975+
&mut Inst::ElfTlsGetAddr { .. } => {}
29622976
&mut Inst::ValueLabelMarker { ref mut reg, .. } => {
29632977
map_use(mapper, reg);
29642978
}
@@ -4333,6 +4347,10 @@ impl Inst {
43334347
}
43344348
&Inst::EmitIsland { needed_space } => format!("emit_island {}", needed_space),
43354349

4350+
&Inst::ElfTlsGetAddr { ref symbol } => {
4351+
format!("elf_tls_get_addr {}", symbol)
4352+
}
4353+
43364354
&Inst::ValueLabelMarker { label, reg } => {
43374355
format!("value_label {:?}, {}", label, reg.show_rru(mb_rru))
43384356
}

cranelift/codegen/src/isa/aarch64/lower_inst.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::ir::{InstructionData, Opcode, TrapCode};
88
use crate::isa::aarch64::settings as aarch64_settings;
99
use crate::machinst::lower::*;
1010
use crate::machinst::*;
11-
use crate::settings::Flags;
11+
use crate::settings::{Flags, TlsModel};
1212
use crate::{CodegenError, CodegenResult};
1313

1414
use crate::isa::aarch64::abi::*;
@@ -3506,7 +3506,24 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
35063506
});
35073507
}
35083508

3509-
Opcode::TlsValue => unimplemented!("tls_value"),
3509+
Opcode::TlsValue => match flags.tls_model() {
3510+
TlsModel::ElfGd => {
3511+
let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
3512+
let (name, _, _) = ctx.symbol_value(insn).unwrap();
3513+
let symbol = name.clone();
3514+
ctx.emit(Inst::ElfTlsGetAddr { symbol });
3515+
3516+
let x0 = xreg(0);
3517+
ctx.emit(Inst::gen_move(dst, x0, I64));
3518+
}
3519+
_ => {
3520+
todo!(
3521+
"Unimplemented TLS model in AArch64 backend: {:?}",
3522+
flags.tls_model()
3523+
);
3524+
}
3525+
},
3526+
35103527
Opcode::FcvtLowFromSint => unimplemented!("FcvtLowFromSint"),
35113528
Opcode::FvpromoteLow => unimplemented!("FvpromoteLow"),
35123529
Opcode::Fvdemote => unimplemented!("Fvdemote"),
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
test compile
2+
set tls_model=elf_gd
3+
target aarch64
4+
5+
function u0:0(i32) -> i32, i64 {
6+
gv0 = symbol colocated tls u1:0
7+
8+
block0(v0: i32):
9+
v1 = global_value.i64 gv0
10+
return v0, v1
11+
}
12+
; check: stp fp, lr, [sp, #-16]!
13+
; nextln: mov fp, sp
14+
; nextln: str x19, [sp, #-16]!
15+
; nextln: stp d14, d15, [sp, #-16]!
16+
; nextln: stp d12, d13, [sp, #-16]!
17+
; nextln: stp d10, d11, [sp, #-16]!
18+
; nextln: stp d8, d9, [sp, #-16]!
19+
; nextln: mov x19, x0
20+
; nextln: elf_tls_get_addr u1:0
21+
; nextln: mov x1, x0
22+
; nextln: mov x0, x19
23+
; nextln: ldp d8, d9, [sp], #16
24+
; nextln: ldp d10, d11, [sp], #16
25+
; nextln: ldp d12, d13, [sp], #16
26+
; nextln: ldp d14, d15, [sp], #16
27+
; nextln: ldr x19, [sp], #16
28+
; nextln: ldp fp, lr, [sp], #16
29+
; nextln: ret

cranelift/object/src/backend.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,30 @@ impl ObjectModule {
618618
32,
619619
)
620620
}
621+
Reloc::Aarch64TlsGdAdrPage21 => {
622+
assert_eq!(
623+
self.object.format(),
624+
object::BinaryFormat::Elf,
625+
"Aarch64TlsGdAdrPrel21 is not supported for this file format"
626+
);
627+
(
628+
RelocationKind::Elf(object::elf::R_AARCH64_TLSGD_ADR_PAGE21),
629+
RelocationEncoding::Generic,
630+
21,
631+
)
632+
}
633+
Reloc::Aarch64TlsGdAddLo12Nc => {
634+
assert_eq!(
635+
self.object.format(),
636+
object::BinaryFormat::Elf,
637+
"Aarch64TlsGdAddLo12Nc is not supported for this file format"
638+
);
639+
(
640+
RelocationKind::Elf(object::elf::R_AARCH64_TLSGD_ADD_LO12_NC),
641+
RelocationEncoding::Generic,
642+
12,
643+
)
644+
}
621645
// FIXME
622646
reloc => unimplemented!("{:?}", reloc),
623647
};

0 commit comments

Comments
 (0)