@@ -183,6 +183,24 @@ static unsigned estimateRSStackSizeLimit(MachineFunction &MF) {
183183 return DefaultSafeSPDisplacement;
184184}
185185
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+
186204bool AArch64FrameLowering::canUseRedZone (const MachineFunction &MF) const {
187205 if (!EnableRedZone)
188206 return false ;
@@ -891,10 +909,7 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
891909
892910 bool IsWin64 =
893911 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);
898913
899914 auto PrologueSaveSize = AFI->getCalleeSavedStackSize () + FixedObject;
900915 // All of the remaining stack allocations are for locals.
@@ -922,32 +937,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
922937 ++MBBI;
923938 }
924939
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) {
951942 // Only set up FP if we actually need to. Frame pointer is fp =
952943 // sp - fixedobject - 16.
953944 int FPOffset = AFI->getCalleeSavedStackSize () - 16 ;
@@ -1058,7 +1049,9 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
10581049
10591050 // Allocate space for the rest of the frame.
10601051 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);
10621055 unsigned scratchSPReg = AArch64::SP;
10631056
10641057 if (NeedsRealignment) {
@@ -1111,7 +1104,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
11111104 // FIXME: Clarify FrameSetup flags here.
11121105 // Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
11131106 // needed.
1114- if (RegInfo->hasBasePointer (MF)) {
1107+ // For funclets the BP belongs to the containing function.
1108+ if (!IsFunclet && RegInfo->hasBasePointer (MF)) {
11151109 TII->copyPhysReg (MBB, MBBI, DL, RegInfo->getBaseRegister (), AArch64::SP,
11161110 false );
11171111 if (NeedsWinCFI) {
@@ -1128,6 +1122,18 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
11281122 .setMIFlag (MachineInstr::FrameSetup);
11291123 }
11301124
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+
11311137 if (needsFrameMoves) {
11321138 const DataLayout &TD = MF.getDataLayout ();
11331139 const int StackGrowth = -TD.getPointerSize (0 );
@@ -1344,10 +1350,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
13441350
13451351 bool IsWin64 =
13461352 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);
13511354
13521355 uint64_t AfterCSRPopSize = ArgumentPopSize;
13531356 auto PrologueSaveSize = AFI->getCalleeSavedStackSize () + FixedObject;
@@ -1517,7 +1520,8 @@ static int getFPOffset(const MachineFunction &MF, int ObjectOffset) {
15171520 const auto &Subtarget = MF.getSubtarget <AArch64Subtarget>();
15181521 bool IsWin64 =
15191522 Subtarget.isCallingConvWin64 (MF.getFunction ().getCallingConv ());
1520- unsigned FixedObject = IsWin64 ? alignTo (AFI->getVarArgsGPRSize (), 16 ) : 0 ;
1523+ unsigned FixedObject =
1524+ getFixedObjectSize (MF, AFI, IsWin64, /* IsFunclet=*/ false );
15211525 return ObjectOffset + FixedObject + 16 ;
15221526}
15231527
@@ -2197,9 +2201,15 @@ void AArch64FrameLowering::processFunctionBeforeFrameFinalized(
21972201 ++MBBI;
21982202
21992203 // 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 );
22022211 EHInfo.UnwindHelpFrameIdx = UnwindHelpFI;
2212+
22032213 // We need to store -2 into the UnwindHelp object at the start of the
22042214 // function.
22052215 DebugLoc DL;
@@ -2221,10 +2231,14 @@ int AArch64FrameLowering::getFrameIndexReferencePreferSP(
22212231 const MachineFunction &MF, int FI, unsigned &FrameReg,
22222232 bool IgnoreSPUpdates) const {
22232233 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);
22282242}
22292243
22302244// / The parent frame offset (aka dispFrame) is only used on X86_64 to retrieve
0 commit comments