Skip to content

Commit a094df4

Browse files
committed
[aarch64][PAC] Move MachO (pro|epi)logue PAC to generic AArch64PointerAuth infra
This is _almost_ NFCI, though there are some small changes I expect re: adding cfi's that we were missing before. rdar://163365479
1 parent c9601a3 commit a094df4

File tree

9 files changed

+88
-109
lines changed

9 files changed

+88
-109
lines changed

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,8 @@ bool AArch64FrameLowering::shouldSignReturnAddressEverywhere(
984984
if (MF.getTarget().getMCAsmInfo()->usesWindowsCFI())
985985
return false;
986986
const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
987-
bool SignReturnAddressAll = AFI->shouldSignReturnAddress(/*SpillsLR=*/false);
987+
bool SignReturnAddressAll =
988+
AFI->shouldSignReturnAddress(MF, /*SpillsLR=*/false);
988989
return SignReturnAddressAll;
989990
}
990991

llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9547,8 +9547,10 @@ outliningCandidatesSigningScopeConsensus(const outliner::Candidate &a,
95479547
const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
95489548
const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
95499549

9550-
return MFIa->shouldSignReturnAddress(false) == MFIb->shouldSignReturnAddress(false) &&
9551-
MFIa->shouldSignReturnAddress(true) == MFIb->shouldSignReturnAddress(true);
9550+
return MFIa->shouldSignReturnAddress(*a.getMF(), false) ==
9551+
MFIb->shouldSignReturnAddress(*b.getMF(), false) &&
9552+
MFIa->shouldSignReturnAddress(*a.getMF(), true) ==
9553+
MFIb->shouldSignReturnAddress(*b.getMF(), true);
95529554
}
95539555

95549556
static bool
@@ -9618,10 +9620,8 @@ AArch64InstrInfo::getOutliningCandidateInfo(
96189620
// Performing a tail call may require extra checks when PAuth is enabled.
96199621
// If PAuth is disabled, set it to zero for uniformity.
96209622
unsigned NumBytesToCheckLRInTCEpilogue = 0;
9621-
if (RepeatedSequenceLocs[0]
9622-
.getMF()
9623-
->getInfo<AArch64FunctionInfo>()
9624-
->shouldSignReturnAddress(true)) {
9623+
const MachineFunction &MF = *RepeatedSequenceLocs[0].getMF();
9624+
if (MF.getInfo<AArch64FunctionInfo>()->shouldSignReturnAddress(MF, true)) {
96259625
// One PAC and one AUT instructions
96269626
NumBytesToCreateFrame += 8;
96279627

@@ -10425,7 +10425,7 @@ void AArch64InstrInfo::buildOutlinedFrame(
1042510425
Et = MBB.insert(Et, LDRXpost);
1042610426
}
1042710427

10428-
bool ShouldSignReturnAddr = FI->shouldSignReturnAddress(!IsLeafFunction);
10428+
bool ShouldSignReturnAddr = FI->shouldSignReturnAddress(MF, !IsLeafFunction);
1042910429

1043010430
// If this is a tail call outlined function, then there's already a return.
1043110431
if (OF.FrameConstructionID == MachineOutlinerTailCall ||

llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ static std::pair<bool, bool> GetSignReturnAddress(const Function &F,
8686
}
8787

8888
static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) {
89-
if (!STI.getTargetTriple().isOSBinFormatMachO() &&
90-
F.hasFnAttribute("ptrauth-returns"))
89+
if (F.hasFnAttribute("ptrauth-returns"))
9190
return true;
9291
if (!F.hasFnAttribute("sign-return-address-key")) {
9392
if (STI.getTargetTriple().isOSWindows())
@@ -173,7 +172,18 @@ MachineFunctionInfo *AArch64FunctionInfo::clone(
173172
return DestMF.cloneInfo<AArch64FunctionInfo>(*this);
174173
}
175174

176-
bool AArch64FunctionInfo::shouldSignReturnAddress(bool SpillsLR) const {
175+
static bool shouldAuthenticateLR(const MachineFunction &MF) {
176+
// Return address authentication can be enabled at the function level, using
177+
// the "ptrauth-returns" attribute.
178+
const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
179+
return Subtarget.isTargetMachO() &&
180+
MF.getFunction().hasFnAttribute("ptrauth-returns");
181+
}
182+
183+
bool AArch64FunctionInfo::shouldSignReturnAddress(const MachineFunction &MF,
184+
bool SpillsLR) const {
185+
if (SpillsLR && shouldAuthenticateLR(MF))
186+
return true;
177187
if (!SignReturnAddress)
178188
return false;
179189
if (SignReturnAddressAll)
@@ -189,7 +199,7 @@ static bool isLRSpilled(const MachineFunction &MF) {
189199

190200
bool AArch64FunctionInfo::shouldSignReturnAddress(
191201
const MachineFunction &MF) const {
192-
return shouldSignReturnAddress(isLRSpilled(MF));
202+
return shouldSignReturnAddress(MF, isLRSpilled(MF));
193203
}
194204

195205
bool AArch64FunctionInfo::needsShadowCallStackPrologueEpilogue(

llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
596596
}
597597

598598
bool shouldSignReturnAddress(const MachineFunction &MF) const;
599-
bool shouldSignReturnAddress(bool SpillsLR) const;
599+
bool shouldSignReturnAddress(const MachineFunction &MF, bool SpillsLR) const;
600600

601601
bool needsShadowCallStackPrologueEpilogue(MachineFunction &MF) const;
602602

llvm/lib/Target/AArch64/AArch64PointerAuth.cpp

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
#include "AArch64Subtarget.h"
1515
#include "llvm/CodeGen/CFIInstBuilder.h"
1616
#include "llvm/CodeGen/MachineBasicBlock.h"
17+
#include "llvm/CodeGen/MachineFrameInfo.h"
1718
#include "llvm/CodeGen/MachineInstrBuilder.h"
1819
#include "llvm/CodeGen/MachineModuleInfo.h"
20+
#include "llvm/IR/CallingConv.h"
1921

2022
using namespace llvm;
2123
using namespace llvm::AArch64PAuth;
@@ -133,17 +135,15 @@ void AArch64PointerAuth::signLR(MachineFunction &MF,
133135
if (MFnI.branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) {
134136
emitPACCFI(MBB, MBBI, MachineInstr::FrameSetup, EmitCFI);
135137
BuildMI(MBB, MBBI, DL,
136-
TII->get(MFnI.shouldSignWithBKey() ? AArch64::PACIBSPPC
137-
: AArch64::PACIASPPC))
138+
TII->get(UseBKey ? AArch64::PACIBSPPC : AArch64::PACIASPPC))
138139
.setMIFlag(MachineInstr::FrameSetup)
139140
->setPreInstrSymbol(MF, MFnI.getSigningInstrLabel());
140141
} else {
141142
BuildPACM(*Subtarget, MBB, MBBI, DL, MachineInstr::FrameSetup);
142143
if (MFnI.branchProtectionPAuthLR())
143144
emitPACCFI(MBB, MBBI, MachineInstr::FrameSetup, EmitCFI);
144145
BuildMI(MBB, MBBI, DL,
145-
TII->get(MFnI.shouldSignWithBKey() ? AArch64::PACIBSP
146-
: AArch64::PACIASP))
146+
TII->get(UseBKey ? AArch64::PACIBSP : AArch64::PACIASP))
147147
.setMIFlag(MachineInstr::FrameSetup)
148148
->setPreInstrSymbol(MF, MFnI.getSigningInstrLabel());
149149
if (!MFnI.branchProtectionPAuthLR())
@@ -181,6 +181,17 @@ void AArch64PointerAuth::authenticateLR(
181181
TI != MBB.end() && TI->getOpcode() == AArch64::RET;
182182
MCSymbol *PACSym = MFnI->getSigningInstrLabel();
183183

184+
const MachineFrameInfo &MFI = MF.getFrameInfo();
185+
bool IsLRSpilled =
186+
llvm::any_of(MFI.getCalleeSavedInfo(), [](const CalleeSavedInfo &Info) {
187+
return Info.getReg() == AArch64::LR;
188+
});
189+
190+
// FIXME: do we need to look for the AArch64::RET_POPLESS at the end of the
191+
// epilogue?
192+
bool IsSwiftCoroPartialReturn =
193+
MF.getFunction().getCallingConv() == CallingConv::SwiftCoro;
194+
184195
if (Subtarget->hasPAuth() && TerminatorIsCombinable && !NeedsWinCFI &&
185196
!MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)) {
186197
if (MFnI->branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) {
@@ -198,6 +209,29 @@ void AArch64PointerAuth::authenticateLR(
198209
.setMIFlag(MachineInstr::FrameDestroy);
199210
}
200211
MBB.erase(TI);
212+
} else if (IsLRSpilled && IsSwiftCoroPartialReturn) {
213+
const auto *TRI = Subtarget->getRegisterInfo();
214+
215+
MachineBasicBlock::iterator EpilogStartI = MBB.getFirstTerminator();
216+
MachineBasicBlock::iterator Begin = MBB.begin();
217+
while (EpilogStartI != Begin) {
218+
--EpilogStartI;
219+
if (!EpilogStartI->getFlag(MachineInstr::FrameDestroy)) {
220+
++EpilogStartI;
221+
break;
222+
}
223+
if (EpilogStartI->readsRegister(AArch64::X16, TRI) ||
224+
EpilogStartI->modifiesRegister(AArch64::X16, TRI))
225+
report_fatal_error("unable to use x16 for popless ret LR auth");
226+
}
227+
228+
emitFrameOffset(MBB, EpilogStartI, DL, AArch64::X16, AArch64::FP,
229+
StackOffset::getFixed(16), TII, MachineInstr::FrameDestroy);
230+
emitPACCFI(MBB, MBBI, MachineInstr::FrameDestroy, EmitAsyncCFI);
231+
BuildMI(MBB, TI, DL, TII->get(AArch64::AUTIB), AArch64::LR)
232+
.addUse(AArch64::LR)
233+
.addUse(AArch64::X16)
234+
.setMIFlag(MachineInstr::FrameDestroy);
201235
} else {
202236
if (MFnI->branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) {
203237
assert(PACSym && "No PAC instruction to refer to");

llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -520,14 +520,6 @@ void AArch64PrologueEmitter::verifyPrologueClobbers() const {
520520
}
521521
#endif
522522

523-
static bool shouldAuthenticateLR(const MachineFunction &MF) {
524-
// Return address authentication can be enabled at the function level, using
525-
// the "ptrauth-returns" attribute.
526-
const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
527-
return Subtarget.isTargetMachO() &&
528-
MF.getFunction().hasFnAttribute("ptrauth-returns");
529-
}
530-
531523
void AArch64PrologueEmitter::determineLocalsStackSize(
532524
uint64_t StackSize, uint64_t PrologueSaveSize) {
533525
AFI->setLocalStackSize(StackSize - PrologueSaveSize);
@@ -709,18 +701,6 @@ void AArch64PrologueEmitter::emitPrologue() {
709701
BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::EMITMTETAGGED))
710702
.setMIFlag(MachineInstr::FrameSetup);
711703

712-
// If we're saving LR, sign it first.
713-
if (shouldAuthenticateLR(MF)) {
714-
if (LLVM_UNLIKELY(!Subtarget.hasPAuth()))
715-
report_fatal_error("arm64e LR authentication requires ptrauth");
716-
for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) {
717-
if (Info.getReg() != AArch64::LR)
718-
continue;
719-
BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::PACIBSP))
720-
.setMIFlags(MachineInstr::FrameSetup);
721-
}
722-
}
723-
724704
// We signal the presence of a Swift extended frame to external tools by
725705
// storing FP with 0b0001 in bits 63:60. In normal userland operation a simple
726706
// ORR is sufficient, it is assumed a Swift kernel would initialize the TBI
@@ -1407,66 +1387,6 @@ void AArch64EpilogueEmitter::emitEpilogue() {
14071387
if (MF.getFunction().getCallingConv() == CallingConv::GHC)
14081388
return;
14091389

1410-
// If we're restoring LR, authenticate it before returning.
1411-
// Use scope_exit to ensure we do that last on all return paths.
1412-
auto InsertAuthLROnExit = make_scope_exit([&]() {
1413-
if (shouldAuthenticateLR(MF)) {
1414-
if (LLVM_UNLIKELY(!Subtarget.hasPAuth()))
1415-
report_fatal_error("arm64e LR authentication requires ptrauth");
1416-
for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) {
1417-
if (Info.getReg() != AArch64::LR)
1418-
continue;
1419-
MachineBasicBlock::iterator TI = MBB.getFirstTerminator();
1420-
1421-
// When we're doing a popless ret (i.e., that doesn't restore SP), we
1422-
// can't rely on the exit SP being the same as the entry, but they need
1423-
// to match for the LR auth to succeed. Instead, derive the entry SP
1424-
// from our FP (using a -16 static offset for the size of the frame
1425-
// record itself), save that into X16, and use that as the discriminator
1426-
// in an AUTIB.
1427-
if (IsSwiftCoroPartialReturn) {
1428-
const auto *TRI = Subtarget.getRegisterInfo();
1429-
1430-
MachineBasicBlock::iterator EpilogStartI = MBB.getFirstTerminator();
1431-
MachineBasicBlock::iterator Begin = MBB.begin();
1432-
while (EpilogStartI != Begin) {
1433-
--EpilogStartI;
1434-
if (!EpilogStartI->getFlag(MachineInstr::FrameDestroy)) {
1435-
++EpilogStartI;
1436-
break;
1437-
}
1438-
if (EpilogStartI->readsRegister(AArch64::X16, TRI) ||
1439-
EpilogStartI->modifiesRegister(AArch64::X16, TRI))
1440-
report_fatal_error("unable to use x16 for popless ret LR auth");
1441-
}
1442-
1443-
emitFrameOffset(MBB, EpilogStartI, DL, AArch64::X16, AArch64::FP,
1444-
StackOffset::getFixed(16), TII,
1445-
MachineInstr::FrameDestroy);
1446-
BuildMI(MBB, TI, DL, TII->get(AArch64::AUTIB), AArch64::LR)
1447-
.addUse(AArch64::LR)
1448-
.addUse(AArch64::X16)
1449-
.setMIFlag(MachineInstr::FrameDestroy);
1450-
return;
1451-
}
1452-
1453-
if (TI != MBB.end() && TI->getOpcode() == AArch64::RET_ReallyLR) {
1454-
// If there is a terminator and it's a RET, we can fold AUTH into it.
1455-
// Be careful to keep the implicitly returned registers.
1456-
// By now, we don't need the ReallyLR pseudo, since it's only there
1457-
// to make it possible for LR to be used for non-RET purposes, and
1458-
// that happens in RA and PEI.
1459-
BuildMI(MBB, TI, DL, TII->get(AArch64::RETAB)).copyImplicitOps(*TI);
1460-
MBB.erase(TI);
1461-
} else {
1462-
// Otherwise, we could be in a shrink-wrapped or tail-calling block.
1463-
BuildMI(MBB, TI, DL, TII->get(AArch64::AUTIBSP));
1464-
}
1465-
}
1466-
}
1467-
});
1468-
1469-
14701390
// How much of the stack used by incoming arguments this function is expected
14711391
// to restore in this particular epilogue.
14721392
int64_t ArgumentStackToRestore = AFL.getArgumentStackToRestore(MF, MBB);

llvm/test/CodeGen/AArch64/ptrauth-invoke-wrapper-globals.ll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
; CHECK-NEXT: .cfi_personality 155, ___gxx_personality_v0
88
; CHECK-NEXT: .cfi_lsda 16, [[EXCEPT:Lexception[0-9]+]]
99
; CHECK-NEXT: ; %bb.0:
10+
; CHECK-NEXT: .cfi_b_key_frame
1011
; CHECK-NEXT: pacibsp
12+
; CHECK-NEXT: .cfi_negate_ra_state
1113
; CHECK-NEXT: stp x20, x19, [sp, #-32]!
1214
; CHECK-NEXT: stp x29, x30, [sp, #16]
1315
; CHECK-NEXT: .cfi_def_cfa_offset 32
@@ -57,7 +59,9 @@ continuebb:
5759
; CHECK-NEXT: .cfi_personality 155, ___gxx_personality_v0
5860
; CHECK-NEXT: .cfi_lsda 16, [[EXCEPT:Lexception[0-9]+]]
5961
; CHECK-NEXT: ; %bb.0:
62+
; CHECK-NEXT: .cfi_b_key_frame
6063
; CHECK-NEXT: pacibsp
64+
; CHECK-NEXT: .cfi_negate_ra_state
6165
; CHECK-NEXT: stp x20, x19, [sp, #-32]!
6266
; CHECK-NEXT: stp x29, x30, [sp, #16]
6367
; CHECK-NEXT: .cfi_def_cfa_offset 32
@@ -112,7 +116,9 @@ continuebb:
112116
; CHECK-NEXT: .cfi_personality 155, ___gxx_personality_v0
113117
; CHECK-NEXT: .cfi_lsda 16, [[EXCEPT:Lexception[0-9]+]]
114118
; CHECK-NEXT: ; %bb.0:
119+
; CHECK-NEXT: .cfi_b_key_frame
115120
; CHECK-NEXT: pacibsp
121+
; CHECK-NEXT: .cfi_negate_ra_state
116122
; CHECK-NEXT: stp x20, x19, [sp, #-32]!
117123
; CHECK-NEXT: stp x29, x30, [sp, #16]
118124
; CHECK-NEXT: .cfi_def_cfa_offset 32

llvm/test/CodeGen/AArch64/swiftcorocc-call.ll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ declare i64 @g(ptr, ptr)
1010
define i64 @test_call_to_swiftcoro() #0 {
1111
; CHECK-LABEL: test_call_to_swiftcoro:
1212
; CHECK: ; %bb.0:
13+
; CHECK-NEXT: .cfi_b_key_frame
1314
; CHECK-NEXT: pacibsp
15+
; CHECK-NEXT: .cfi_negate_ra_state
1416
; CHECK-NEXT: stp x26, x25, [sp, #-32]! ; 16-byte Folded Spill
1517
; CHECK-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill
1618
; CHECK-NEXT: add x29, sp, #16
@@ -41,7 +43,9 @@ define i64 @test_call_to_swiftcoro() #0 {
4143
define i64 @test_call_to_normal() #0 {
4244
; CHECK-LABEL: test_call_to_normal:
4345
; CHECK: ; %bb.0:
46+
; CHECK-NEXT: .cfi_b_key_frame
4447
; CHECK-NEXT: pacibsp
48+
; CHECK-NEXT: .cfi_negate_ra_state
4549
; CHECK-NEXT: sub sp, sp, #48
4650
; CHECK-NEXT: stp x26, x25, [sp, #16] ; 16-byte Folded Spill
4751
; CHECK-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill
@@ -71,7 +75,9 @@ define i64 @test_call_to_normal() #0 {
7175
define swiftcorocc i64 @test_call() #0 {
7276
; CHECK-LABEL: test_call:
7377
; CHECK: ; %bb.0:
78+
; CHECK-NEXT: .cfi_b_key_frame
7479
; CHECK-NEXT: pacibsp
80+
; CHECK-NEXT: .cfi_negate_ra_state
7581
; CHECK-NEXT: sub sp, sp, #48
7682
; CHECK-NEXT: stp x26, x25, [sp, #16] ; 16-byte Folded Spill
7783
; CHECK-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill
@@ -99,7 +105,9 @@ define swiftcorocc i64 @test_call() #0 {
99105
define i64 @test_call_normal() #0 {
100106
; CHECK-LABEL: test_call_normal:
101107
; CHECK: ; %bb.0:
108+
; CHECK-NEXT: .cfi_b_key_frame
102109
; CHECK-NEXT: pacibsp
110+
; CHECK-NEXT: .cfi_negate_ra_state
103111
; CHECK-NEXT: sub sp, sp, #48
104112
; CHECK-NEXT: stp x26, x25, [sp, #16] ; 16-byte Folded Spill
105113
; CHECK-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill

0 commit comments

Comments
 (0)