Skip to content

Commit e04830e

Browse files
committed
[PAC][CodeGen][ELF][AArch64] Support signed TLSDESC
Support the following relocations and assembly operators: - `R_AARCH64_AUTH_TLSDESC_ADR_PAGE21` (`:tlsdesc_auth:` for `adrp`) - `R_AARCH64_AUTH_TLSDESC_LD64_LO12` (`:tlsdesc_auth_lo12:` for `ldr`) - `R_AARCH64_AUTH_TLSDESC_ADD_LO12` (`:tlsdesc_auth_lo12:` for `add`) `TLSDESC_AUTH_CALLSEQ` pseudo-instruction is introduced which is later expanded to actual instruction sequence like the following. ``` adrp x0, :tlsdesc_auth:var ldr x16, [x0, #:tlsdesc_auth_lo12:var] add x0, x0, #:tlsdesc_auth_lo12:var blraa x16, x0 (TPIDR_EL0 offset now in x0) ``` Only SelectionDAG ISel is supported. Tests starting with 'ptrauth-' have corresponding variants w/o this prefix.
1 parent 45c01e8 commit e04830e

File tree

5 files changed

+188
-5
lines changed

5 files changed

+188
-5
lines changed

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2730,6 +2730,55 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
27302730
EmitToStreamer(*OutStreamer, TmpInstSB);
27312731
return;
27322732
}
2733+
case AArch64::TLSDESC_AUTH_CALLSEQ: {
2734+
/// lower this to:
2735+
/// adrp x0, :tlsdesc_auth:var
2736+
/// ldr x16, [x0, #:tlsdesc_auth_lo12:var]
2737+
/// add x0, x0, #:tlsdesc_auth_lo12:var
2738+
/// blraa x16, x0
2739+
/// (TPIDR_EL0 offset now in x0)
2740+
const MachineOperand &MO_Sym = MI->getOperand(0);
2741+
MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
2742+
MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
2743+
MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF);
2744+
MO_TLSDESC.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGE);
2745+
MCInstLowering.lowerOperand(MO_Sym, Sym);
2746+
MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
2747+
MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
2748+
2749+
MCInst Adrp;
2750+
Adrp.setOpcode(AArch64::ADRP);
2751+
Adrp.addOperand(MCOperand::createReg(AArch64::X0));
2752+
Adrp.addOperand(SymTLSDesc);
2753+
EmitToStreamer(*OutStreamer, Adrp);
2754+
2755+
MCInst Ldr;
2756+
Ldr.setOpcode(AArch64::LDRXui);
2757+
Ldr.addOperand(MCOperand::createReg(AArch64::X16));
2758+
Ldr.addOperand(MCOperand::createReg(AArch64::X0));
2759+
Ldr.addOperand(SymTLSDescLo12);
2760+
Ldr.addOperand(MCOperand::createImm(0));
2761+
EmitToStreamer(*OutStreamer, Ldr);
2762+
2763+
MCInst Add;
2764+
Add.setOpcode(AArch64::ADDXri);
2765+
Add.addOperand(MCOperand::createReg(AArch64::X0));
2766+
Add.addOperand(MCOperand::createReg(AArch64::X0));
2767+
Add.addOperand(SymTLSDescLo12);
2768+
Add.addOperand(MCOperand::createImm(AArch64_AM::getShiftValue(0)));
2769+
EmitToStreamer(*OutStreamer, Add);
2770+
2771+
// Authenticated TLSDESC accesses are not relatex.
2772+
// Thus, do not emit .tlsdesccall for AUTH TLSDESC.
2773+
2774+
MCInst Blraa;
2775+
Blraa.setOpcode(AArch64::BLRAA);
2776+
Blraa.addOperand(MCOperand::createReg(AArch64::X16));
2777+
Blraa.addOperand(MCOperand::createReg(AArch64::X0));
2778+
EmitToStreamer(*OutStreamer, Blraa);
2779+
2780+
return;
2781+
}
27332782
case AArch64::TLSDESC_CALLSEQ: {
27342783
/// lower this to:
27352784
/// adrp x0, :tlsdesc:var

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2668,6 +2668,7 @@ const char *AArch64TargetLowering::getTargetNodeName(unsigned Opcode) const {
26682668
MAKE_CASE(AArch64ISD::CSINC)
26692669
MAKE_CASE(AArch64ISD::THREAD_POINTER)
26702670
MAKE_CASE(AArch64ISD::TLSDESC_CALLSEQ)
2671+
MAKE_CASE(AArch64ISD::TLSDESC_AUTH_CALLSEQ)
26712672
MAKE_CASE(AArch64ISD::PROBED_ALLOCA)
26722673
MAKE_CASE(AArch64ISD::ABDS_PRED)
26732674
MAKE_CASE(AArch64ISD::ABDU_PRED)
@@ -9995,8 +9996,11 @@ SDValue AArch64TargetLowering::LowerELFTLSDescCallSeq(SDValue SymAddr,
99959996
SDValue Chain = DAG.getEntryNode();
99969997
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
99979998

9998-
Chain =
9999-
DAG.getNode(AArch64ISD::TLSDESC_CALLSEQ, DL, NodeTys, {Chain, SymAddr});
9999+
unsigned Opcode =
10000+
DAG.getMachineFunction().getInfo<AArch64FunctionInfo>()->hasELFSignedGOT()
10001+
? AArch64ISD::TLSDESC_AUTH_CALLSEQ
10002+
: AArch64ISD::TLSDESC_CALLSEQ;
10003+
Chain = DAG.getNode(Opcode, DL, NodeTys, {Chain, SymAddr});
1000010004
SDValue Glue = Chain.getValue(1);
1000110005

1000210006
return DAG.getCopyFromReg(Chain, DL, AArch64::X0, PtrVT, Glue);
@@ -10008,8 +10012,14 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SDValue Op,
1000810012
assert(Subtarget->isTargetELF() && "This function expects an ELF target");
1000910013

1001010014
const GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
10015+
AArch64FunctionInfo *MFI =
10016+
DAG.getMachineFunction().getInfo<AArch64FunctionInfo>();
1001110017

10012-
TLSModel::Model Model = getTargetMachine().getTLSModel(GA->getGlobal());
10018+
TLSModel::Model Model;
10019+
if (MFI->hasELFSignedGOT())
10020+
Model = TLSModel::GeneralDynamic;
10021+
else
10022+
Model = getTargetMachine().getTLSModel(GA->getGlobal());
1001310023

1001410024
if (!EnableAArch64ELFLocalDynamicTLSGeneration) {
1001510025
if (Model == TLSModel::LocalDynamic)
@@ -10046,8 +10056,6 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SDValue Op,
1004610056
// calculation.
1004710057

1004810058
// These accesses will need deduplicating if there's more than one.
10049-
AArch64FunctionInfo *MFI =
10050-
DAG.getMachineFunction().getInfo<AArch64FunctionInfo>();
1005110059
MFI->incNumLocalDynamicTLSAccesses();
1005210060

1005310061
// The call needs a relocation too for linker relaxation. It doesn't make

llvm/lib/Target/AArch64/AArch64ISelLowering.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ enum NodeType : unsigned {
8383
// Produces the full sequence of instructions for getting the thread pointer
8484
// offset of a variable into X0, using the TLSDesc model.
8585
TLSDESC_CALLSEQ,
86+
TLSDESC_AUTH_CALLSEQ,
8687
ADRP, // Page address of a TargetGlobalAddress operand.
8788
ADR, // ADR
8889
ADDlow, // Add the low 12 bits of a TargetGlobalAddress operand.

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,8 @@ def SDT_AArch64stnp : SDTypeProfile<0, 3, [SDTCisVT<0, v4i32>, SDTCisSameAs<0, 1
501501
// number of operands (the variable)
502502
def SDT_AArch64TLSDescCallSeq : SDTypeProfile<0,1,
503503
[SDTCisPtrTy<0>]>;
504+
def SDT_AArch64TLSDescAuthCallSeq : SDTypeProfile<0,1,
505+
[SDTCisPtrTy<0>]>;
504506

505507
def SDT_AArch64WrapperLarge : SDTypeProfile<1, 4,
506508
[SDTCisVT<0, i64>, SDTCisVT<1, i32>,
@@ -886,6 +888,10 @@ def AArch64tlsdesc_callseq : SDNode<"AArch64ISD::TLSDESC_CALLSEQ",
886888
SDT_AArch64TLSDescCallSeq,
887889
[SDNPOutGlue, SDNPHasChain, SDNPVariadic]>;
888890

891+
def AArch64tlsdesc_auth_callseq : SDNode<"AArch64ISD::TLSDESC_AUTH_CALLSEQ",
892+
SDT_AArch64TLSDescAuthCallSeq,
893+
[SDNPInGlue, SDNPOutGlue, SDNPHasChain,
894+
SDNPVariadic]>;
889895

890896
def AArch64WrapperLarge : SDNode<"AArch64ISD::WrapperLarge",
891897
SDT_AArch64WrapperLarge>;
@@ -3315,8 +3321,16 @@ def TLSDESC_CALLSEQ
33153321
: Pseudo<(outs), (ins i64imm:$sym),
33163322
[(AArch64tlsdesc_callseq tglobaltlsaddr:$sym)]>,
33173323
Sched<[WriteI, WriteLD, WriteI, WriteBrReg]>;
3324+
let isCall = 1, Defs = [NZCV, LR, X0, X16], hasSideEffects = 1, Size = 16,
3325+
isCodeGenOnly = 1 in
3326+
def TLSDESC_AUTH_CALLSEQ
3327+
: Pseudo<(outs), (ins i64imm:$sym),
3328+
[(AArch64tlsdesc_auth_callseq tglobaltlsaddr:$sym)]>,
3329+
Sched<[WriteI, WriteLD, WriteI, WriteBrReg]>;
33183330
def : Pat<(AArch64tlsdesc_callseq texternalsym:$sym),
33193331
(TLSDESC_CALLSEQ texternalsym:$sym)>;
3332+
def : Pat<(AArch64tlsdesc_auth_callseq texternalsym:$sym),
3333+
(TLSDESC_AUTH_CALLSEQ texternalsym:$sym)>;
33203334

33213335
//===----------------------------------------------------------------------===//
33223336
// Conditional branch (immediate) instruction.
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
; RUN: llc -mtriple=aarch64-unknown-linux-gnu -mattr=+pauth -relocation-model=pic \
2+
; RUN: -verify-machineinstrs < %s | FileCheck %s
3+
; RUN: llc -mtriple=aarch64-unknown-linux-gnu -mattr=+pauth -relocation-model=pic \
4+
; RUN: -filetype=obj < %s | llvm-readelf -r -s - | FileCheck --check-prefix=CHECK-OBJ %s
5+
; RUN: not --crash llc -mtriple=aarch64-unknown-linux-gnu -mattr=+pauth -relocation-model=pic \
6+
; RUN: -global-isel=1 < %s 2>&1 | FileCheck --check-prefix=CHECK-ERR %s
7+
8+
@general_dynamic_var = external thread_local global i32
9+
10+
define i32 @test_generaldynamic() {
11+
; CHECK-LABEL: test_generaldynamic:
12+
13+
%val = load i32, ptr @general_dynamic_var
14+
ret i32 %val
15+
16+
; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:general_dynamic_var
17+
; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var]
18+
; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var
19+
; CHECK-NEXT: blraa x16, x0
20+
; CHECK-NEXT: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
21+
; CHECK-NEXT: ldr w0, [x[[TPIDR]], x0]
22+
23+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
24+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
25+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
26+
; CHECK-OBJ-NOT: R_AARCH64_TLSDESC_CALL
27+
28+
; CHECK-ERR: LLVM ERROR: cannot select: %1:gpr64sp(p0) = G_GLOBAL_VALUE @general_dynamic_var (in function: test_generaldynamic)
29+
}
30+
31+
define ptr @test_generaldynamic_addr() {
32+
; CHECK-LABEL: test_generaldynamic_addr:
33+
34+
ret ptr @general_dynamic_var
35+
36+
; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:general_dynamic_var
37+
; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var]
38+
; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var
39+
; CHECK-NEXT: blraa x16, x0
40+
; CHECK-NEXT: mrs [[TP:x[0-9]+]], TPIDR_EL0
41+
; CHECK-NEXT: add x0, [[TP]], x0
42+
43+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
44+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
45+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
46+
; CHECK-OBJ-NOT: R_AARCH64_TLSDESC_CALL
47+
}
48+
49+
@local_dynamic_var = external thread_local(localdynamic) global i32
50+
51+
define i32 @test_localdynamic() {
52+
; CHECK-LABEL: test_localdynamic:
53+
54+
%val = load i32, ptr @local_dynamic_var
55+
ret i32 %val
56+
57+
; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:local_dynamic_var
58+
; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var]
59+
; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var
60+
; CHECK-NEXT: blraa x16, x0
61+
; CHECK-NEXT: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
62+
; CHECK-NEXT: ldr w0, [x[[TPIDR]], x0]
63+
64+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
65+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
66+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
67+
; CHECK-OBJ-NOT: R_AARCH64_TLSDESC_CALL
68+
}
69+
70+
define ptr @test_localdynamic_addr() {
71+
; CHECK-LABEL: test_localdynamic_addr:
72+
73+
ret ptr @local_dynamic_var
74+
75+
; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:local_dynamic_var
76+
; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var]
77+
; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var
78+
; CHECK-NEXT: blraa x16, x0
79+
; CHECK-NEXT: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
80+
; CHECK-NEXT: add x0, x[[TPIDR]], x0
81+
82+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
83+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
84+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
85+
; CHECK-OBJ-NOT: R_AARCH64_TLSDESC_CALL
86+
}
87+
88+
@extern_weak_var = extern_weak thread_local global i32
89+
90+
define i32 @test_extern_weak() {
91+
; CHECK-LABEL: test_extern_weak:
92+
93+
%val = load i32, ptr @extern_weak_var
94+
ret i32 %val
95+
96+
; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:extern_weak_var
97+
; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:extern_weak_var]
98+
; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:extern_weak_var
99+
; CHECK-NEXT: blraa x16, x0
100+
; CHECK-NEXT: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
101+
; CHECK-NEXT: ldr w0, [x[[TPIDR]], x0]
102+
103+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
104+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
105+
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
106+
; CHECK-OBJ-NOT: R_AARCH64_TLSDESC_CALL
107+
; CHECK-OBJ: 0000000000000000 0 TLS WEAK DEFAULT UND extern_weak_var
108+
}
109+
110+
!llvm.module.flags = !{!0}
111+
!0 = !{i32 8, !"ptrauth-elf-got", i32 1}

0 commit comments

Comments
 (0)