Skip to content

Commit 18ac017

Browse files
committed
Revert "[ARM] Fix frame chains with M-profile PACBTI (#110285)"
Reverting because this is causing failures with MSan: https://lab.llvm.org/buildbot/#/builders/169/builds/4378 This reverts commit e1f8f84.
1 parent f7f51f2 commit 18ac017

File tree

6 files changed

+57
-281
lines changed

6 files changed

+57
-281
lines changed

llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,9 @@ ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
116116
return CSR_iOS_SaveList;
117117

118118
if (PushPopSplit == ARMSubtarget::SplitR7)
119-
return STI.createAAPCSFrameChain() ? CSR_AAPCS_SplitPush_R7_SaveList
119+
return STI.createAAPCSFrameChain() ? CSR_AAPCS_SplitPush_SaveList
120120
: CSR_ATPCS_SplitPush_SaveList;
121121

122-
if (PushPopSplit == ARMSubtarget::SplitR11AAPCSSignRA)
123-
return CSR_AAPCS_SplitPush_R11_SaveList;
124-
125122
return CSR_AAPCS_SaveList;
126123
}
127124

llvm/lib/Target/ARM/ARMCallingConv.td

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -301,17 +301,14 @@ def CSR_ATPCS_SplitPush_SwiftError : CalleeSavedRegs<(sub CSR_ATPCS_SplitPush,
301301
def CSR_ATPCS_SplitPush_SwiftTail : CalleeSavedRegs<(sub CSR_ATPCS_SplitPush,
302302
R10)>;
303303

304-
// Sometimes we need to split the push of the callee-saved GPRs into two
305-
// regions, to ensure that the frame chain record is set up correctly. These
306-
// list the callee-saved registers in the order they end up on the stack, which
307-
// depends on whether the frame pointer is r7 or r11.
308-
def CSR_AAPCS_SplitPush_R11 : CalleeSavedRegs<(add R10, R9, R8, R7, R6, R5, R4,
309-
LR, R11,
310-
(sequence "D%u", 15, 8))>;
311-
def CSR_AAPCS_SplitPush_R7 : CalleeSavedRegs<(add LR, R11,
312-
R7, R6, R5, R4,
313-
R10, R9, R8,
314-
(sequence "D%u", 15, 8))>;
304+
// When enforcing an AAPCS compliant frame chain, R11 is used as the frame
305+
// pointer even for Thumb targets, where split pushes are necessary.
306+
// This AAPCS alternative makes sure the frame index slots match the push
307+
// order in that case.
308+
def CSR_AAPCS_SplitPush : CalleeSavedRegs<(add LR, R11,
309+
R7, R6, R5, R4,
310+
R10, R9, R8,
311+
(sequence "D%u", 15, 8))>;
315312

316313
// Constructors and destructors return 'this' in the ARM C++ ABI; since 'this'
317314
// and the pointer return value are both passed in R0 in these cases, this can

llvm/lib/Target/ARM/ARMFrameLowering.cpp

Lines changed: 48 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,6 @@ SpillArea getSpillArea(Register Reg,
199199
// push {r0-r10, r12} GPRCS1
200200
// vpush {r8-d15} DPRCS1
201201
// push {r11, lr} GPRCS2
202-
//
203-
// SplitR11AAPCSSignRA:
204-
// push {r0-r10, r12} GPRSC1
205-
// push {r11, lr} GPRCS2
206-
// vpush {r8-d15} DPRCS1
207202

208203
// If FPCXTNS is spilled (for CMSE secure entryfunctions), it is always at
209204
// the top of the stack frame.
@@ -251,8 +246,7 @@ SpillArea getSpillArea(Register Reg,
251246
return SpillArea::GPRCS1;
252247

253248
case ARM::LR:
254-
if (Variation == ARMSubtarget::SplitR11WindowsSEH ||
255-
Variation == ARMSubtarget::SplitR11AAPCSSignRA)
249+
if (Variation == ARMSubtarget::SplitR11WindowsSEH)
256250
return SpillArea::GPRCS2;
257251
else
258252
return SpillArea::GPRCS1;
@@ -869,9 +863,6 @@ static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI,
869863
// This is a conservative estimation: Assume the frame pointer being r7 and
870864
// pc("r15") up to r8 getting spilled before (= 8 registers).
871865
int MaxRegBytes = 8 * 4;
872-
if (PushPopSplit == ARMSubtarget::SplitR11AAPCSSignRA)
873-
// Here, r11 can be stored below all of r4-r15.
874-
MaxRegBytes = 11 * 4;
875866
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
876867
// Here, r11 can be stored below all of r4-r15 plus d8-d15.
877868
MaxRegBytes = 11 * 4 + 8 * 8;
@@ -944,23 +935,17 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
944935
}
945936

946937
// Determine spill area sizes, and some important frame indices.
947-
SpillArea FramePtrSpillArea;
948-
bool BeforeFPPush = true;
949938
for (const CalleeSavedInfo &I : CSI) {
950939
Register Reg = I.getReg();
951940
int FI = I.getFrameIdx();
952941

953-
SpillArea Area = getSpillArea(Reg, PushPopSplit,
954-
AFI->getNumAlignedDPRCS2Regs(), RegInfo);
955-
956-
if (Reg == FramePtr) {
942+
if (Reg == FramePtr)
957943
FramePtrSpillFI = FI;
958-
FramePtrSpillArea = Area;
959-
}
960944
if (Reg == ARM::D8)
961945
D8SpillFI = FI;
962946

963-
switch (Area) {
947+
switch (getSpillArea(Reg, PushPopSplit, AFI->getNumAlignedDPRCS2Regs(),
948+
RegInfo)) {
964949
case SpillArea::FPCXT:
965950
FPCXTSaveSize += 4;
966951
break;
@@ -987,23 +972,21 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
987972
// Move past FPCXT area.
988973
if (FPCXTSaveSize > 0) {
989974
LastPush = MBBI++;
990-
DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, BeforeFPPush);
975+
DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, true);
991976
}
992977

993978
// Allocate the vararg register save area.
994979
if (ArgRegsSaveSize) {
995980
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -ArgRegsSaveSize,
996981
MachineInstr::FrameSetup);
997982
LastPush = std::prev(MBBI);
998-
DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, BeforeFPPush);
983+
DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, true);
999984
}
1000985

1001986
// Move past area 1.
1002987
if (GPRCS1Size > 0) {
1003988
GPRCS1Push = LastPush = MBBI++;
1004-
DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, BeforeFPPush);
1005-
if (FramePtrSpillArea == SpillArea::GPRCS1)
1006-
BeforeFPPush = false;
989+
DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, true);
1007990
}
1008991

1009992
// Determine starting offsets of spill areas. These offsets are all positive
@@ -1027,13 +1010,21 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
10271010
} else {
10281011
DPRCSOffset = GPRCS2Offset - DPRGapSize - DPRCSSize;
10291012
}
1013+
int FramePtrOffsetInPush = 0;
10301014
if (HasFP) {
10311015
// Offset from the CFA to the saved frame pointer, will be negative.
10321016
[[maybe_unused]] int FPOffset = MFI.getObjectOffset(FramePtrSpillFI);
10331017
LLVM_DEBUG(dbgs() << "FramePtrSpillFI: " << FramePtrSpillFI
10341018
<< ", FPOffset: " << FPOffset << "\n");
10351019
assert(getMaxFPOffset(STI, *AFI, MF) <= FPOffset &&
10361020
"Max FP estimation is wrong");
1021+
// Offset from the top of the GPRCS1 area to the saved frame pointer, will
1022+
// be negative.
1023+
FramePtrOffsetInPush = FPOffset + ArgRegsSaveSize + FPCXTSaveSize;
1024+
LLVM_DEBUG(dbgs() << "FramePtrOffsetInPush=" << FramePtrOffsetInPush
1025+
<< ", FramePtrSpillOffset="
1026+
<< (MFI.getObjectOffset(FramePtrSpillFI) + NumBytes)
1027+
<< "\n");
10371028
AFI->setFramePtrSpillOffset(MFI.getObjectOffset(FramePtrSpillFI) +
10381029
NumBytes);
10391030
}
@@ -1045,9 +1036,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
10451036
// after DPRCS1.
10461037
if (GPRCS2Size > 0 && PushPopSplit != ARMSubtarget::SplitR11WindowsSEH) {
10471038
GPRCS2Push = LastPush = MBBI++;
1048-
DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size, BeforeFPPush);
1049-
if (FramePtrSpillArea == SpillArea::GPRCS2)
1050-
BeforeFPPush = false;
1039+
DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
10511040
}
10521041

10531042
// Prolog/epilog inserter assumes we correctly align DPRs on the stack, so our
@@ -1060,7 +1049,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
10601049
else {
10611050
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -DPRGapSize,
10621051
MachineInstr::FrameSetup);
1063-
DefCFAOffsetCandidates.addInst(std::prev(MBBI), DPRGapSize, BeforeFPPush);
1052+
DefCFAOffsetCandidates.addInst(std::prev(MBBI), DPRGapSize);
10641053
}
10651054
}
10661055

@@ -1069,8 +1058,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
10691058
// Since vpush register list cannot have gaps, there may be multiple vpush
10701059
// instructions in the prologue.
10711060
while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
1072-
DefCFAOffsetCandidates.addInst(MBBI, sizeOfSPAdjustment(*MBBI),
1073-
BeforeFPPush);
1061+
DefCFAOffsetCandidates.addInst(MBBI, sizeOfSPAdjustment(*MBBI));
10741062
LastPush = MBBI++;
10751063
}
10761064
}
@@ -1089,9 +1077,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
10891077
// Move GPRCS2, if using using SplitR11WindowsSEH.
10901078
if (GPRCS2Size > 0 && PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
10911079
GPRCS2Push = LastPush = MBBI++;
1092-
DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size, BeforeFPPush);
1093-
if (FramePtrSpillArea == SpillArea::GPRCS2)
1094-
BeforeFPPush = false;
1080+
DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
10951081
}
10961082

10971083
bool NeedsWinCFIStackAlloc = NeedsWinCFI;
@@ -1192,51 +1178,28 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
11921178
// into spill area 1, including the FP in R11. In either case, it
11931179
// is in area one and the adjustment needs to take place just after
11941180
// that push.
1181+
// FIXME: The above is not necessary true when PACBTI is enabled.
1182+
// AAPCS requires use of R11, and PACBTI gets in the way of regular pushes,
1183+
// so FP ends up on area two.
11951184
MachineBasicBlock::iterator AfterPush;
11961185
if (HasFP) {
1197-
MachineBasicBlock::iterator FPPushInst;
1198-
// Offset from SP immediately after the push which saved the FP to the FP
1199-
// save slot.
1200-
int64_t FPOffsetAfterPush;
1201-
switch (FramePtrSpillArea) {
1202-
case SpillArea::GPRCS1:
1203-
FPPushInst = GPRCS1Push;
1204-
FPOffsetAfterPush = MFI.getObjectOffset(FramePtrSpillFI) +
1205-
ArgRegsSaveSize + FPCXTSaveSize +
1206-
sizeOfSPAdjustment(*FPPushInst);
1207-
LLVM_DEBUG(dbgs() << "Frame pointer in GPRCS1, offset "
1208-
<< FPOffsetAfterPush << " after that push\n");
1209-
break;
1210-
case SpillArea::GPRCS2:
1211-
FPPushInst = GPRCS2Push;
1212-
FPOffsetAfterPush = MFI.getObjectOffset(FramePtrSpillFI) +
1213-
ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1214-
sizeOfSPAdjustment(*FPPushInst);
1215-
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH)
1216-
FPOffsetAfterPush += DPRCSSize + DPRGapSize;
1217-
LLVM_DEBUG(dbgs() << "Frame pointer in GPRCS2, offset "
1218-
<< FPOffsetAfterPush << " after that push\n");
1219-
break;
1220-
default:
1221-
llvm_unreachable("frame pointer in unknown spill area");
1222-
break;
1186+
AfterPush = std::next(GPRCS1Push);
1187+
unsigned PushSize = sizeOfSPAdjustment(*GPRCS1Push);
1188+
int FPOffset = PushSize + FramePtrOffsetInPush;
1189+
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
1190+
AfterPush = std::next(GPRCS2Push);
1191+
emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, dl, TII,
1192+
FramePtr, ARM::SP, 0, MachineInstr::FrameSetup);
1193+
} else {
1194+
emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, dl, TII,
1195+
FramePtr, ARM::SP, FPOffset,
1196+
MachineInstr::FrameSetup);
12231197
}
1224-
AfterPush = std::next(FPPushInst);
1225-
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH)
1226-
assert(FPOffsetAfterPush == 0);
1227-
1228-
// Emit the MOV or ADD to set up the frame pointer register.
1229-
emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, dl, TII,
1230-
FramePtr, ARM::SP, FPOffsetAfterPush,
1231-
MachineInstr::FrameSetup);
1232-
12331198
if (!NeedsWinCFI) {
1234-
// Emit DWARF info to find the CFA using the frame pointer from this
1235-
// point onward.
1236-
if (FPOffsetAfterPush != 0) {
1199+
if (FramePtrOffsetInPush + PushSize != 0) {
12371200
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa(
12381201
nullptr, MRI->getDwarfRegNum(FramePtr, true),
1239-
-MFI.getObjectOffset(FramePtrSpillFI)));
1202+
FPCXTSaveSize + ArgRegsSaveSize - FramePtrOffsetInPush));
12401203
BuildMI(MBB, AfterPush, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
12411204
.addCFIIndex(CFIIndex)
12421205
.setMIFlags(MachineInstr::FrameSetup);
@@ -1749,8 +1712,7 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
17491712
if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
17501713
!isCmseEntry && !isTrap && AFI->getArgumentStackToRestore() == 0 &&
17511714
STI.hasV5TOps() && MBB.succ_empty() && !hasPAC &&
1752-
(PushPopSplit != ARMSubtarget::SplitR11WindowsSEH &&
1753-
PushPopSplit != ARMSubtarget::SplitR11AAPCSSignRA)) {
1715+
PushPopSplit != ARMSubtarget::SplitR11WindowsSEH) {
17541716
Reg = ARM::PC;
17551717
// Fold the return instruction into the LDM.
17561718
DeleteRet = true;
@@ -2983,29 +2945,18 @@ bool ARMFrameLowering::assignCalleeSavedSpillSlots(
29832945
const auto &AFI = *MF.getInfo<ARMFunctionInfo>();
29842946
if (AFI.shouldSignReturnAddress()) {
29852947
// The order of register must match the order we push them, because the
2986-
// PEI assigns frame indices in that order. That order depends on the
2987-
// PushPopSplitVariation, there are only two cases which we use with return
2988-
// address signing:
2989-
switch (STI.getPushPopSplitVariation(MF)) {
2990-
case ARMSubtarget::SplitR7:
2991-
// LR, R7, R6, R5, R4, <R12>, R11, R10, R9, R8, D15-D8
2992-
CSI.insert(find_if(CSI,
2993-
[=](const auto &CS) {
2994-
Register Reg = CS.getReg();
2995-
return Reg == ARM::R10 || Reg == ARM::R11 ||
2996-
Reg == ARM::R8 || Reg == ARM::R9 ||
2997-
ARM::DPRRegClass.contains(Reg);
2998-
}),
2999-
CalleeSavedInfo(ARM::R12));
3000-
break;
3001-
case ARMSubtarget::SplitR11AAPCSSignRA:
3002-
// With SplitR11AAPCSSignRA, R12 will always be the highest-addressed CSR
3003-
// on the stack.
3004-
CSI.insert(CSI.begin(), CalleeSavedInfo(ARM::R12));
3005-
break;
3006-
default:
3007-
llvm_unreachable("Unexpected CSR split with return address signing");
3008-
}
2948+
// PEI assigns frame indices in that order. When compiling for return
2949+
// address sign and authenication, we use split push, therefore the orders
2950+
// we want are:
2951+
// LR, R7, R6, R5, R4, <R12>, R11, R10, R9, R8, D15-D8
2952+
CSI.insert(find_if(CSI,
2953+
[=](const auto &CS) {
2954+
Register Reg = CS.getReg();
2955+
return Reg == ARM::R10 || Reg == ARM::R11 ||
2956+
Reg == ARM::R8 || Reg == ARM::R9 ||
2957+
ARM::DPRRegClass.contains(Reg);
2958+
}),
2959+
CalleeSavedInfo(ARM::R12));
30092960
}
30102961

30112962
return false;

llvm/lib/Target/ARM/ARMSubtarget.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -514,12 +514,5 @@ ARMSubtarget::getPushPopSplitVariation(const MachineFunction &MF) const {
514514
F.needsUnwindTableEntry() &&
515515
(MFI.hasVarSizedObjects() || getRegisterInfo()->hasStackRealignment(MF)))
516516
return SplitR11WindowsSEH;
517-
518-
// Returns R11SplitAAPCSBranchSigning if R11 and lr are not adjacent to each
519-
// other in the list of callee saved registers in a frame, and branch
520-
// signing is enabled.
521-
if (MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress() &&
522-
getFramePointerReg() == ARM::R11)
523-
return SplitR11AAPCSSignRA;
524517
return NoSplit;
525518
}

llvm/lib/Target/ARM/ARMSubtarget.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,18 +105,6 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
105105
/// vpush {d8-d15}
106106
/// push {r11, lr}
107107
SplitR11WindowsSEH,
108-
109-
/// When generating AAPCS-compilant frame chains, R11 is the frame pointer,
110-
/// and must be pushed adjacent to the return address (LR). Normally this
111-
/// isn't a problem, because the only register between them is r12, which is
112-
/// the intra-procedure-call scratch register, so doesn't need to be saved.
113-
/// However, when PACBTI is in use, r12 contains the authentication code, so
114-
/// does need to be saved. This means that we need a separate push for R11
115-
/// and LR.
116-
/// push {r0-r10, r12}
117-
/// push {r11, lr}
118-
/// vpush {d8-d15}
119-
SplitR11AAPCSSignRA,
120108
};
121109

122110
protected:

0 commit comments

Comments
 (0)