@@ -211,6 +211,24 @@ AArch64FrameLowering::getStackIDForScalableVectors() const {
211211 return TargetStackID::SVEVector;
212212}
213213
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+
214232// / Returns the size of the entire SVE stackframe (calleesaves + spills).
215233static StackOffset getSVEStackSize (const MachineFunction &MF) {
216234 const AArch64FunctionInfo *AFI = MF.getInfo <AArch64FunctionInfo>();
@@ -959,10 +977,7 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
959977
960978 bool IsWin64 =
961979 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);
966981
967982 auto PrologueSaveSize = AFI->getCalleeSavedStackSize () + FixedObject;
968983 // All of the remaining stack allocations are for locals.
@@ -993,32 +1008,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
9931008 ++MBBI;
9941009 }
9951010
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) {
10221013 // Only set up FP if we actually need to.
10231014 int64_t FPOffset = isTargetDarwin (MF) ? (AFI->getCalleeSavedStackSize () - 16 ) : 0 ;
10241015
@@ -1161,7 +1152,9 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
11611152
11621153 // Allocate space for the rest of the frame.
11631154 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);
11651158 unsigned scratchSPReg = AArch64::SP;
11661159
11671160 if (NeedsRealignment) {
@@ -1215,7 +1208,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
12151208 // FIXME: Clarify FrameSetup flags here.
12161209 // Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
12171210 // needed.
1218- if (RegInfo->hasBasePointer (MF)) {
1211+ // For funclets the BP belongs to the containing function.
1212+ if (!IsFunclet && RegInfo->hasBasePointer (MF)) {
12191213 TII->copyPhysReg (MBB, MBBI, DL, RegInfo->getBaseRegister (), AArch64::SP,
12201214 false );
12211215 if (NeedsWinCFI) {
@@ -1232,6 +1226,19 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
12321226 .setMIFlag (MachineInstr::FrameSetup);
12331227 }
12341228
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+
12351242 if (needsFrameMoves) {
12361243 const DataLayout &TD = MF.getDataLayout ();
12371244 const int StackGrowth = isTargetDarwin (MF)
@@ -1450,10 +1457,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
14501457
14511458 bool IsWin64 =
14521459 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);
14571461
14581462 uint64_t AfterCSRPopSize = ArgumentPopSize;
14591463 auto PrologueSaveSize = AFI->getCalleeSavedStackSize () + FixedObject;
@@ -1679,7 +1683,9 @@ static StackOffset getFPOffset(const MachineFunction &MF, int64_t ObjectOffset)
16791683 const auto &Subtarget = MF.getSubtarget <AArch64Subtarget>();
16801684 bool IsWin64 =
16811685 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 );
16831689 unsigned FPAdjust = isTargetDarwin (MF)
16841690 ? 16 : AFI->getCalleeSavedStackSize (MF.getFrameInfo ());
16851691 return {ObjectOffset + FixedObject + FPAdjust, MVT::i8 };
@@ -2632,9 +2638,14 @@ void AArch64FrameLowering::processFunctionBeforeFrameFinalized(
26322638 ++MBBI;
26332639
26342640 // 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 );
26372647 EHInfo.UnwindHelpFrameIdx = UnwindHelpFI;
2648+
26382649 // We need to store -2 into the UnwindHelp object at the start of the
26392650 // function.
26402651 DebugLoc DL;
@@ -2656,10 +2667,14 @@ int AArch64FrameLowering::getFrameIndexReferencePreferSP(
26562667 const MachineFunction &MF, int FI, unsigned &FrameReg,
26572668 bool IgnoreSPUpdates) const {
26582669 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);
26632678}
26642679
26652680// / The parent frame offset (aka dispFrame) is only used on X86_64 to retrieve
0 commit comments