@@ -216,6 +216,24 @@ AArch64FrameLowering::getStackIDForScalableVectors() const {
216
216
return TargetStackID::SVEVector;
217
217
}
218
218
219
+ // / Returns the size of the fixed object area (allocated next to sp on entry)
220
+ // / On Win64 this may include a var args area and an UnwindHelp object for EH.
221
+ static unsigned getFixedObjectSize (const MachineFunction &MF,
222
+ const AArch64FunctionInfo *AFI, bool IsWin64,
223
+ bool IsFunclet) {
224
+ if (!IsWin64 || IsFunclet) {
225
+ // Only Win64 uses fixed objects, and then only for the function (not
226
+ // funclets)
227
+ return 0 ;
228
+ } else {
229
+ // Var args are stored here in the primary function.
230
+ const unsigned VarArgsArea = AFI->getVarArgsGPRSize ();
231
+ // To support EH funclets we allocate an UnwindHelp object
232
+ const unsigned UnwindHelpObject = (MF.hasEHFunclets () ? 8 : 0 );
233
+ return alignTo (VarArgsArea + UnwindHelpObject, 16 );
234
+ }
235
+ }
236
+
219
237
// / Returns the size of the entire SVE stackframe (calleesaves + spills).
220
238
static StackOffset getSVEStackSize (const MachineFunction &MF) {
221
239
const AArch64FunctionInfo *AFI = MF.getInfo <AArch64FunctionInfo>();
@@ -997,10 +1015,7 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
997
1015
998
1016
bool IsWin64 =
999
1017
Subtarget.isCallingConvWin64 (MF.getFunction ().getCallingConv ());
1000
- // Var args are accounted for in the containing function, so don't
1001
- // include them for funclets.
1002
- unsigned FixedObject = (IsWin64 && !IsFunclet) ?
1003
- alignTo (AFI->getVarArgsGPRSize (), 16 ) : 0 ;
1018
+ unsigned FixedObject = getFixedObjectSize (MF, AFI, IsWin64, IsFunclet);
1004
1019
1005
1020
auto PrologueSaveSize = AFI->getCalleeSavedStackSize () + FixedObject;
1006
1021
// All of the remaining stack allocations are for locals.
@@ -1031,32 +1046,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1031
1046
++MBBI;
1032
1047
}
1033
1048
1034
- // The code below is not applicable to funclets. We have emitted all the SEH
1035
- // opcodes that we needed to emit. The FP and BP belong to the containing
1036
- // function.
1037
- if (IsFunclet) {
1038
- if (NeedsWinCFI) {
1039
- HasWinCFI = true ;
1040
- BuildMI (MBB, MBBI, DL, TII->get (AArch64::SEH_PrologEnd))
1041
- .setMIFlag (MachineInstr::FrameSetup);
1042
- }
1043
-
1044
- // SEH funclets are passed the frame pointer in X1. If the parent
1045
- // function uses the base register, then the base register is used
1046
- // directly, and is not retrieved from X1.
1047
- if (F.hasPersonalityFn ()) {
1048
- EHPersonality Per = classifyEHPersonality (F.getPersonalityFn ());
1049
- if (isAsynchronousEHPersonality (Per)) {
1050
- BuildMI (MBB, MBBI, DL, TII->get (TargetOpcode::COPY), AArch64::FP)
1051
- .addReg (AArch64::X1).setMIFlag (MachineInstr::FrameSetup);
1052
- MBB.addLiveIn (AArch64::X1);
1053
- }
1054
- }
1055
-
1056
- return ;
1057
- }
1058
-
1059
- if (HasFP) {
1049
+ // For funclets the FP belongs to the containing function.
1050
+ if (!IsFunclet && HasFP) {
1060
1051
// Only set up FP if we actually need to.
1061
1052
int64_t FPOffset = isTargetDarwin (MF) ? (AFI->getCalleeSavedStackSize () - 16 ) : 0 ;
1062
1053
@@ -1199,7 +1190,9 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1199
1190
1200
1191
// Allocate space for the rest of the frame.
1201
1192
if (NumBytes) {
1202
- const bool NeedsRealignment = RegInfo->needsStackRealignment (MF);
1193
+ // Alignment is required for the parent frame, not the funclet
1194
+ const bool NeedsRealignment =
1195
+ !IsFunclet && RegInfo->needsStackRealignment (MF);
1203
1196
unsigned scratchSPReg = AArch64::SP;
1204
1197
1205
1198
if (NeedsRealignment) {
@@ -1253,7 +1246,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1253
1246
// FIXME: Clarify FrameSetup flags here.
1254
1247
// Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
1255
1248
// needed.
1256
- if (RegInfo->hasBasePointer (MF)) {
1249
+ // For funclets the BP belongs to the containing function.
1250
+ if (!IsFunclet && RegInfo->hasBasePointer (MF)) {
1257
1251
TII->copyPhysReg (MBB, MBBI, DL, RegInfo->getBaseRegister (), AArch64::SP,
1258
1252
false );
1259
1253
if (NeedsWinCFI) {
@@ -1270,6 +1264,19 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1270
1264
.setMIFlag (MachineInstr::FrameSetup);
1271
1265
}
1272
1266
1267
+ // SEH funclets are passed the frame pointer in X1. If the parent
1268
+ // function uses the base register, then the base register is used
1269
+ // directly, and is not retrieved from X1.
1270
+ if (IsFunclet && F.hasPersonalityFn ()) {
1271
+ EHPersonality Per = classifyEHPersonality (F.getPersonalityFn ());
1272
+ if (isAsynchronousEHPersonality (Per)) {
1273
+ BuildMI (MBB, MBBI, DL, TII->get (TargetOpcode::COPY), AArch64::FP)
1274
+ .addReg (AArch64::X1)
1275
+ .setMIFlag (MachineInstr::FrameSetup);
1276
+ MBB.addLiveIn (AArch64::X1);
1277
+ }
1278
+ }
1279
+
1273
1280
if (needsFrameMoves) {
1274
1281
const DataLayout &TD = MF.getDataLayout ();
1275
1282
const int StackGrowth = isTargetDarwin (MF)
@@ -1488,10 +1495,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
1488
1495
1489
1496
bool IsWin64 =
1490
1497
Subtarget.isCallingConvWin64 (MF.getFunction ().getCallingConv ());
1491
- // Var args are accounted for in the containing function, so don't
1492
- // include them for funclets.
1493
- unsigned FixedObject =
1494
- (IsWin64 && !IsFunclet) ? alignTo (AFI->getVarArgsGPRSize (), 16 ) : 0 ;
1498
+ unsigned FixedObject = getFixedObjectSize (MF, AFI, IsWin64, IsFunclet);
1495
1499
1496
1500
uint64_t AfterCSRPopSize = ArgumentPopSize;
1497
1501
auto PrologueSaveSize = AFI->getCalleeSavedStackSize () + FixedObject;
@@ -1717,7 +1721,9 @@ static StackOffset getFPOffset(const MachineFunction &MF, int64_t ObjectOffset)
1717
1721
const auto &Subtarget = MF.getSubtarget <AArch64Subtarget>();
1718
1722
bool IsWin64 =
1719
1723
Subtarget.isCallingConvWin64 (MF.getFunction ().getCallingConv ());
1720
- unsigned FixedObject = IsWin64 ? alignTo (AFI->getVarArgsGPRSize (), 16 ) : 0 ;
1724
+
1725
+ unsigned FixedObject =
1726
+ getFixedObjectSize (MF, AFI, IsWin64, /* IsFunclet=*/ false );
1721
1727
unsigned FPAdjust = isTargetDarwin (MF)
1722
1728
? 16 : AFI->getCalleeSavedStackSize (MF.getFrameInfo ());
1723
1729
return {ObjectOffset + FixedObject + FPAdjust, MVT::i8};
@@ -2668,9 +2674,14 @@ void AArch64FrameLowering::processFunctionBeforeFrameFinalized(
2668
2674
++MBBI;
2669
2675
2670
2676
// Create an UnwindHelp object.
2671
- int UnwindHelpFI =
2672
- MFI.CreateStackObject (/* size*/ 8 , /* alignment*/ 16 , false );
2677
+ // The UnwindHelp object is allocated at the start of the fixed object area
2678
+ int64_t FixedObject =
2679
+ getFixedObjectSize (MF, AFI, /* IsWin64*/ true , /* IsFunclet*/ false );
2680
+ int UnwindHelpFI = MFI.CreateFixedObject (/* Size*/ 8 ,
2681
+ /* SPOffset*/ -FixedObject,
2682
+ /* IsImmutable=*/ false );
2673
2683
EHInfo.UnwindHelpFrameIdx = UnwindHelpFI;
2684
+
2674
2685
// We need to store -2 into the UnwindHelp object at the start of the
2675
2686
// function.
2676
2687
DebugLoc DL;
@@ -3082,10 +3093,14 @@ int AArch64FrameLowering::getFrameIndexReferencePreferSP(
3082
3093
const MachineFunction &MF, int FI, unsigned &FrameReg,
3083
3094
bool IgnoreSPUpdates) const {
3084
3095
const MachineFrameInfo &MFI = MF.getFrameInfo ();
3085
- LLVM_DEBUG (dbgs () << " Offset from the SP for " << FI << " is "
3086
- << MFI.getObjectOffset (FI) << " \n " );
3087
- FrameReg = AArch64::SP;
3088
- return MFI.getObjectOffset (FI);
3096
+ if (IgnoreSPUpdates) {
3097
+ LLVM_DEBUG (dbgs () << " Offset from the SP for " << FI << " is "
3098
+ << MFI.getObjectOffset (FI) << " \n " );
3099
+ FrameReg = AArch64::SP;
3100
+ return MFI.getObjectOffset (FI);
3101
+ }
3102
+
3103
+ return getFrameIndexReference (MF, FI, FrameReg);
3089
3104
}
3090
3105
3091
3106
// / The parent frame offset (aka dispFrame) is only used on X86_64 to retrieve
0 commit comments