[llvm-branch-commits] [llvm] [PAC][CodeGen][ELF][AArch64] Support signed TLSDESC (PR #113813)
Daniil Kovalev via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Oct 27 07:34:22 PDT 2024
https://github.com/kovdan01 created https://github.com/llvm/llvm-project/pull/113813
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
.tlsdesccall 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.
>From b3ff2bb40a3cfb8db35962acf2dccaca538b4ceb Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 21 Aug 2024 10:22:30 +0300
Subject: [PATCH] [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
.tlsdesccall 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.
---
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 59 ++++++++
.../Target/AArch64/AArch64ISelLowering.cpp | 16 ++-
llvm/lib/Target/AArch64/AArch64ISelLowering.h | 1 +
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 14 ++
.../lib/Target/AArch64/AArch64MCInstLower.cpp | 26 +++-
.../AArch64/AsmParser/AArch64AsmParser.cpp | 109 ++++++++-------
.../MCTargetDesc/AArch64ELFObjectWriter.cpp | 26 ++++
.../AArch64/MCTargetDesc/AArch64MCExpr.cpp | 4 +
.../AArch64/MCTargetDesc/AArch64MCExpr.h | 127 +++++++++---------
.../AArch64/ptrauth-arm64-tls-dynamics.ll | 104 ++++++++++++++
llvm/test/MC/AArch64/arm64-elf-relocs.s | 55 +++++---
llvm/test/MC/AArch64/ilp32-diagnostics.s | 9 ++
12 files changed, 409 insertions(+), 141 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/ptrauth-arm64-tls-dynamics.ll
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index e79457f925db66..8ec785027d23d7 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2603,6 +2603,65 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, TmpInstSB);
return;
}
+ case AArch64::TLSDESC_AUTH_CALLSEQ: {
+ /// lower this to:
+ /// adrp x0, :tlsdesc_auth:var
+ /// ldr x16, [x0, #:tlsdesc_auth_lo12:var]
+ /// add x0, x0, #:tlsdesc_auth_lo12:var
+ /// .tlsdesccall var
+ /// blraa x16, x0
+ /// (TPIDR_EL0 offset now in x0)
+ const MachineOperand &MO_Sym = MI->getOperand(0);
+ MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
+ MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
+ MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF);
+ MO_TLSDESC.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGE);
+ MCInstLowering.lowerOperand(MO_Sym, Sym);
+ MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
+ MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
+
+ MCInst Adrp;
+ Adrp.setOpcode(AArch64::ADRP);
+ Adrp.addOperand(MCOperand::createReg(AArch64::X0));
+ Adrp.addOperand(SymTLSDesc);
+ EmitToStreamer(*OutStreamer, Adrp);
+
+ MCInst Ldr;
+ Ldr.setOpcode(AArch64::LDRXui);
+ Ldr.addOperand(MCOperand::createReg(AArch64::X16));
+ Ldr.addOperand(MCOperand::createReg(AArch64::X0));
+ Ldr.addOperand(SymTLSDescLo12);
+ Ldr.addOperand(MCOperand::createImm(0));
+ EmitToStreamer(*OutStreamer, Ldr);
+
+ MCInst Add;
+ Add.setOpcode(AArch64::ADDXri);
+ Add.addOperand(MCOperand::createReg(AArch64::X0));
+ Add.addOperand(MCOperand::createReg(AArch64::X0));
+ Add.addOperand(SymTLSDescLo12);
+ Add.addOperand(MCOperand::createImm(AArch64_AM::getShiftValue(0)));
+ EmitToStreamer(*OutStreamer, Add);
+
+ // Emit a relocation-annotation. This expands to no code, but requests
+ // the following instruction gets an R_AARCH64_TLSDESC_CALL.
+ // TODO: we probably don't need that for AUTH TLSDESC. Emit as for now for
+ // consistency with non-AUTH case.
+ MCInst TLSDescCall;
+ TLSDescCall.setOpcode(AArch64::TLSDESCCALL);
+ TLSDescCall.addOperand(Sym);
+ EmitToStreamer(*OutStreamer, TLSDescCall);
+#ifndef NDEBUG
+ --InstsEmitted; // no code emitted
+#endif
+
+ MCInst Blraa;
+ Blraa.setOpcode(AArch64::BLRAA);
+ Blraa.addOperand(MCOperand::createReg(AArch64::X16));
+ Blraa.addOperand(MCOperand::createReg(AArch64::X0));
+ EmitToStreamer(*OutStreamer, Blraa);
+
+ return;
+ }
case AArch64::TLSDESC_CALLSEQ: {
/// lower this to:
/// adrp x0, :tlsdesc:var
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 884e5fe9f60040..108a01f34e2e81 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -2634,6 +2634,7 @@ const char *AArch64TargetLowering::getTargetNodeName(unsigned Opcode) const {
MAKE_CASE(AArch64ISD::CSINC)
MAKE_CASE(AArch64ISD::THREAD_POINTER)
MAKE_CASE(AArch64ISD::TLSDESC_CALLSEQ)
+ MAKE_CASE(AArch64ISD::TLSDESC_AUTH_CALLSEQ)
MAKE_CASE(AArch64ISD::PROBED_ALLOCA)
MAKE_CASE(AArch64ISD::ABDS_PRED)
MAKE_CASE(AArch64ISD::ABDU_PRED)
@@ -9889,8 +9890,11 @@ SDValue AArch64TargetLowering::LowerELFTLSDescCallSeq(SDValue SymAddr,
SDValue Chain = DAG.getEntryNode();
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
- Chain =
- DAG.getNode(AArch64ISD::TLSDESC_CALLSEQ, DL, NodeTys, {Chain, SymAddr});
+ unsigned Opcode =
+ DAG.getMachineFunction().getInfo<AArch64FunctionInfo>()->hasELFSignedGOT()
+ ? AArch64ISD::TLSDESC_AUTH_CALLSEQ
+ : AArch64ISD::TLSDESC_CALLSEQ;
+ Chain = DAG.getNode(Opcode, DL, NodeTys, {Chain, SymAddr});
SDValue Glue = Chain.getValue(1);
return DAG.getCopyFromReg(Chain, DL, AArch64::X0, PtrVT, Glue);
@@ -9903,7 +9907,13 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SDValue Op,
const GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
- TLSModel::Model Model = getTargetMachine().getTLSModel(GA->getGlobal());
+ TLSModel::Model Model;
+ if (DAG.getMachineFunction()
+ .getInfo<AArch64FunctionInfo>()
+ ->hasELFSignedGOT())
+ Model = TLSModel::GeneralDynamic;
+ else
+ Model = getTargetMachine().getTLSModel(GA->getGlobal());
if (!EnableAArch64ELFLocalDynamicTLSGeneration) {
if (Model == TLSModel::LocalDynamic)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 160cd18ca53b32..03c027d7497f96 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -85,6 +85,7 @@ enum NodeType : unsigned {
// Produces the full sequence of instructions for getting the thread pointer
// offset of a variable into X0, using the TLSDesc model.
TLSDESC_CALLSEQ,
+ TLSDESC_AUTH_CALLSEQ,
ADRP, // Page address of a TargetGlobalAddress operand.
ADR, // ADR
ADDlow, // Add the low 12 bits of a TargetGlobalAddress operand.
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index fdaa01598dcba5..c67b3996dc7c67 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -493,6 +493,8 @@ def SDT_AArch64stnp : SDTypeProfile<0, 3, [SDTCisVT<0, v4i32>, SDTCisSameAs<0, 1
// number of operands (the variable)
def SDT_AArch64TLSDescCallSeq : SDTypeProfile<0,1,
[SDTCisPtrTy<0>]>;
+def SDT_AArch64TLSDescAuthCallSeq : SDTypeProfile<0,1,
+ [SDTCisPtrTy<0>]>;
def SDT_AArch64WrapperLarge : SDTypeProfile<1, 4,
[SDTCisVT<0, i64>, SDTCisVT<1, i32>,
@@ -879,6 +881,10 @@ def AArch64tlsdesc_callseq : SDNode<"AArch64ISD::TLSDESC_CALLSEQ",
[SDNPInGlue, SDNPOutGlue, SDNPHasChain,
SDNPVariadic]>;
+def AArch64tlsdesc_auth_callseq : SDNode<"AArch64ISD::TLSDESC_AUTH_CALLSEQ",
+ SDT_AArch64TLSDescAuthCallSeq,
+ [SDNPInGlue, SDNPOutGlue, SDNPHasChain,
+ SDNPVariadic]>;
def AArch64WrapperLarge : SDNode<"AArch64ISD::WrapperLarge",
SDT_AArch64WrapperLarge>;
@@ -3294,8 +3300,16 @@ def TLSDESC_CALLSEQ
: Pseudo<(outs), (ins i64imm:$sym),
[(AArch64tlsdesc_callseq tglobaltlsaddr:$sym)]>,
Sched<[WriteI, WriteLD, WriteI, WriteBrReg]>;
+let isCall = 1, Defs = [NZCV, LR, X0, X16], hasSideEffects = 1, Size = 16,
+ isCodeGenOnly = 1 in
+def TLSDESC_AUTH_CALLSEQ
+ : Pseudo<(outs), (ins i64imm:$sym),
+ [(AArch64tlsdesc_auth_callseq tglobaltlsaddr:$sym)]>,
+ Sched<[WriteI, WriteLD, WriteI, WriteBrReg]>;
def : Pat<(AArch64tlsdesc_callseq texternalsym:$sym),
(TLSDESC_CALLSEQ texternalsym:$sym)>;
+def : Pat<(AArch64tlsdesc_auth_callseq texternalsym:$sym),
+ (TLSDESC_AUTH_CALLSEQ texternalsym:$sym)>;
//===----------------------------------------------------------------------===//
// Conditional branch (immediate) instruction.
diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
index 9f234b0f917058..46ce151ca82b64 100644
--- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
@@ -194,12 +194,16 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
} else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
TLSModel::Model Model;
if (MO.isGlobal()) {
- const GlobalValue *GV = MO.getGlobal();
- Model = Printer.TM.getTLSModel(GV);
- if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
- Model == TLSModel::LocalDynamic)
+ const MachineFunction *MF = MO.getParent()->getParent()->getParent();
+ if (MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT()) {
Model = TLSModel::GeneralDynamic;
-
+ } else {
+ const GlobalValue *GV = MO.getGlobal();
+ Model = Printer.TM.getTLSModel(GV);
+ if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
+ Model == TLSModel::LocalDynamic)
+ Model = TLSModel::GeneralDynamic;
+ }
} else {
assert(MO.isSymbol() &&
StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
@@ -218,10 +222,18 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
case TLSModel::LocalDynamic:
RefFlags |= AArch64MCExpr::VK_DTPREL;
break;
- case TLSModel::GeneralDynamic:
- RefFlags |= AArch64MCExpr::VK_TLSDESC;
+ case TLSModel::GeneralDynamic: {
+ // TODO: it's probably better to introduce MO_TLS_AUTH or smth and avoid
+ // running hasELFSignedGOT() every time, but existing flags already
+ // cover all 12 bits of SubReg_TargetFlags field in MachineOperand, and
+ // making the field wider breaks static assertions.
+ const MachineFunction *MF = MO.getParent()->getParent()->getParent();
+ RefFlags |= MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT()
+ ? AArch64MCExpr::VK_TLSDESC_AUTH
+ : AArch64MCExpr::VK_TLSDESC;
break;
}
+ }
} else if (MO.getTargetFlags() & AArch64II::MO_PREL) {
RefFlags |= AArch64MCExpr::VK_PREL;
} else {
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index b83ca3f7e52db4..b4c37c6d02cfdb 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -903,6 +903,7 @@ class AArch64Operand : public MCParsedAsmOperand {
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
+ ELFRefKind == AArch64MCExpr::VK_TLSDESC_AUTH_LO12 ||
ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
ELFRefKind == AArch64MCExpr::VK_SECREL_HI12 ||
ELFRefKind == AArch64MCExpr::VK_GOT_PAGE_LO15) {
@@ -1020,6 +1021,7 @@ class AArch64Operand : public MCParsedAsmOperand {
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
+ ELFRefKind == AArch64MCExpr::VK_TLSDESC_AUTH_LO12 ||
ELFRefKind == AArch64MCExpr::VK_SECREL_HI12 ||
ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
}
@@ -3313,7 +3315,8 @@ ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
ELFRefKind != AArch64MCExpr::VK_GOT_AUTH_PAGE &&
ELFRefKind != AArch64MCExpr::VK_GOT_PAGE_LO15 &&
ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
- ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
+ ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE &&
+ ELFRefKind != AArch64MCExpr::VK_TLSDESC_AUTH_PAGE) {
// The operand must be an @page or @gotpage qualified symbolref.
return Error(S, "page or gotpage label reference expected");
}
@@ -4390,56 +4393,59 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
return TokError("expect relocation specifier in operand after ':'");
std::string LowerCase = getTok().getIdentifier().lower();
- RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
- .Case("lo12", AArch64MCExpr::VK_LO12)
- .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
- .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
- .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
- .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
- .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
- .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
- .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
- .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
- .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
- .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
- .Case("prel_g3", AArch64MCExpr::VK_PREL_G3)
- .Case("prel_g2", AArch64MCExpr::VK_PREL_G2)
- .Case("prel_g2_nc", AArch64MCExpr::VK_PREL_G2_NC)
- .Case("prel_g1", AArch64MCExpr::VK_PREL_G1)
- .Case("prel_g1_nc", AArch64MCExpr::VK_PREL_G1_NC)
- .Case("prel_g0", AArch64MCExpr::VK_PREL_G0)
- .Case("prel_g0_nc", AArch64MCExpr::VK_PREL_G0_NC)
- .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
- .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
- .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
- .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
- .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
- .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
- .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
- .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
- .Case("pg_hi21_nc", AArch64MCExpr::VK_ABS_PAGE_NC)
- .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
- .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
- .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
- .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
- .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
- .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
- .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
- .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
- .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
- .Case("got", AArch64MCExpr::VK_GOT_PAGE)
- .Case("gotpage_lo15", AArch64MCExpr::VK_GOT_PAGE_LO15)
- .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
- .Case("got_auth", AArch64MCExpr::VK_GOT_AUTH_PAGE)
- .Case("got_auth_lo12", AArch64MCExpr::VK_GOT_AUTH_LO12)
- .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
- .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
- .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
- .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
- .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
- .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
- .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
- .Default(AArch64MCExpr::VK_INVALID);
+ RefKind =
+ StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
+ .Case("lo12", AArch64MCExpr::VK_LO12)
+ .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
+ .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
+ .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
+ .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
+ .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
+ .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
+ .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
+ .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
+ .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
+ .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
+ .Case("prel_g3", AArch64MCExpr::VK_PREL_G3)
+ .Case("prel_g2", AArch64MCExpr::VK_PREL_G2)
+ .Case("prel_g2_nc", AArch64MCExpr::VK_PREL_G2_NC)
+ .Case("prel_g1", AArch64MCExpr::VK_PREL_G1)
+ .Case("prel_g1_nc", AArch64MCExpr::VK_PREL_G1_NC)
+ .Case("prel_g0", AArch64MCExpr::VK_PREL_G0)
+ .Case("prel_g0_nc", AArch64MCExpr::VK_PREL_G0_NC)
+ .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
+ .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
+ .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
+ .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
+ .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
+ .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
+ .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
+ .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
+ .Case("pg_hi21_nc", AArch64MCExpr::VK_ABS_PAGE_NC)
+ .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
+ .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
+ .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
+ .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
+ .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
+ .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
+ .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
+ .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
+ .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
+ .Case("tlsdesc_auth_lo12", AArch64MCExpr::VK_TLSDESC_AUTH_LO12)
+ .Case("got", AArch64MCExpr::VK_GOT_PAGE)
+ .Case("gotpage_lo15", AArch64MCExpr::VK_GOT_PAGE_LO15)
+ .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
+ .Case("got_auth", AArch64MCExpr::VK_GOT_AUTH_PAGE)
+ .Case("got_auth_lo12", AArch64MCExpr::VK_GOT_AUTH_LO12)
+ .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
+ .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
+ .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
+ .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
+ .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
+ .Case("tlsdesc_auth", AArch64MCExpr::VK_TLSDESC_AUTH_PAGE)
+ .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
+ .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
+ .Default(AArch64MCExpr::VK_INVALID);
if (RefKind == AArch64MCExpr::VK_INVALID)
return TokError("expect relocation specifier in operand after ':'");
@@ -5813,6 +5819,7 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
+ ELFRefKind == AArch64MCExpr::VK_TLSDESC_AUTH_LO12 ||
ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
(Inst.getOpcode() == AArch64::ADDXri ||
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
index b5f5a58d96288e..61e92b16762522 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -178,6 +178,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
return R_CLS(TLSIE_ADR_GOTTPREL_PAGE21);
if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC)
return R_CLS(TLSDESC_ADR_PAGE21);
+ if (SymLoc == AArch64MCExpr::VK_TLSDESC_AUTH && !IsNC) {
+ if (IsILP32) {
+ Ctx.reportError(Fixup.getLoc(),
+ "ILP32 ADRP AUTH relocation not supported "
+ "(LP64 eqv: AUTH_TLSDESC_ADR_PAGE21)");
+ return ELF::R_AARCH64_NONE;
+ }
+ return ELF::R_AARCH64_AUTH_TLSDESC_ADR_PAGE21;
+ }
Ctx.reportError(Fixup.getLoc(),
"invalid symbol kind for ADRP relocation");
return ELF::R_AARCH64_NONE;
@@ -249,6 +258,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
return R_CLS(TLSLE_ADD_TPREL_LO12);
if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12)
return R_CLS(TLSDESC_ADD_LO12);
+ if (RefKind == AArch64MCExpr::VK_TLSDESC_AUTH_LO12) {
+ if (IsILP32) {
+ Ctx.reportError(Fixup.getLoc(),
+ "ILP32 ADD AUTH relocation not supported "
+ "(LP64 eqv: AUTH_TLSDESC_ADD_LO12)");
+ return ELF::R_AARCH64_NONE;
+ }
+ return ELF::R_AARCH64_AUTH_TLSDESC_ADD_LO12;
+ }
if (RefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 && IsNC) {
if (IsILP32) {
Ctx.reportError(Fixup.getLoc(),
@@ -393,6 +411,14 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
"TLSDESC_LD64_LO12)");
return ELF::R_AARCH64_NONE;
}
+ if (SymLoc == AArch64MCExpr::VK_TLSDESC_AUTH) {
+ if (!IsILP32)
+ return ELF::R_AARCH64_AUTH_TLSDESC_LD64_LO12;
+ Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store AUTH "
+ "relocation not supported (LP64 eqv: "
+ "AUTH_TLSDESC_LD64_LO12)");
+ return ELF::R_AARCH64_NONE;
+ }
Ctx.reportError(Fixup.getLoc(),
"invalid fixup for 64-bit load/store instruction");
return ELF::R_AARCH64_NONE;
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
index 3430b9002894f0..53e4e1730f070c 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
@@ -68,6 +68,7 @@ StringRef AArch64MCExpr::getVariantKindName() const {
case VK_TPREL_LO12: return ":tprel_lo12:";
case VK_TPREL_LO12_NC: return ":tprel_lo12_nc:";
case VK_TLSDESC_LO12: return ":tlsdesc_lo12:";
+ case VK_TLSDESC_AUTH_LO12: return ":tlsdesc_auth_lo12:";
case VK_ABS_PAGE: return "";
case VK_ABS_PAGE_NC: return ":pg_hi21_nc:";
case VK_GOT: return ":got:";
@@ -81,6 +82,8 @@ StringRef AArch64MCExpr::getVariantKindName() const {
case VK_GOTTPREL_G0_NC: return ":gottprel_g0_nc:";
case VK_TLSDESC: return "";
case VK_TLSDESC_PAGE: return ":tlsdesc:";
+ case VK_TLSDESC_AUTH: return "";
+ case VK_TLSDESC_AUTH_PAGE: return ":tlsdesc_auth:";
case VK_SECREL_LO12: return ":secrel_lo12:";
case VK_SECREL_HI12: return ":secrel_hi12:";
case VK_GOT_AUTH: return ":got_auth:";
@@ -154,6 +157,7 @@ void AArch64MCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
case VK_GOTTPREL:
case VK_TPREL:
case VK_TLSDESC:
+ case VK_TLSDESC_AUTH:
break;
}
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h
index 699992782f67b8..3f9a85d634d8f2 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h
@@ -28,19 +28,20 @@ class AArch64MCExpr : public MCTargetExpr {
// Symbol locations specifying (roughly speaking) what calculation should be
// performed to construct the final address for the relocated
// symbol. E.g. direct, via the GOT, ...
- VK_ABS = 0x001,
- VK_SABS = 0x002,
- VK_PREL = 0x003,
- VK_GOT = 0x004,
- VK_DTPREL = 0x005,
- VK_GOTTPREL = 0x006,
- VK_TPREL = 0x007,
- VK_TLSDESC = 0x008,
- VK_SECREL = 0x009,
- VK_AUTH = 0x00a,
- VK_AUTHADDR = 0x00b,
- VK_GOT_AUTH = 0x00c,
- VK_SymLocBits = 0x00f,
+ VK_ABS = 0x001,
+ VK_SABS = 0x002,
+ VK_PREL = 0x003,
+ VK_GOT = 0x004,
+ VK_DTPREL = 0x005,
+ VK_GOTTPREL = 0x006,
+ VK_TPREL = 0x007,
+ VK_TLSDESC = 0x008,
+ VK_SECREL = 0x009,
+ VK_AUTH = 0x00a,
+ VK_AUTHADDR = 0x00b,
+ VK_GOT_AUTH = 0x00c,
+ VK_TLSDESC_AUTH = 0x00d,
+ VK_SymLocBits = 0x00f,
// Variants specifying which part of the final address calculation is
// used. E.g. the low 12 bits for an ADD/LDR, the middle 16 bits for a
@@ -67,55 +68,57 @@ class AArch64MCExpr : public MCTargetExpr {
// omitted in line with assembly syntax here (VK_LO12 rather than VK_LO12_NC
// since a user would write ":lo12:").
VK_CALL = VK_ABS,
- VK_ABS_PAGE = VK_ABS | VK_PAGE,
- VK_ABS_PAGE_NC = VK_ABS | VK_PAGE | VK_NC,
- VK_ABS_G3 = VK_ABS | VK_G3,
- VK_ABS_G2 = VK_ABS | VK_G2,
- VK_ABS_G2_S = VK_SABS | VK_G2,
- VK_ABS_G2_NC = VK_ABS | VK_G2 | VK_NC,
- VK_ABS_G1 = VK_ABS | VK_G1,
- VK_ABS_G1_S = VK_SABS | VK_G1,
- VK_ABS_G1_NC = VK_ABS | VK_G1 | VK_NC,
- VK_ABS_G0 = VK_ABS | VK_G0,
- VK_ABS_G0_S = VK_SABS | VK_G0,
- VK_ABS_G0_NC = VK_ABS | VK_G0 | VK_NC,
- VK_LO12 = VK_ABS | VK_PAGEOFF | VK_NC,
- VK_PREL_G3 = VK_PREL | VK_G3,
- VK_PREL_G2 = VK_PREL | VK_G2,
- VK_PREL_G2_NC = VK_PREL | VK_G2 | VK_NC,
- VK_PREL_G1 = VK_PREL | VK_G1,
- VK_PREL_G1_NC = VK_PREL | VK_G1 | VK_NC,
- VK_PREL_G0 = VK_PREL | VK_G0,
- VK_PREL_G0_NC = VK_PREL | VK_G0 | VK_NC,
- VK_GOT_LO12 = VK_GOT | VK_PAGEOFF | VK_NC,
- VK_GOT_PAGE = VK_GOT | VK_PAGE,
- VK_GOT_PAGE_LO15 = VK_GOT | VK_LO15 | VK_NC,
- VK_GOT_AUTH_LO12 = VK_GOT_AUTH | VK_PAGEOFF | VK_NC,
- VK_GOT_AUTH_PAGE = VK_GOT_AUTH | VK_PAGE,
- VK_DTPREL_G2 = VK_DTPREL | VK_G2,
- VK_DTPREL_G1 = VK_DTPREL | VK_G1,
- VK_DTPREL_G1_NC = VK_DTPREL | VK_G1 | VK_NC,
- VK_DTPREL_G0 = VK_DTPREL | VK_G0,
- VK_DTPREL_G0_NC = VK_DTPREL | VK_G0 | VK_NC,
- VK_DTPREL_HI12 = VK_DTPREL | VK_HI12,
- VK_DTPREL_LO12 = VK_DTPREL | VK_PAGEOFF,
- VK_DTPREL_LO12_NC = VK_DTPREL | VK_PAGEOFF | VK_NC,
- VK_GOTTPREL_PAGE = VK_GOTTPREL | VK_PAGE,
- VK_GOTTPREL_LO12_NC = VK_GOTTPREL | VK_PAGEOFF | VK_NC,
- VK_GOTTPREL_G1 = VK_GOTTPREL | VK_G1,
- VK_GOTTPREL_G0_NC = VK_GOTTPREL | VK_G0 | VK_NC,
- VK_TPREL_G2 = VK_TPREL | VK_G2,
- VK_TPREL_G1 = VK_TPREL | VK_G1,
- VK_TPREL_G1_NC = VK_TPREL | VK_G1 | VK_NC,
- VK_TPREL_G0 = VK_TPREL | VK_G0,
- VK_TPREL_G0_NC = VK_TPREL | VK_G0 | VK_NC,
- VK_TPREL_HI12 = VK_TPREL | VK_HI12,
- VK_TPREL_LO12 = VK_TPREL | VK_PAGEOFF,
- VK_TPREL_LO12_NC = VK_TPREL | VK_PAGEOFF | VK_NC,
- VK_TLSDESC_LO12 = VK_TLSDESC | VK_PAGEOFF,
- VK_TLSDESC_PAGE = VK_TLSDESC | VK_PAGE,
- VK_SECREL_LO12 = VK_SECREL | VK_PAGEOFF,
- VK_SECREL_HI12 = VK_SECREL | VK_HI12,
+ VK_ABS_PAGE = VK_ABS | VK_PAGE,
+ VK_ABS_PAGE_NC = VK_ABS | VK_PAGE | VK_NC,
+ VK_ABS_G3 = VK_ABS | VK_G3,
+ VK_ABS_G2 = VK_ABS | VK_G2,
+ VK_ABS_G2_S = VK_SABS | VK_G2,
+ VK_ABS_G2_NC = VK_ABS | VK_G2 | VK_NC,
+ VK_ABS_G1 = VK_ABS | VK_G1,
+ VK_ABS_G1_S = VK_SABS | VK_G1,
+ VK_ABS_G1_NC = VK_ABS | VK_G1 | VK_NC,
+ VK_ABS_G0 = VK_ABS | VK_G0,
+ VK_ABS_G0_S = VK_SABS | VK_G0,
+ VK_ABS_G0_NC = VK_ABS | VK_G0 | VK_NC,
+ VK_LO12 = VK_ABS | VK_PAGEOFF | VK_NC,
+ VK_PREL_G3 = VK_PREL | VK_G3,
+ VK_PREL_G2 = VK_PREL | VK_G2,
+ VK_PREL_G2_NC = VK_PREL | VK_G2 | VK_NC,
+ VK_PREL_G1 = VK_PREL | VK_G1,
+ VK_PREL_G1_NC = VK_PREL | VK_G1 | VK_NC,
+ VK_PREL_G0 = VK_PREL | VK_G0,
+ VK_PREL_G0_NC = VK_PREL | VK_G0 | VK_NC,
+ VK_GOT_LO12 = VK_GOT | VK_PAGEOFF | VK_NC,
+ VK_GOT_PAGE = VK_GOT | VK_PAGE,
+ VK_GOT_PAGE_LO15 = VK_GOT | VK_LO15 | VK_NC,
+ VK_GOT_AUTH_LO12 = VK_GOT_AUTH | VK_PAGEOFF | VK_NC,
+ VK_GOT_AUTH_PAGE = VK_GOT_AUTH | VK_PAGE,
+ VK_DTPREL_G2 = VK_DTPREL | VK_G2,
+ VK_DTPREL_G1 = VK_DTPREL | VK_G1,
+ VK_DTPREL_G1_NC = VK_DTPREL | VK_G1 | VK_NC,
+ VK_DTPREL_G0 = VK_DTPREL | VK_G0,
+ VK_DTPREL_G0_NC = VK_DTPREL | VK_G0 | VK_NC,
+ VK_DTPREL_HI12 = VK_DTPREL | VK_HI12,
+ VK_DTPREL_LO12 = VK_DTPREL | VK_PAGEOFF,
+ VK_DTPREL_LO12_NC = VK_DTPREL | VK_PAGEOFF | VK_NC,
+ VK_GOTTPREL_PAGE = VK_GOTTPREL | VK_PAGE,
+ VK_GOTTPREL_LO12_NC = VK_GOTTPREL | VK_PAGEOFF | VK_NC,
+ VK_GOTTPREL_G1 = VK_GOTTPREL | VK_G1,
+ VK_GOTTPREL_G0_NC = VK_GOTTPREL | VK_G0 | VK_NC,
+ VK_TPREL_G2 = VK_TPREL | VK_G2,
+ VK_TPREL_G1 = VK_TPREL | VK_G1,
+ VK_TPREL_G1_NC = VK_TPREL | VK_G1 | VK_NC,
+ VK_TPREL_G0 = VK_TPREL | VK_G0,
+ VK_TPREL_G0_NC = VK_TPREL | VK_G0 | VK_NC,
+ VK_TPREL_HI12 = VK_TPREL | VK_HI12,
+ VK_TPREL_LO12 = VK_TPREL | VK_PAGEOFF,
+ VK_TPREL_LO12_NC = VK_TPREL | VK_PAGEOFF | VK_NC,
+ VK_TLSDESC_LO12 = VK_TLSDESC | VK_PAGEOFF,
+ VK_TLSDESC_PAGE = VK_TLSDESC | VK_PAGE,
+ VK_TLSDESC_AUTH_LO12 = VK_TLSDESC_AUTH | VK_PAGEOFF,
+ VK_TLSDESC_AUTH_PAGE = VK_TLSDESC_AUTH | VK_PAGE,
+ VK_SECREL_LO12 = VK_SECREL | VK_PAGEOFF,
+ VK_SECREL_HI12 = VK_SECREL | VK_HI12,
VK_INVALID = 0xfff
// clang-format on
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-arm64-tls-dynamics.ll b/llvm/test/CodeGen/AArch64/ptrauth-arm64-tls-dynamics.ll
new file mode 100644
index 00000000000000..6716a97608047d
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-arm64-tls-dynamics.ll
@@ -0,0 +1,104 @@
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -mattr=+pauth -relocation-model=pic \
+; RUN: -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -mattr=+pauth -relocation-model=pic \
+; RUN: -filetype=obj < %s | llvm-readelf -r -s - | FileCheck --check-prefix=CHECK-OBJ %s
+; RUN: not --crash llc -mtriple=aarch64-unknown-linux-gnu -mattr=+pauth -relocation-model=pic \
+; RUN: -global-isel=1 < %s 2>&1 | FileCheck --check-prefix=CHECK-ERR %s
+
+ at general_dynamic_var = external thread_local global i32
+
+define i32 @test_generaldynamic() {
+; CHECK-LABEL: test_generaldynamic:
+
+ %val = load i32, ptr @general_dynamic_var
+ ret i32 %val
+
+; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:general_dynamic_var
+; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var]
+; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var
+; CHECK-NEXT: .tlsdesccall general_dynamic_var
+; CHECK-NEXT: blraa x16, x0
+
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
+; CHECK-OBJ: R_AARCH64_TLSDESC_CALL
+
+; CHECK-ERR: LLVM ERROR: cannot select: %1:gpr64sp(p0) = G_GLOBAL_VALUE @general_dynamic_var (in function: test_generaldynamic)
+}
+
+define ptr @test_generaldynamic_addr() {
+; CHECK-LABEL: test_generaldynamic_addr:
+
+ ret ptr @general_dynamic_var
+
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
+; CHECK-OBJ: R_AARCH64_TLSDESC_CALL
+}
+
+ at local_dynamic_var = external thread_local(localdynamic) global i32
+
+define i32 @test_localdynamic() {
+; CHECK-LABEL: test_localdynamic:
+
+ %val = load i32, ptr @local_dynamic_var
+ ret i32 %val
+
+; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:local_dynamic_var
+; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var]
+; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var
+; CHECK-NEXT: .tlsdesccall local_dynamic_var
+; CHECK-NEXT: blraa x16, x0
+; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
+; CHECK: ldr w0, [x[[TPIDR]], x0]
+
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
+; CHECK-OBJ: R_AARCH64_TLSDESC_CALL
+}
+
+define ptr @test_localdynamic_addr() {
+; CHECK-LABEL: test_localdynamic_addr:
+
+ ret ptr @local_dynamic_var
+
+; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:local_dynamic_var
+; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var]
+; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var
+; CHECK-NEXT: .tlsdesccall local_dynamic_var
+; CHECK-NEXT: blraa x16, x0
+; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
+; CHECK: add x0, x[[TPIDR]], x0
+
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
+; CHECK-OBJ: R_AARCH64_TLSDESC_CALL
+}
+
+ at extern_weak_var = extern_weak thread_local global i32
+
+define i32 @test_extern_weak() {
+; CHECK-LABEL: test_extern_weak:
+
+ %val = load i32, ptr @extern_weak_var
+ ret i32 %val
+
+; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:extern_weak_var
+; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:extern_weak_var]
+; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:extern_weak_var
+; CHECK-NEXT: .tlsdesccall extern_weak_var
+; CHECK-NEXT: blraa x16, x0
+
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
+; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
+; CHECK-OBJ: R_AARCH64_TLSDESC_CALL
+; CHECK-OBJ: 0000000000000000 0 TLS WEAK DEFAULT UND extern_weak_var
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/MC/AArch64/arm64-elf-relocs.s b/llvm/test/MC/AArch64/arm64-elf-relocs.s
index f679bb4c82827b..5ddfe7a84b0408 100644
--- a/llvm/test/MC/AArch64/arm64-elf-relocs.s
+++ b/llvm/test/MC/AArch64/arm64-elf-relocs.s
@@ -35,63 +35,75 @@
// CHECK: add x5, x0, :tlsdesc_lo12:sym
// CHECK-OBJ-LP64: 1c R_AARCH64_TLSDESC_ADD_LO12 sym
+ add x5, x0, #:tlsdesc_auth_lo12:sym
+// CHECK: add x5, x0, :tlsdesc_auth_lo12:sym
+// CHECK-OBJ-LP64: 20 R_AARCH64_AUTH_TLSDESC_ADD_LO12 sym
+
add x0, x2, #:lo12:sym+8
// CHECK: add x0, x2, :lo12:sym
-// CHECK-OBJ-LP64: 20 R_AARCH64_ADD_ABS_LO12_NC sym+0x8
+// CHECK-OBJ-LP64: 24 R_AARCH64_ADD_ABS_LO12_NC sym+0x8
add x5, x7, #:dtprel_lo12:sym+1
// CHECK: add x5, x7, :dtprel_lo12:sym+1
-// CHECK-OBJ-LP64: 24 R_AARCH64_TLSLD_ADD_DTPREL_LO12 sym+0x1
+// CHECK-OBJ-LP64: 28 R_AARCH64_TLSLD_ADD_DTPREL_LO12 sym+0x1
add x9, x12, #:dtprel_lo12_nc:sym+2
// CHECK: add x9, x12, :dtprel_lo12_nc:sym+2
-// CHECK-OBJ-LP64: 28 R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC sym+0x2
+// CHECK-OBJ-LP64: 2c R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC sym+0x2
add x20, x30, #:tprel_lo12:sym+12
// CHECK: add x20, x30, :tprel_lo12:sym+12
-// CHECK-OBJ-LP64: 2c R_AARCH64_TLSLE_ADD_TPREL_LO12 sym+0xc
+// CHECK-OBJ-LP64: 30 R_AARCH64_TLSLE_ADD_TPREL_LO12 sym+0xc
add x9, x12, #:tprel_lo12_nc:sym+54
// CHECK: add x9, x12, :tprel_lo12_nc:sym+54
-// CHECK-OBJ-LP64: 30 R_AARCH64_TLSLE_ADD_TPREL_LO12_NC sym+0x36
+// CHECK-OBJ-LP64: 34 R_AARCH64_TLSLE_ADD_TPREL_LO12_NC sym+0x36
add x5, x0, #:tlsdesc_lo12:sym+70
// CHECK: add x5, x0, :tlsdesc_lo12:sym+70
-// CHECK-OBJ-LP64: 34 R_AARCH64_TLSDESC_ADD_LO12 sym+0x46
+// CHECK-OBJ-LP64: 38 R_AARCH64_TLSDESC_ADD_LO12 sym+0x46
+
+ add x5, x0, #:tlsdesc_auth_lo12:sym+70
+// CHECK: add x5, x0, :tlsdesc_auth_lo12:sym+70
+// CHECK-OBJ-LP64: 3c R_AARCH64_AUTH_TLSDESC_ADD_LO12 sym+0x46
.hword sym + 4 - .
-// CHECK-OBJ-LP64: 38 R_AARCH64_PREL16 sym+0x4
+// CHECK-OBJ-LP64: 40 R_AARCH64_PREL16 sym+0x4
.word sym - . + 8
-// CHECK-OBJ-LP64: 3a R_AARCH64_PREL32 sym+0x8
+// CHECK-OBJ-LP64: 42 R_AARCH64_PREL32 sym+0x8
.xword sym-.
-// CHECK-OBJ-LP64: 3e R_AARCH64_PREL64 sym{{$}}
+// CHECK-OBJ-LP64: 46 R_AARCH64_PREL64 sym{{$}}
.hword sym
-// CHECK-OBJ-LP64: 46 R_AARCH64_ABS16 sym
+// CHECK-OBJ-LP64: 4e R_AARCH64_ABS16 sym
.word sym+1
-// CHECK-OBJ-LP64: 48 R_AARCH64_ABS32 sym+0x1
+// CHECK-OBJ-LP64: 50 R_AARCH64_ABS32 sym+0x1
.xword sym+16
-// CHECK-OBJ-LP64: 4c R_AARCH64_ABS64 sym+0x10
+// CHECK-OBJ-LP64: 54 R_AARCH64_ABS64 sym+0x10
adrp x0, sym
// CHECK: adrp x0, sym
-// CHECK-OBJ-LP64: 54 R_AARCH64_ADR_PREL_PG_HI21 sym
+// CHECK-OBJ-LP64: 5c R_AARCH64_ADR_PREL_PG_HI21 sym
adrp x15, :got:sym
// CHECK: adrp x15, :got:sym
-// CHECK-OBJ-LP64: 58 R_AARCH64_ADR_GOT_PAGE sym
+// CHECK-OBJ-LP64: 60 R_AARCH64_ADR_GOT_PAGE sym
adrp x15, :got_auth:sym
// CHECK: adrp x15, :got_auth:sym
-// CHECK-OBJ-LP64: 5c R_AARCH64_AUTH_ADR_GOT_PAGE sym
+// CHECK-OBJ-LP64: 64 R_AARCH64_AUTH_ADR_GOT_PAGE sym
adrp x29, :gottprel:sym
// CHECK: adrp x29, :gottprel:sym
-// CHECK-OBJ-LP64: 60 R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym
+// CHECK-OBJ-LP64: 68 R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym
adrp x2, :tlsdesc:sym
// CHECK: adrp x2, :tlsdesc:sym
-// CHECK-OBJ-LP64: 64 R_AARCH64_TLSDESC_ADR_PAGE21 sym
+// CHECK-OBJ-LP64: 6c R_AARCH64_TLSDESC_ADR_PAGE21 sym
+
+ adrp x2, :tlsdesc_auth:sym
+// CHECK: adrp x2, :tlsdesc_auth:sym
+// CHECK-OBJ-LP64: 70 R_AARCH64_AUTH_TLSDESC_ADR_PAGE21 sym
// LLVM is not competent enough to do this relocation because the
// page boundary could occur anywhere after linking. A relocation
@@ -100,7 +112,7 @@
.global trickQuestion
trickQuestion:
// CHECK: adrp x3, trickQuestion
-// CHECK-OBJ-LP64: 68 R_AARCH64_ADR_PREL_PG_HI21 trickQuestion
+// CHECK-OBJ-LP64: 74 R_AARCH64_ADR_PREL_PG_HI21 trickQuestion
ldrb w2, [x3, :lo12:sym]
ldrsb w5, [x7, #:lo12:sym]
@@ -311,6 +323,13 @@ trickQuestion:
// CHECK-OBJ-LP64: R_AARCH64_TLSDESC_LD64_LO12 sym
// CHECK-OBJ-LP64: R_AARCH64_TLSDESC_LD64_LO12 sym
+ ldr x24, [x23, #:tlsdesc_auth_lo12:sym]
+ ldr d22, [x21, :tlsdesc_auth_lo12:sym]
+// CHECK: ldr x24, [x23, :tlsdesc_auth_lo12:sym]
+// CHECK: ldr d22, [x21, :tlsdesc_auth_lo12:sym]
+// CHECK-OBJ-LP64: R_AARCH64_AUTH_TLSDESC_LD64_LO12 sym
+// CHECK-OBJ-LP64: R_AARCH64_AUTH_TLSDESC_LD64_LO12 sym
+
ldr q20, [x19, #:lo12:sym]
// CHECK: ldr q20, [x19, :lo12:sym]
// CHECK-OBJ-LP64: R_AARCH64_LDST128_ABS_LO12_NC sym
diff --git a/llvm/test/MC/AArch64/ilp32-diagnostics.s b/llvm/test/MC/AArch64/ilp32-diagnostics.s
index 5d9c6e5626b2b3..dd37834a0e7b1e 100644
--- a/llvm/test/MC/AArch64/ilp32-diagnostics.s
+++ b/llvm/test/MC/AArch64/ilp32-diagnostics.s
@@ -87,3 +87,12 @@ ldr x24, [x23, #:got_lo12:sym]
ldr x24, [x23, :gottprel_lo12:sym]
// ERROR: [[#@LINE-1]]:1: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: TLSIE_LD64_GOTTPREL_LO12_NC)
+
+adrp x24, :tlsdesc_auth:sym
+// ERROR: error: ILP32 ADRP AUTH relocation not supported (LP64 eqv: AUTH_TLSDESC_ADR_PAGE21)
+
+ldr x24, [x23, :tlsdesc_auth_lo12:sym]
+// ERROR: error: ILP32 64-bit load/store AUTH relocation not supported (LP64 eqv: AUTH_TLSDESC_LD64_LO12)
+
+add x24, x23, :tlsdesc_auth_lo12:sym
+// ERROR: error: ILP32 ADD AUTH relocation not supported (LP64 eqv: AUTH_TLSDESC_ADD_LO12)
More information about the llvm-branch-commits
mailing list