[llvm] 182c61d - AArch64: Correctly emit large addends into PAuth ifunc.
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 10 13:47:12 PST 2025
Author: Peter Collingbourne
Date: 2025-12-10T13:47:08-08:00
New Revision: 182c61da17bfd4d06079fc96ed6d47669a2b7ff4
URL: https://github.com/llvm/llvm-project/commit/182c61da17bfd4d06079fc96ed6d47669a2b7ff4
DIFF: https://github.com/llvm/llvm-project/commit/182c61da17bfd4d06079fc96ed6d47669a2b7ff4.diff
LOG: AArch64: Correctly emit large addends into PAuth ifunc.
Previously we would hit an assertion failure when a relocation represented
by a PAuth ifunc required a GOT and the addend of a relocation did not fit
into the immediate operand of an ADD instruction. Fix it by extracting a
function for materializing arbitrary addends and using it to materialize
the addend.
Reviewers: fmayer, hvdijk
Pull Request: https://github.com/llvm/llvm-project/pull/171707
Added:
Modified:
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 25fc59e3fc258..28a52ab8b1ae6 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -219,6 +219,10 @@ class AArch64AsmPrinter : public AsmPrinter {
// authenticating)
void LowerLOADgotAUTH(const MachineInstr &MI);
+ void emitAddImm(MCRegister Val, int64_t Addend, MCRegister Tmp);
+ void emitAddress(MCRegister Reg, const MCExpr *Expr, MCRegister Tmp,
+ bool DSOLocal, const MCSubtargetInfo &STI);
+
const MCExpr *emitPAuthRelocationAsIRelative(
const MCExpr *Target, uint64_t Disc, AArch64PACKey::ID KeyID,
bool HasAddressDiversity, bool IsDSOLocal, const MCExpr *DSExpr);
@@ -2336,50 +2340,82 @@ void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, BRInst);
}
-static void emitAddress(MCStreamer &Streamer, MCRegister Reg,
- const MCExpr *Expr, bool DSOLocal,
- const MCSubtargetInfo &STI) {
+void AArch64AsmPrinter::emitAddImm(MCRegister Reg, int64_t Addend,
+ MCRegister Tmp) {
+ if (Addend != 0) {
+ const uint64_t AbsOffset = (Addend > 0 ? Addend : -((uint64_t)Addend));
+ const bool IsNeg = Addend < 0;
+ if (isUInt<24>(AbsOffset)) {
+ for (int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
+ BitPos += 12) {
+ EmitToStreamer(
+ MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
+ .addReg(Reg)
+ .addReg(Reg)
+ .addImm((AbsOffset >> BitPos) & 0xfff)
+ .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, BitPos)));
+ }
+ } else {
+ const uint64_t UAddend = Addend;
+ EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
+ .addReg(Tmp)
+ .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
+ .addImm(/*shift=*/0));
+ auto NeedMovk = [IsNeg, UAddend](int BitPos) -> bool {
+ assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
+ uint64_t Shifted = UAddend >> BitPos;
+ if (!IsNeg)
+ return Shifted != 0;
+ for (int I = 0; I != 64 - BitPos; I += 16)
+ if (((Shifted >> I) & 0xffff) != 0xffff)
+ return true;
+ return false;
+ };
+ for (int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
+ emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
+
+ EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
+ .addReg(Reg)
+ .addReg(Reg)
+ .addReg(Tmp)
+ .addImm(/*shift=*/0));
+ }
+ }
+}
+
+void AArch64AsmPrinter::emitAddress(MCRegister Reg, const MCExpr *Expr,
+ MCRegister Tmp, bool DSOLocal,
+ const MCSubtargetInfo &STI) {
MCValue Val;
if (!Expr->evaluateAsRelocatable(Val, nullptr))
report_fatal_error("emitAddress could not evaluate");
if (DSOLocal) {
- Streamer.emitInstruction(
+ EmitToStreamer(
MCInstBuilder(AArch64::ADRP)
.addReg(Reg)
.addExpr(MCSpecifierExpr::create(Expr, AArch64::S_ABS_PAGE,
- Streamer.getContext())),
- STI);
- Streamer.emitInstruction(
- MCInstBuilder(AArch64::ADDXri)
- .addReg(Reg)
- .addReg(Reg)
- .addExpr(MCSpecifierExpr::create(Expr, AArch64::S_LO12,
- Streamer.getContext()))
- .addImm(0),
- STI);
+ OutStreamer->getContext())));
+ EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
+ .addReg(Reg)
+ .addReg(Reg)
+ .addExpr(MCSpecifierExpr::create(
+ Expr, AArch64::S_LO12, OutStreamer->getContext()))
+ .addImm(0));
} else {
auto *SymRef =
- MCSymbolRefExpr::create(Val.getAddSym(), Streamer.getContext());
- Streamer.emitInstruction(
+ MCSymbolRefExpr::create(Val.getAddSym(), OutStreamer->getContext());
+ EmitToStreamer(
MCInstBuilder(AArch64::ADRP)
.addReg(Reg)
.addExpr(MCSpecifierExpr::create(SymRef, AArch64::S_GOT_PAGE,
- Streamer.getContext())),
- STI);
- Streamer.emitInstruction(
+ OutStreamer->getContext())));
+ EmitToStreamer(
MCInstBuilder(AArch64::LDRXui)
.addReg(Reg)
.addReg(Reg)
.addExpr(MCSpecifierExpr::create(SymRef, AArch64::S_GOT_LO12,
- Streamer.getContext())),
- STI);
- if (Val.getConstant())
- Streamer.emitInstruction(MCInstBuilder(AArch64::ADDXri)
- .addReg(Reg)
- .addReg(Reg)
- .addImm(Val.getConstant())
- .addImm(0),
- STI);
+ OutStreamer->getContext())));
+ emitAddImm(Reg, Val.getConstant(), Tmp);
}
}
@@ -2504,14 +2540,14 @@ const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
.addImm(0),
*STI);
} else {
- emitAddress(*OutStreamer, AArch64::X0, Target, IsDSOLocal, *STI);
+ emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
}
if (HasAddressDiversity) {
auto *PlacePlusDisc = MCBinaryExpr::createAdd(
MCSymbolRefExpr::create(Place, OutStreamer->getContext()),
MCConstantExpr::create(Disc, OutStreamer->getContext()),
OutStreamer->getContext());
- emitAddress(*OutStreamer, AArch64::X1, PlacePlusDisc, /*IsDSOLocal=*/true,
+ emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16, /*IsDSOLocal=*/true,
*STI);
} else {
if (!isUInt<16>(Disc)) {
@@ -2801,46 +2837,7 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
.addImm(0));
}
- if (Offset != 0) {
- const uint64_t AbsOffset = (Offset > 0 ? Offset : -((uint64_t)Offset));
- const bool IsNeg = Offset < 0;
- if (isUInt<24>(AbsOffset)) {
- for (int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
- BitPos += 12) {
- EmitToStreamer(
- MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
- .addReg(AArch64::X16)
- .addReg(AArch64::X16)
- .addImm((AbsOffset >> BitPos) & 0xfff)
- .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, BitPos)));
- }
- } else {
- const uint64_t UOffset = Offset;
- EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
- .addReg(AArch64::X17)
- .addImm((IsNeg ? ~UOffset : UOffset) & 0xffff)
- .addImm(/*shift=*/0));
- auto NeedMovk = [IsNeg, UOffset](int BitPos) -> bool {
- assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
- uint64_t Shifted = UOffset >> BitPos;
- if (!IsNeg)
- return Shifted != 0;
- for (int I = 0; I != 64 - BitPos; I += 16)
- if (((Shifted >> I) & 0xffff) != 0xffff)
- return true;
- return false;
- };
- for (int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
- emitMOVK(AArch64::X17, (UOffset >> BitPos) & 0xffff, BitPos);
-
- EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
- .addReg(AArch64::X16)
- .addReg(AArch64::X16)
- .addReg(AArch64::X17)
- .addImm(/*shift=*/0));
- }
- }
-
+ emitAddImm(AArch64::X16, Offset, AArch64::X17);
Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
auto MIB = MCInstBuilder(getPACOpcodeForKey(Key, DiscReg == AArch64::XZR))
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll b/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
index c366459a3637d..1a367bf0d6046 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
@@ -107,6 +107,21 @@
; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
@globalref8 = constant ptr ptrauth (ptr getelementptr (i8, ptr @global, i64 8), i32 2, i64 5, ptr null), align 8
+; CHECK: globalref16777216:
+; CHECK-NEXT: [[PLACE:.*]]:
+; CHECK-NEXT: .section .text.startup
+; CHECK-NEXT: [[FUNC:.*]]:
+; CHECK-NEXT: adrp x0, :got:global
+; CHECK-NEXT: ldr x0, [x0, :got_lo12:global]
+; CHECK-NEXT: mov x16, #0
+; CHECK-NEXT: movk x16, #256, lsl #16
+; CHECK-NEXT: add x0, x0, x16
+; CHECK-NEXT: mov x1, #5
+; CHECK-NEXT: b __emupac_pacda
+; CHECK-NEXT: .section .rodata
+; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
+ at globalref16777216 = constant ptr ptrauth (ptr getelementptr (i8, ptr @global, i64 16777216), i32 2, i64 5, ptr null), align 8
+
$comdat = comdat any
@comdat = constant ptr ptrauth (ptr null, i32 2, i64 1, ptr null), align 8, comdat
; CHECK: comdat:
More information about the llvm-commits
mailing list