Skip to content

Commit 3e44c51

Browse files
pccgithub-actions[bot]
authored andcommitted
Automerge: 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: llvm/llvm-project#171707
2 parents 81e7524 + 182c61d commit 3e44c51

File tree

2 files changed

+82
-70
lines changed

2 files changed

+82
-70
lines changed

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 67 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ class AArch64AsmPrinter : public AsmPrinter {
219219
// authenticating)
220220
void LowerLOADgotAUTH(const MachineInstr &MI);
221221

222+
void emitAddImm(MCRegister Val, int64_t Addend, MCRegister Tmp);
223+
void emitAddress(MCRegister Reg, const MCExpr *Expr, MCRegister Tmp,
224+
bool DSOLocal, const MCSubtargetInfo &STI);
225+
222226
const MCExpr *emitPAuthRelocationAsIRelative(
223227
const MCExpr *Target, uint64_t Disc, AArch64PACKey::ID KeyID,
224228
bool HasAddressDiversity, bool IsDSOLocal, const MCExpr *DSExpr);
@@ -2336,50 +2340,82 @@ void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) {
23362340
EmitToStreamer(*OutStreamer, BRInst);
23372341
}
23382342

2339-
static void emitAddress(MCStreamer &Streamer, MCRegister Reg,
2340-
const MCExpr *Expr, bool DSOLocal,
2341-
const MCSubtargetInfo &STI) {
2343+
void AArch64AsmPrinter::emitAddImm(MCRegister Reg, int64_t Addend,
2344+
MCRegister Tmp) {
2345+
if (Addend != 0) {
2346+
const uint64_t AbsOffset = (Addend > 0 ? Addend : -((uint64_t)Addend));
2347+
const bool IsNeg = Addend < 0;
2348+
if (isUInt<24>(AbsOffset)) {
2349+
for (int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2350+
BitPos += 12) {
2351+
EmitToStreamer(
2352+
MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2353+
.addReg(Reg)
2354+
.addReg(Reg)
2355+
.addImm((AbsOffset >> BitPos) & 0xfff)
2356+
.addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, BitPos)));
2357+
}
2358+
} else {
2359+
const uint64_t UAddend = Addend;
2360+
EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2361+
.addReg(Tmp)
2362+
.addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2363+
.addImm(/*shift=*/0));
2364+
auto NeedMovk = [IsNeg, UAddend](int BitPos) -> bool {
2365+
assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2366+
uint64_t Shifted = UAddend >> BitPos;
2367+
if (!IsNeg)
2368+
return Shifted != 0;
2369+
for (int I = 0; I != 64 - BitPos; I += 16)
2370+
if (((Shifted >> I) & 0xffff) != 0xffff)
2371+
return true;
2372+
return false;
2373+
};
2374+
for (int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2375+
emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2376+
2377+
EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2378+
.addReg(Reg)
2379+
.addReg(Reg)
2380+
.addReg(Tmp)
2381+
.addImm(/*shift=*/0));
2382+
}
2383+
}
2384+
}
2385+
2386+
void AArch64AsmPrinter::emitAddress(MCRegister Reg, const MCExpr *Expr,
2387+
MCRegister Tmp, bool DSOLocal,
2388+
const MCSubtargetInfo &STI) {
23422389
MCValue Val;
23432390
if (!Expr->evaluateAsRelocatable(Val, nullptr))
23442391
report_fatal_error("emitAddress could not evaluate");
23452392
if (DSOLocal) {
2346-
Streamer.emitInstruction(
2393+
EmitToStreamer(
23472394
MCInstBuilder(AArch64::ADRP)
23482395
.addReg(Reg)
23492396
.addExpr(MCSpecifierExpr::create(Expr, AArch64::S_ABS_PAGE,
2350-
Streamer.getContext())),
2351-
STI);
2352-
Streamer.emitInstruction(
2353-
MCInstBuilder(AArch64::ADDXri)
2354-
.addReg(Reg)
2355-
.addReg(Reg)
2356-
.addExpr(MCSpecifierExpr::create(Expr, AArch64::S_LO12,
2357-
Streamer.getContext()))
2358-
.addImm(0),
2359-
STI);
2397+
OutStreamer->getContext())));
2398+
EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2399+
.addReg(Reg)
2400+
.addReg(Reg)
2401+
.addExpr(MCSpecifierExpr::create(
2402+
Expr, AArch64::S_LO12, OutStreamer->getContext()))
2403+
.addImm(0));
23602404
} else {
23612405
auto *SymRef =
2362-
MCSymbolRefExpr::create(Val.getAddSym(), Streamer.getContext());
2363-
Streamer.emitInstruction(
2406+
MCSymbolRefExpr::create(Val.getAddSym(), OutStreamer->getContext());
2407+
EmitToStreamer(
23642408
MCInstBuilder(AArch64::ADRP)
23652409
.addReg(Reg)
23662410
.addExpr(MCSpecifierExpr::create(SymRef, AArch64::S_GOT_PAGE,
2367-
Streamer.getContext())),
2368-
STI);
2369-
Streamer.emitInstruction(
2411+
OutStreamer->getContext())));
2412+
EmitToStreamer(
23702413
MCInstBuilder(AArch64::LDRXui)
23712414
.addReg(Reg)
23722415
.addReg(Reg)
23732416
.addExpr(MCSpecifierExpr::create(SymRef, AArch64::S_GOT_LO12,
2374-
Streamer.getContext())),
2375-
STI);
2376-
if (Val.getConstant())
2377-
Streamer.emitInstruction(MCInstBuilder(AArch64::ADDXri)
2378-
.addReg(Reg)
2379-
.addReg(Reg)
2380-
.addImm(Val.getConstant())
2381-
.addImm(0),
2382-
STI);
2417+
OutStreamer->getContext())));
2418+
emitAddImm(Reg, Val.getConstant(), Tmp);
23832419
}
23842420
}
23852421

@@ -2504,14 +2540,14 @@ const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
25042540
.addImm(0),
25052541
*STI);
25062542
} else {
2507-
emitAddress(*OutStreamer, AArch64::X0, Target, IsDSOLocal, *STI);
2543+
emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
25082544
}
25092545
if (HasAddressDiversity) {
25102546
auto *PlacePlusDisc = MCBinaryExpr::createAdd(
25112547
MCSymbolRefExpr::create(Place, OutStreamer->getContext()),
25122548
MCConstantExpr::create(Disc, OutStreamer->getContext()),
25132549
OutStreamer->getContext());
2514-
emitAddress(*OutStreamer, AArch64::X1, PlacePlusDisc, /*IsDSOLocal=*/true,
2550+
emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16, /*IsDSOLocal=*/true,
25152551
*STI);
25162552
} else {
25172553
if (!isUInt<16>(Disc)) {
@@ -2801,46 +2837,7 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
28012837
.addImm(0));
28022838
}
28032839

2804-
if (Offset != 0) {
2805-
const uint64_t AbsOffset = (Offset > 0 ? Offset : -((uint64_t)Offset));
2806-
const bool IsNeg = Offset < 0;
2807-
if (isUInt<24>(AbsOffset)) {
2808-
for (int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2809-
BitPos += 12) {
2810-
EmitToStreamer(
2811-
MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2812-
.addReg(AArch64::X16)
2813-
.addReg(AArch64::X16)
2814-
.addImm((AbsOffset >> BitPos) & 0xfff)
2815-
.addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, BitPos)));
2816-
}
2817-
} else {
2818-
const uint64_t UOffset = Offset;
2819-
EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2820-
.addReg(AArch64::X17)
2821-
.addImm((IsNeg ? ~UOffset : UOffset) & 0xffff)
2822-
.addImm(/*shift=*/0));
2823-
auto NeedMovk = [IsNeg, UOffset](int BitPos) -> bool {
2824-
assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2825-
uint64_t Shifted = UOffset >> BitPos;
2826-
if (!IsNeg)
2827-
return Shifted != 0;
2828-
for (int I = 0; I != 64 - BitPos; I += 16)
2829-
if (((Shifted >> I) & 0xffff) != 0xffff)
2830-
return true;
2831-
return false;
2832-
};
2833-
for (int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2834-
emitMOVK(AArch64::X17, (UOffset >> BitPos) & 0xffff, BitPos);
2835-
2836-
EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2837-
.addReg(AArch64::X16)
2838-
.addReg(AArch64::X16)
2839-
.addReg(AArch64::X17)
2840-
.addImm(/*shift=*/0));
2841-
}
2842-
}
2843-
2840+
emitAddImm(AArch64::X16, Offset, AArch64::X17);
28442841
Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
28452842

28462843
auto MIB = MCInstBuilder(getPACOpcodeForKey(Key, DiscReg == AArch64::XZR))

llvm/test/CodeGen/AArch64/ptrauth-irelative.ll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,21 @@
107107
; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
108108
@globalref8 = constant ptr ptrauth (ptr getelementptr (i8, ptr @global, i64 8), i32 2, i64 5, ptr null), align 8
109109

110+
; CHECK: globalref16777216:
111+
; CHECK-NEXT: [[PLACE:.*]]:
112+
; CHECK-NEXT: .section .text.startup
113+
; CHECK-NEXT: [[FUNC:.*]]:
114+
; CHECK-NEXT: adrp x0, :got:global
115+
; CHECK-NEXT: ldr x0, [x0, :got_lo12:global]
116+
; CHECK-NEXT: mov x16, #0
117+
; CHECK-NEXT: movk x16, #256, lsl #16
118+
; CHECK-NEXT: add x0, x0, x16
119+
; CHECK-NEXT: mov x1, #5
120+
; CHECK-NEXT: b __emupac_pacda
121+
; CHECK-NEXT: .section .rodata
122+
; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
123+
@globalref16777216 = constant ptr ptrauth (ptr getelementptr (i8, ptr @global, i64 16777216), i32 2, i64 5, ptr null), align 8
124+
110125
$comdat = comdat any
111126
@comdat = constant ptr ptrauth (ptr null, i32 2, i64 1, ptr null), align 8, comdat
112127
; CHECK: comdat:

0 commit comments

Comments
 (0)