@@ -183,6 +183,24 @@ static unsigned estimateRSStackSizeLimit(MachineFunction &MF) {
183
183
return DefaultSafeSPDisplacement;
184
184
}
185
185
186
+ // / Returns the size of the fixed object area (allocated next to sp on entry)
187
+ // / On Win64 this may include a var args area and an UnwindHelp object for EH.
188
+ static unsigned getFixedObjectSize (const MachineFunction &MF,
189
+ const AArch64FunctionInfo *AFI, bool IsWin64,
190
+ bool IsFunclet) {
191
+ if (!IsWin64 || IsFunclet) {
192
+ // Only Win64 uses fixed objects, and then only for the function (not
193
+ // funclets)
194
+ return 0 ;
195
+ } else {
196
+ // Var args are stored here in the primary function.
197
+ const unsigned VarArgsArea = AFI->getVarArgsGPRSize ();
198
+ // To support EH funclets we allocate an UnwindHelp object
199
+ const unsigned UnwindHelpObject = (MF.hasEHFunclets () ? 8 : 0 );
200
+ return alignTo (VarArgsArea + UnwindHelpObject, 16 );
201
+ }
202
+ }
203
+
186
204
bool AArch64FrameLowering::canUseRedZone (const MachineFunction &MF) const {
187
205
if (!EnableRedZone)
188
206
return false ;
@@ -891,10 +909,7 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
891
909
892
910
bool IsWin64 =
893
911
Subtarget.isCallingConvWin64 (MF.getFunction ().getCallingConv ());
894
- // Var args are accounted for in the containing function, so don't
895
- // include them for funclets.
896
- unsigned FixedObject = (IsWin64 && !IsFunclet) ?
897
- alignTo (AFI->getVarArgsGPRSize (), 16 ) : 0 ;
912
+ unsigned FixedObject = getFixedObjectSize (MF, AFI, IsWin64, IsFunclet);
898
913
899
914
auto PrologueSaveSize = AFI->getCalleeSavedStackSize () + FixedObject;
900
915
// All of the remaining stack allocations are for locals.
@@ -922,32 +937,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
922
937
++MBBI;
923
938
}
924
939
925
- // The code below is not applicable to funclets. We have emitted all the SEH
926
- // opcodes that we needed to emit. The FP and BP belong to the containing
927
- // function.
928
- if (IsFunclet) {
929
- if (NeedsWinCFI) {
930
- HasWinCFI = true ;
931
- BuildMI (MBB, MBBI, DL, TII->get (AArch64::SEH_PrologEnd))
932
- .setMIFlag (MachineInstr::FrameSetup);
933
- }
934
-
935
- // SEH funclets are passed the frame pointer in X1. If the parent
936
- // function uses the base register, then the base register is used
937
- // directly, and is not retrieved from X1.
938
- if (F.hasPersonalityFn ()) {
939
- EHPersonality Per = classifyEHPersonality (F.getPersonalityFn ());
940
- if (isAsynchronousEHPersonality (Per)) {
941
- BuildMI (MBB, MBBI, DL, TII->get (TargetOpcode::COPY), AArch64::FP)
942
- .addReg (AArch64::X1).setMIFlag (MachineInstr::FrameSetup);
943
- MBB.addLiveIn (AArch64::X1);
944
- }
945
- }
946
-
947
- return ;
948
- }
949
-
950
- if (HasFP) {
940
+ // For funclets the FP belongs to the containing function.
941
+ if (!IsFunclet && HasFP) {
951
942
// Only set up FP if we actually need to. Frame pointer is fp =
952
943
// sp - fixedobject - 16.
953
944
int FPOffset = AFI->getCalleeSavedStackSize () - 16 ;
@@ -1058,7 +1049,9 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1058
1049
1059
1050
// Allocate space for the rest of the frame.
1060
1051
if (NumBytes) {
1061
- const bool NeedsRealignment = RegInfo->needsStackRealignment (MF);
1052
+ // Alignment is required for the parent frame, not the funclet
1053
+ const bool NeedsRealignment =
1054
+ !IsFunclet && RegInfo->needsStackRealignment (MF);
1062
1055
unsigned scratchSPReg = AArch64::SP;
1063
1056
1064
1057
if (NeedsRealignment) {
@@ -1111,7 +1104,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1111
1104
// FIXME: Clarify FrameSetup flags here.
1112
1105
// Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
1113
1106
// needed.
1114
- if (RegInfo->hasBasePointer (MF)) {
1107
+ // For funclets the BP belongs to the containing function.
1108
+ if (!IsFunclet && RegInfo->hasBasePointer (MF)) {
1115
1109
TII->copyPhysReg (MBB, MBBI, DL, RegInfo->getBaseRegister (), AArch64::SP,
1116
1110
false );
1117
1111
if (NeedsWinCFI) {
@@ -1128,6 +1122,18 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1128
1122
.setMIFlag (MachineInstr::FrameSetup);
1129
1123
}
1130
1124
1125
+ // SEH funclets are passed the frame pointer in X1. If the parent
1126
+ // function uses the base register, then the base register is used
1127
+ // directly, and is not retrieved from X1.
1128
+ if (IsFunclet && F.hasPersonalityFn ()) {
1129
+ EHPersonality Per = classifyEHPersonality (F.getPersonalityFn ());
1130
+ if (isAsynchronousEHPersonality (Per)) {
1131
+ BuildMI (MBB, MBBI, DL, TII->get (TargetOpcode::COPY), AArch64::FP)
1132
+ .addReg (AArch64::X1).setMIFlag (MachineInstr::FrameSetup);
1133
+ MBB.addLiveIn (AArch64::X1);
1134
+ }
1135
+ }
1136
+
1131
1137
if (needsFrameMoves) {
1132
1138
const DataLayout &TD = MF.getDataLayout ();
1133
1139
const int StackGrowth = -TD.getPointerSize (0 );
@@ -1344,10 +1350,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
1344
1350
1345
1351
bool IsWin64 =
1346
1352
Subtarget.isCallingConvWin64 (MF.getFunction ().getCallingConv ());
1347
- // Var args are accounted for in the containing function, so don't
1348
- // include them for funclets.
1349
- unsigned FixedObject =
1350
- (IsWin64 && !IsFunclet) ? alignTo (AFI->getVarArgsGPRSize (), 16 ) : 0 ;
1353
+ unsigned FixedObject = getFixedObjectSize (MF, AFI, IsWin64, IsFunclet);
1351
1354
1352
1355
uint64_t AfterCSRPopSize = ArgumentPopSize;
1353
1356
auto PrologueSaveSize = AFI->getCalleeSavedStackSize () + FixedObject;
@@ -1517,7 +1520,8 @@ static int getFPOffset(const MachineFunction &MF, int ObjectOffset) {
1517
1520
const auto &Subtarget = MF.getSubtarget <AArch64Subtarget>();
1518
1521
bool IsWin64 =
1519
1522
Subtarget.isCallingConvWin64 (MF.getFunction ().getCallingConv ());
1520
- unsigned FixedObject = IsWin64 ? alignTo (AFI->getVarArgsGPRSize (), 16 ) : 0 ;
1523
+ unsigned FixedObject =
1524
+ getFixedObjectSize (MF, AFI, IsWin64, /* IsFunclet=*/ false );
1521
1525
return ObjectOffset + FixedObject + 16 ;
1522
1526
}
1523
1527
@@ -2197,9 +2201,15 @@ void AArch64FrameLowering::processFunctionBeforeFrameFinalized(
2197
2201
++MBBI;
2198
2202
2199
2203
// Create an UnwindHelp object.
2200
- int UnwindHelpFI =
2201
- MFI.CreateStackObject (/* size*/ 8 , /* alignment*/ 16 , false );
2204
+ // The UnwindHelp object is allocated at the start of the fixed object area
2205
+ const AArch64FunctionInfo *AFI = MF.getInfo <AArch64FunctionInfo>();
2206
+ int64_t FixedObject =
2207
+ getFixedObjectSize (MF, AFI, /* IsWin64*/ true , /* IsFunclet*/ false );
2208
+ int UnwindHelpFI = MFI.CreateFixedObject (/* Size*/ 8 ,
2209
+ /* SPOffset*/ -FixedObject,
2210
+ /* IsImmutable=*/ false );
2202
2211
EHInfo.UnwindHelpFrameIdx = UnwindHelpFI;
2212
+
2203
2213
// We need to store -2 into the UnwindHelp object at the start of the
2204
2214
// function.
2205
2215
DebugLoc DL;
@@ -2221,10 +2231,14 @@ int AArch64FrameLowering::getFrameIndexReferencePreferSP(
2221
2231
const MachineFunction &MF, int FI, unsigned &FrameReg,
2222
2232
bool IgnoreSPUpdates) const {
2223
2233
const MachineFrameInfo &MFI = MF.getFrameInfo ();
2224
- LLVM_DEBUG (dbgs () << " Offset from the SP for " << FI << " is "
2225
- << MFI.getObjectOffset (FI) << " \n " );
2226
- FrameReg = AArch64::SP;
2227
- return MFI.getObjectOffset (FI);
2234
+ if (IgnoreSPUpdates) {
2235
+ LLVM_DEBUG (dbgs () << " Offset from the SP for " << FI << " is "
2236
+ << MFI.getObjectOffset (FI) << " \n " );
2237
+ FrameReg = AArch64::SP;
2238
+ return MFI.getObjectOffset (FI);
2239
+ }
2240
+
2241
+ return getFrameIndexReference (MF, FI, FrameReg);
2228
2242
}
2229
2243
2230
2244
// / The parent frame offset (aka dispFrame) is only used on X86_64 to retrieve
0 commit comments