Skip to content

Commit 00e4a41

Browse files
authored
[ARM] R11 not pushed adjacent to link register with PAC-M and AAPCS frame chain fix (#82801)
When code for M class architecture was compiled with AAPCS and PAC enabled, the frame pointer, r11, was not pushed to the stack adjacent to the link register. Due to PAC being enabled, r12 was placed between r11 and lr. This patch fixes this by adding an extra case to the already existing code that splits the GPR push in two when R11 is the frame pointer and certain paremeters are met. The differential revision for this previous change can be found here: https://reviews.llvm.org/D125649. This now ensures that r11 and lr are pushed in a separate push instruction to the other GPRs when PAC and AAPCS are enabled, meaning the frame pointer and link register are now pushed onto the stack adjacent to each other.
1 parent 8f30b62 commit 00e4a41

File tree

6 files changed

+297
-93
lines changed

6 files changed

+297
-93
lines changed

llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,16 @@ ARMBaseRegisterInfo::ARMBaseRegisterInfo()
6262
const MCPhysReg*
6363
ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
6464
const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
65-
bool UseSplitPush = STI.splitFramePushPop(*MF);
65+
bool UseSplitPush = (STI.getPushPopSplitVariation(*MF) ==
66+
ARMSubtarget::PushPopSplitVariation::R7Split);
6667
const Function &F = MF->getFunction();
6768

6869
if (F.getCallingConv() == CallingConv::GHC) {
6970
// GHC set of callee saved regs is empty as all those regs are
7071
// used for passing STG regs around
7172
return CSR_NoRegs_SaveList;
72-
} else if (STI.splitFramePointerPush(*MF)) {
73+
} else if (STI.getPushPopSplitVariation(*MF) ==
74+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) {
7375
return CSR_Win_SplitFP_SaveList;
7476
} else if (F.getCallingConv() == CallingConv::CFGuard_Check) {
7577
return CSR_Win_AAPCS_CFGuard_Check_SaveList;

llvm/lib/Target/ARM/ARMFrameLowering.cpp

Lines changed: 155 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -718,9 +718,14 @@ static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI,
718718
// This is a conservative estimation: Assume the frame pointer being r7 and
719719
// pc("r15") up to r8 getting spilled before (= 8 registers).
720720
int MaxRegBytes = 8 * 4;
721-
if (STI.splitFramePointerPush(MF)) {
721+
if (STI.getPushPopSplitVariation(MF) ==
722+
ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning)
722723
// Here, r11 can be stored below all of r4-r15 (3 registers more than
723-
// above), plus d8-d15.
724+
// above).
725+
MaxRegBytes = 11 * 4;
726+
if (STI.getPushPopSplitVariation(MF) ==
727+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) {
728+
// Here, r11 can be stored below all of r4-r15 plus d8-d15.
724729
MaxRegBytes = 11 * 4 + 8 * 8;
725730
}
726731
int FPCXTSaveSize =
@@ -788,7 +793,10 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
788793
}
789794

790795
// Determine spill area sizes.
791-
if (STI.splitFramePointerPush(MF)) {
796+
if (STI.getPushPopSplitVariation(MF) ==
797+
ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning ||
798+
STI.getPushPopSplitVariation(MF) ==
799+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) {
792800
for (const CalleeSavedInfo &I : CSI) {
793801
Register Reg = I.getReg();
794802
int FI = I.getFrameIdx();
@@ -834,7 +842,8 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
834842
case ARM::R10:
835843
case ARM::R11:
836844
case ARM::R12:
837-
if (STI.splitFramePushPop(MF)) {
845+
if (STI.getPushPopSplitVariation(MF) ==
846+
ARMSubtarget::PushPopSplitVariation::R7Split) {
838847
GPRCS2Size += 4;
839848
break;
840849
}
@@ -897,13 +906,15 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
897906
unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
898907
Align DPRAlign = DPRCSSize ? std::min(Align(8), Alignment) : Align(4);
899908
unsigned DPRGapSize = GPRCS1Size + FPCXTSaveSize + ArgRegsSaveSize;
900-
if (!STI.splitFramePointerPush(MF)) {
909+
if (STI.getPushPopSplitVariation(MF) !=
910+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) {
901911
DPRGapSize += GPRCS2Size;
902912
}
903913
DPRGapSize %= DPRAlign.value();
904914

905915
unsigned DPRCSOffset;
906-
if (STI.splitFramePointerPush(MF)) {
916+
if (STI.getPushPopSplitVariation(MF) ==
917+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) {
907918
DPRCSOffset = GPRCS1Offset - DPRGapSize - DPRCSSize;
908919
GPRCS2Offset = DPRCSOffset - GPRCS2Size;
909920
} else {
@@ -922,8 +933,10 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
922933
AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset);
923934
AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
924935

925-
// Move past area 2.
926-
if (GPRCS2Size > 0 && !STI.splitFramePointerPush(MF)) {
936+
// Move past area 2, unless following the CSR_Win_SplitFP calling convention.
937+
if (GPRCS2Size > 0 &&
938+
STI.getPushPopSplitVariation(MF) !=
939+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) {
927940
GPRCS2Push = LastPush = MBBI++;
928941
DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
929942
}
@@ -963,13 +976,18 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
963976
} else
964977
NumBytes = DPRCSOffset;
965978

966-
if (GPRCS2Size > 0 && STI.splitFramePointerPush(MF)) {
979+
// Move past area 2 if following the CSR_Win_SplitFP calling convention.
980+
if (GPRCS2Size > 0 &&
981+
STI.getPushPopSplitVariation(MF) ==
982+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) {
967983
GPRCS2Push = LastPush = MBBI++;
968984
DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
969985
}
970986

971987
bool NeedsWinCFIStackAlloc = NeedsWinCFI;
972-
if (STI.splitFramePointerPush(MF) && HasFP)
988+
if (STI.getPushPopSplitVariation(MF) ==
989+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind &&
990+
HasFP)
973991
NeedsWinCFIStackAlloc = false;
974992

975993
if (STI.isTargetWindows() && WindowsRequiresStackProbe(MF, NumBytes)) {
@@ -1074,7 +1092,10 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
10741092
AfterPush = std::next(GPRCS1Push);
10751093
unsigned PushSize = sizeOfSPAdjustment(*GPRCS1Push);
10761094
int FPOffset = PushSize + FramePtrOffsetInPush;
1077-
if (STI.splitFramePointerPush(MF)) {
1095+
if (STI.getPushPopSplitVariation(MF) ==
1096+
ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning ||
1097+
STI.getPushPopSplitVariation(MF) ==
1098+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) {
10781099
AfterPush = std::next(GPRCS2Push);
10791100
emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, dl, TII,
10801101
FramePtr, ARM::SP, 0, MachineInstr::FrameSetup);
@@ -1106,7 +1127,9 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
11061127
// instructions below don't need to be replayed to unwind the stack.
11071128
if (NeedsWinCFI && MBBI != MBB.begin()) {
11081129
MachineBasicBlock::iterator End = MBBI;
1109-
if (HasFP && STI.splitFramePointerPush(MF))
1130+
if (HasFP &&
1131+
STI.getPushPopSplitVariation(MF) ==
1132+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind)
11101133
End = AfterPush;
11111134
insertSEHRange(MBB, {}, End, TII, MachineInstr::FrameSetup);
11121135
BuildMI(MBB, End, dl, TII.get(ARM::SEH_PrologEnd))
@@ -1118,51 +1141,103 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
11181141
// the necessary DWARF cf instructions to describe the situation. Start by
11191142
// recording where each register ended up:
11201143
if (GPRCS1Size > 0 && !NeedsWinCFI) {
1121-
MachineBasicBlock::iterator Pos = std::next(GPRCS1Push);
1122-
int CFIIndex;
1123-
for (const auto &Entry : CSI) {
1124-
Register Reg = Entry.getReg();
1125-
int FI = Entry.getFrameIdx();
1126-
switch (Reg) {
1127-
case ARM::R8:
1128-
case ARM::R9:
1129-
case ARM::R10:
1130-
case ARM::R11:
1131-
case ARM::R12:
1132-
if (STI.splitFramePushPop(MF))
1144+
if (STI.getPushPopSplitVariation(MF) ==
1145+
ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning) {
1146+
MachineBasicBlock::iterator Pos = std::next(GPRCS1Push);
1147+
int CFIIndex;
1148+
for (const auto &Entry : CSI) {
1149+
Register Reg = Entry.getReg();
1150+
int FI = Entry.getFrameIdx();
1151+
switch (Reg) {
1152+
case ARM::R0:
1153+
case ARM::R1:
1154+
case ARM::R2:
1155+
case ARM::R3:
1156+
case ARM::R4:
1157+
case ARM::R5:
1158+
case ARM::R6:
1159+
case ARM::R7:
1160+
case ARM::R8:
1161+
case ARM::R9:
1162+
case ARM::R10:
1163+
case ARM::R12:
1164+
CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
1165+
nullptr, MRI->getDwarfRegNum(Reg, true),
1166+
MFI.getObjectOffset(FI)));
1167+
BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
1168+
.addCFIIndex(CFIIndex)
1169+
.setMIFlags(MachineInstr::FrameSetup);
11331170
break;
1134-
[[fallthrough]];
1135-
case ARM::R0:
1136-
case ARM::R1:
1137-
case ARM::R2:
1138-
case ARM::R3:
1139-
case ARM::R4:
1140-
case ARM::R5:
1141-
case ARM::R6:
1142-
case ARM::R7:
1143-
case ARM::LR:
1144-
CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
1145-
nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI)));
1146-
BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
1147-
.addCFIIndex(CFIIndex)
1148-
.setMIFlags(MachineInstr::FrameSetup);
1149-
break;
1171+
}
1172+
}
1173+
} else {
1174+
MachineBasicBlock::iterator Pos = std::next(GPRCS1Push);
1175+
int CFIIndex;
1176+
for (const auto &Entry : CSI) {
1177+
Register Reg = Entry.getReg();
1178+
int FI = Entry.getFrameIdx();
1179+
switch (Reg) {
1180+
case ARM::R8:
1181+
case ARM::R9:
1182+
case ARM::R10:
1183+
case ARM::R11:
1184+
case ARM::R12:
1185+
if (STI.getPushPopSplitVariation(MF) ==
1186+
ARMSubtarget::PushPopSplitVariation::R7Split)
1187+
break;
1188+
[[fallthrough]];
1189+
case ARM::R0:
1190+
case ARM::R1:
1191+
case ARM::R2:
1192+
case ARM::R3:
1193+
case ARM::R4:
1194+
case ARM::R5:
1195+
case ARM::R6:
1196+
case ARM::R7:
1197+
case ARM::LR:
1198+
CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
1199+
nullptr, MRI->getDwarfRegNum(Reg, true),
1200+
MFI.getObjectOffset(FI)));
1201+
BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
1202+
.addCFIIndex(CFIIndex)
1203+
.setMIFlags(MachineInstr::FrameSetup);
1204+
break;
1205+
}
11501206
}
11511207
}
11521208
}
11531209

11541210
if (GPRCS2Size > 0 && !NeedsWinCFI) {
11551211
MachineBasicBlock::iterator Pos = std::next(GPRCS2Push);
1156-
for (const auto &Entry : CSI) {
1157-
Register Reg = Entry.getReg();
1158-
int FI = Entry.getFrameIdx();
1159-
switch (Reg) {
1160-
case ARM::R8:
1161-
case ARM::R9:
1162-
case ARM::R10:
1163-
case ARM::R11:
1164-
case ARM::R12:
1165-
if (STI.splitFramePushPop(MF)) {
1212+
if (STI.getPushPopSplitVariation(MF) ==
1213+
ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning) {
1214+
for (const auto &Entry : CSI) {
1215+
Register Reg = Entry.getReg();
1216+
int FI = Entry.getFrameIdx();
1217+
switch (Reg) {
1218+
case ARM::R11:
1219+
case ARM::LR:
1220+
unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
1221+
unsigned Offset = MFI.getObjectOffset(FI);
1222+
unsigned CFIIndex = MF.addFrameInst(
1223+
MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
1224+
BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
1225+
.addCFIIndex(CFIIndex)
1226+
.setMIFlags(MachineInstr::FrameSetup);
1227+
break;
1228+
}
1229+
}
1230+
} else {
1231+
MachineBasicBlock::iterator Pos = std::next(GPRCS2Push);
1232+
for (const auto &Entry : CSI) {
1233+
Register Reg = Entry.getReg();
1234+
int FI = Entry.getFrameIdx();
1235+
switch (Reg) {
1236+
case ARM::R8:
1237+
case ARM::R9:
1238+
case ARM::R10:
1239+
case ARM::R11:
1240+
case ARM::R12:
11661241
unsigned DwarfReg = MRI->getDwarfRegNum(
11671242
Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg, true);
11681243
unsigned Offset = MFI.getObjectOffset(FI);
@@ -1171,8 +1246,8 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
11711246
BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
11721247
.addCFIIndex(CFIIndex)
11731248
.setMIFlags(MachineInstr::FrameSetup);
1249+
break;
11741250
}
1175-
break;
11761251
}
11771252
}
11781253
}
@@ -1382,7 +1457,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
13821457
MachineInstr::FrameDestroy);
13831458

13841459
// Increment past our save areas.
1385-
if (AFI->getGPRCalleeSavedArea2Size() && STI.splitFramePointerPush(MF))
1460+
if (AFI->getGPRCalleeSavedArea2Size() &&
1461+
STI.getPushPopSplitVariation(MF) ==
1462+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind)
13861463
MBBI++;
13871464

13881465
if (MBBI != MBB.end() && AFI->getDPRCalleeSavedAreaSize()) {
@@ -1399,7 +1476,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
13991476
MachineInstr::FrameDestroy);
14001477
}
14011478

1402-
if (AFI->getGPRCalleeSavedArea2Size() && !STI.splitFramePointerPush(MF))
1479+
if (AFI->getGPRCalleeSavedArea2Size() &&
1480+
STI.getPushPopSplitVariation(MF) !=
1481+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind)
14031482
MBBI++;
14041483
if (AFI->getGPRCalleeSavedArea1Size()) MBBI++;
14051484

@@ -1539,7 +1618,9 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB,
15391618
unsigned LastReg = 0;
15401619
for (; i != 0; --i) {
15411620
Register Reg = CSI[i-1].getReg();
1542-
if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue;
1621+
if (!(Func)(Reg, STI.getPushPopSplitVariation(MF) ==
1622+
ARMSubtarget::PushPopSplitVariation::R7Split))
1623+
continue;
15431624

15441625
// D-registers in the aligned area DPRCS2 are NOT spilled here.
15451626
if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
@@ -1632,15 +1713,21 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
16321713
for (; i != 0; --i) {
16331714
CalleeSavedInfo &Info = CSI[i-1];
16341715
Register Reg = Info.getReg();
1635-
if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue;
1716+
if (!(Func)(Reg, STI.getPushPopSplitVariation(MF) ==
1717+
ARMSubtarget::PushPopSplitVariation::R7Split))
1718+
continue;
16361719

16371720
// The aligned reloads from area DPRCS2 are not inserted here.
16381721
if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
16391722
continue;
16401723
if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
16411724
!isCmseEntry && !isTrap && AFI->getArgumentStackToRestore() == 0 &&
16421725
STI.hasV5TOps() && MBB.succ_empty() && !hasPAC &&
1643-
!STI.splitFramePointerPush(MF)) {
1726+
(STI.getPushPopSplitVariation(MF) !=
1727+
ARMSubtarget::PushPopSplitVariation::
1728+
R11SplitAAPCSBranchSigning &&
1729+
STI.getPushPopSplitVariation(MF) !=
1730+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind)) {
16441731
Reg = ARM::PC;
16451732
// Fold the return instruction into the LDM.
16461733
DeleteRet = true;
@@ -2001,7 +2088,10 @@ bool ARMFrameLowering::spillCalleeSavedRegisters(
20012088
.addImm(-4)
20022089
.add(predOps(ARMCC::AL));
20032090
}
2004-
if (STI.splitFramePointerPush(MF)) {
2091+
if (STI.getPushPopSplitVariation(MF) ==
2092+
ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning ||
2093+
STI.getPushPopSplitVariation(MF) ==
2094+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) {
20052095
emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false,
20062096
&isSplitFPArea1Register, 0, MachineInstr::FrameSetup);
20072097
emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register,
@@ -2046,7 +2136,10 @@ bool ARMFrameLowering::restoreCalleeSavedRegisters(
20462136
unsigned LdrOpc =
20472137
AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
20482138
unsigned FltOpc = ARM::VLDMDIA_UPD;
2049-
if (STI.splitFramePointerPush(MF)) {
2139+
if (STI.getPushPopSplitVariation(MF) ==
2140+
ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning ||
2141+
STI.getPushPopSplitVariation(MF) ==
2142+
ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) {
20502143
emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false,
20512144
&isSplitFPArea2Register, 0);
20522145
emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register,
@@ -2362,7 +2455,8 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
23622455
if (Spilled) {
23632456
NumGPRSpills++;
23642457

2365-
if (!STI.splitFramePushPop(MF)) {
2458+
if (STI.getPushPopSplitVariation(MF) !=
2459+
ARMSubtarget::PushPopSplitVariation::R7Split) {
23662460
if (Reg == ARM::LR)
23672461
LRSpilled = true;
23682462
CS1Spilled = true;
@@ -2384,7 +2478,8 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
23842478
break;
23852479
}
23862480
} else {
2387-
if (!STI.splitFramePushPop(MF)) {
2481+
if (STI.getPushPopSplitVariation(MF) !=
2482+
ARMSubtarget::PushPopSplitVariation::R7Split) {
23882483
UnspilledCS1GPRs.push_back(Reg);
23892484
continue;
23902485
}

0 commit comments

Comments
 (0)