@@ -211,6 +211,24 @@ AArch64FrameLowering::getStackIDForScalableVectors() const {
211
211
return TargetStackID::SVEVector;
212
212
}
213
213
214
+ // / Returns the size of the fixed object area (allocated next to sp on entry)
215
+ // / On Win64 this may include a var args area and an UnwindHelp object for EH.
216
+ static unsigned getFixedObjectSize (const MachineFunction &MF,
217
+ const AArch64FunctionInfo *AFI, bool IsWin64,
218
+ bool IsFunclet) {
219
+ if (!IsWin64 || IsFunclet) {
220
+ // Only Win64 uses fixed objects, and then only for the function (not
221
+ // funclets)
222
+ return 0 ;
223
+ } else {
224
+ // Var args are stored here in the primary function.
225
+ const unsigned VarArgsArea = AFI->getVarArgsGPRSize ();
226
+ // To support EH funclets we allocate an UnwindHelp object
227
+ const unsigned UnwindHelpObject = (MF.hasEHFunclets () ? 8 : 0 );
228
+ return alignTo (VarArgsArea + UnwindHelpObject, 16 );
229
+ }
230
+ }
231
+
214
232
// / Returns the size of the entire SVE stackframe (calleesaves + spills).
215
233
static StackOffset getSVEStackSize (const MachineFunction &MF) {
216
234
const AArch64FunctionInfo *AFI = MF.getInfo <AArch64FunctionInfo>();
@@ -959,10 +977,7 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
959
977
960
978
bool IsWin64 =
961
979
Subtarget.isCallingConvWin64 (MF.getFunction ().getCallingConv ());
962
- // Var args are accounted for in the containing function, so don't
963
- // include them for funclets.
964
- unsigned FixedObject = (IsWin64 && !IsFunclet) ?
965
- alignTo (AFI->getVarArgsGPRSize (), 16 ) : 0 ;
980
+ unsigned FixedObject = getFixedObjectSize (MF, AFI, IsWin64, IsFunclet);
966
981
967
982
auto PrologueSaveSize = AFI->getCalleeSavedStackSize () + FixedObject;
968
983
// All of the remaining stack allocations are for locals.
@@ -993,32 +1008,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
993
1008
++MBBI;
994
1009
}
995
1010
996
- // The code below is not applicable to funclets. We have emitted all the SEH
997
- // opcodes that we needed to emit. The FP and BP belong to the containing
998
- // function.
999
- if (IsFunclet) {
1000
- if (NeedsWinCFI) {
1001
- HasWinCFI = true ;
1002
- BuildMI (MBB, MBBI, DL, TII->get (AArch64::SEH_PrologEnd))
1003
- .setMIFlag (MachineInstr::FrameSetup);
1004
- }
1005
-
1006
- // SEH funclets are passed the frame pointer in X1. If the parent
1007
- // function uses the base register, then the base register is used
1008
- // directly, and is not retrieved from X1.
1009
- if (F.hasPersonalityFn ()) {
1010
- EHPersonality Per = classifyEHPersonality (F.getPersonalityFn ());
1011
- if (isAsynchronousEHPersonality (Per)) {
1012
- BuildMI (MBB, MBBI, DL, TII->get (TargetOpcode::COPY), AArch64::FP)
1013
- .addReg (AArch64::X1).setMIFlag (MachineInstr::FrameSetup);
1014
- MBB.addLiveIn (AArch64::X1);
1015
- }
1016
- }
1017
-
1018
- return ;
1019
- }
1020
-
1021
- if (HasFP) {
1011
+ // For funclets the FP belongs to the containing function.
1012
+ if (!IsFunclet && HasFP) {
1022
1013
// Only set up FP if we actually need to.
1023
1014
int64_t FPOffset = isTargetDarwin (MF) ? (AFI->getCalleeSavedStackSize () - 16 ) : 0 ;
1024
1015
@@ -1161,7 +1152,9 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1161
1152
1162
1153
// Allocate space for the rest of the frame.
1163
1154
if (NumBytes) {
1164
- const bool NeedsRealignment = RegInfo->needsStackRealignment (MF);
1155
+ // Alignment is required for the parent frame, not the funclet
1156
+ const bool NeedsRealignment =
1157
+ !IsFunclet && RegInfo->needsStackRealignment (MF);
1165
1158
unsigned scratchSPReg = AArch64::SP;
1166
1159
1167
1160
if (NeedsRealignment) {
@@ -1215,7 +1208,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1215
1208
// FIXME: Clarify FrameSetup flags here.
1216
1209
// Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
1217
1210
// needed.
1218
- if (RegInfo->hasBasePointer (MF)) {
1211
+ // For funclets the BP belongs to the containing function.
1212
+ if (!IsFunclet && RegInfo->hasBasePointer (MF)) {
1219
1213
TII->copyPhysReg (MBB, MBBI, DL, RegInfo->getBaseRegister (), AArch64::SP,
1220
1214
false );
1221
1215
if (NeedsWinCFI) {
@@ -1232,6 +1226,19 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1232
1226
.setMIFlag (MachineInstr::FrameSetup);
1233
1227
}
1234
1228
1229
+ // SEH funclets are passed the frame pointer in X1. If the parent
1230
+ // function uses the base register, then the base register is used
1231
+ // directly, and is not retrieved from X1.
1232
+ if (IsFunclet && F.hasPersonalityFn ()) {
1233
+ EHPersonality Per = classifyEHPersonality (F.getPersonalityFn ());
1234
+ if (isAsynchronousEHPersonality (Per)) {
1235
+ BuildMI (MBB, MBBI, DL, TII->get (TargetOpcode::COPY), AArch64::FP)
1236
+ .addReg (AArch64::X1)
1237
+ .setMIFlag (MachineInstr::FrameSetup);
1238
+ MBB.addLiveIn (AArch64::X1);
1239
+ }
1240
+ }
1241
+
1235
1242
if (needsFrameMoves) {
1236
1243
const DataLayout &TD = MF.getDataLayout ();
1237
1244
const int StackGrowth = isTargetDarwin (MF)
@@ -1450,10 +1457,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
1450
1457
1451
1458
bool IsWin64 =
1452
1459
Subtarget.isCallingConvWin64 (MF.getFunction ().getCallingConv ());
1453
- // Var args are accounted for in the containing function, so don't
1454
- // include them for funclets.
1455
- unsigned FixedObject =
1456
- (IsWin64 && !IsFunclet) ? alignTo (AFI->getVarArgsGPRSize (), 16 ) : 0 ;
1460
+ unsigned FixedObject = getFixedObjectSize (MF, AFI, IsWin64, IsFunclet);
1457
1461
1458
1462
uint64_t AfterCSRPopSize = ArgumentPopSize;
1459
1463
auto PrologueSaveSize = AFI->getCalleeSavedStackSize () + FixedObject;
@@ -1679,7 +1683,9 @@ static StackOffset getFPOffset(const MachineFunction &MF, int64_t ObjectOffset)
1679
1683
const auto &Subtarget = MF.getSubtarget <AArch64Subtarget>();
1680
1684
bool IsWin64 =
1681
1685
Subtarget.isCallingConvWin64 (MF.getFunction ().getCallingConv ());
1682
- unsigned FixedObject = IsWin64 ? alignTo (AFI->getVarArgsGPRSize (), 16 ) : 0 ;
1686
+
1687
+ unsigned FixedObject =
1688
+ getFixedObjectSize (MF, AFI, IsWin64, /* IsFunclet=*/ false );
1683
1689
unsigned FPAdjust = isTargetDarwin (MF)
1684
1690
? 16 : AFI->getCalleeSavedStackSize (MF.getFrameInfo ());
1685
1691
return {ObjectOffset + FixedObject + FPAdjust, MVT::i8};
@@ -2632,9 +2638,14 @@ void AArch64FrameLowering::processFunctionBeforeFrameFinalized(
2632
2638
++MBBI;
2633
2639
2634
2640
// Create an UnwindHelp object.
2635
- int UnwindHelpFI =
2636
- MFI.CreateStackObject (/* size*/ 8 , /* alignment*/ 16 , false );
2641
+ // The UnwindHelp object is allocated at the start of the fixed object area
2642
+ int64_t FixedObject =
2643
+ getFixedObjectSize (MF, AFI, /* IsWin64*/ true , /* IsFunclet*/ false );
2644
+ int UnwindHelpFI = MFI.CreateFixedObject (/* Size*/ 8 ,
2645
+ /* SPOffset*/ -FixedObject,
2646
+ /* IsImmutable=*/ false );
2637
2647
EHInfo.UnwindHelpFrameIdx = UnwindHelpFI;
2648
+
2638
2649
// We need to store -2 into the UnwindHelp object at the start of the
2639
2650
// function.
2640
2651
DebugLoc DL;
@@ -2656,10 +2667,14 @@ int AArch64FrameLowering::getFrameIndexReferencePreferSP(
2656
2667
const MachineFunction &MF, int FI, unsigned &FrameReg,
2657
2668
bool IgnoreSPUpdates) const {
2658
2669
const MachineFrameInfo &MFI = MF.getFrameInfo ();
2659
- LLVM_DEBUG (dbgs () << " Offset from the SP for " << FI << " is "
2660
- << MFI.getObjectOffset (FI) << " \n " );
2661
- FrameReg = AArch64::SP;
2662
- return MFI.getObjectOffset (FI);
2670
+ if (IgnoreSPUpdates) {
2671
+ LLVM_DEBUG (dbgs () << " Offset from the SP for " << FI << " is "
2672
+ << MFI.getObjectOffset (FI) << " \n " );
2673
+ FrameReg = AArch64::SP;
2674
+ return MFI.getObjectOffset (FI);
2675
+ }
2676
+
2677
+ return getFrameIndexReference (MF, FI, FrameReg);
2663
2678
}
2664
2679
2665
2680
// / The parent frame offset (aka dispFrame) is only used on X86_64 to retrieve
0 commit comments