Skip to content

Commit d7b0e55

Browse files
committed
X86: fix frame offset calculation with mandatory tail calls
If there's a region of the stack reserved for potential tail call arguments (only the case when we guarantee tail calls will be honoured), this is right next to the incoming stored return address, not necessarily next to the callee-saved area, so combining the two into a single figure leads to incorrect offsets in some edge cases.
1 parent 16ff91e commit d7b0e55

File tree

1 file changed

+30
-42
lines changed

1 file changed

+30
-42
lines changed

llvm/lib/Target/X86/X86FrameLowering.cpp

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,15 +1349,12 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
13491349
// to determine the end of the prologue.
13501350
DebugLoc DL;
13511351

1352-
// Add RETADDR move area to callee saved frame size.
1353-
int TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta();
1354-
if (TailCallReturnAddrDelta && IsWin64Prologue)
1352+
// Space reserved for stack-based arguments when making a (ABI-guaranteed)
1353+
// tail call.
1354+
unsigned TailCallArgReserveSize = -X86FI->getTCReturnAddrDelta();
1355+
if (TailCallArgReserveSize && IsWin64Prologue)
13551356
report_fatal_error("Can't handle guaranteed tail call under win64 yet");
13561357

1357-
if (TailCallReturnAddrDelta < 0)
1358-
X86FI->setCalleeSavedFrameSize(
1359-
X86FI->getCalleeSavedFrameSize() - TailCallReturnAddrDelta);
1360-
13611358
const bool EmitStackProbeCall =
13621359
STI.getTargetLowering()->hasStackProbeSymbol(MF);
13631360
unsigned StackProbeSize = STI.getTargetLowering()->getStackProbeSize(MF);
@@ -1391,7 +1388,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
13911388
!EmitStackProbeCall && // No stack probes.
13921389
!MFI.hasCopyImplyingStackAdjustment() && // Don't push and pop.
13931390
!MF.shouldSplitStack()) { // Regular stack
1394-
uint64_t MinSize = X86FI->getCalleeSavedFrameSize();
1391+
uint64_t MinSize =
1392+
X86FI->getCalleeSavedFrameSize() - X86FI->getTCReturnAddrDelta();
13951393
if (HasFP) MinSize += SlotSize;
13961394
X86FI->setUsesRedZone(MinSize > 0 || StackSize > 0);
13971395
StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
@@ -1401,8 +1399,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
14011399
// Insert stack pointer adjustment for later moving of return addr. Only
14021400
// applies to tail call optimized functions where the callee argument stack
14031401
// size is bigger than the callers.
1404-
if (TailCallReturnAddrDelta < 0) {
1405-
BuildStackAdjustment(MBB, MBBI, DL, TailCallReturnAddrDelta,
1402+
if (TailCallArgReserveSize != 0) {
1403+
BuildStackAdjustment(MBB, MBBI, DL, -(int)TailCallArgReserveSize,
14061404
/*InEpilogue=*/false)
14071405
.setMIFlag(MachineInstr::FrameSetup);
14081406
}
@@ -1451,7 +1449,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
14511449
if (X86FI->getRestoreBasePointer())
14521450
FrameSize += SlotSize;
14531451

1454-
NumBytes = FrameSize - X86FI->getCalleeSavedFrameSize();
1452+
NumBytes = FrameSize -
1453+
(X86FI->getCalleeSavedFrameSize() + TailCallArgReserveSize);
14551454

14561455
// Callee-saved registers are pushed on stack before the stack is realigned.
14571456
if (TRI->hasStackRealignment(MF) && !IsWin64Prologue)
@@ -1554,7 +1553,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
15541553
}
15551554
} else {
15561555
assert(!IsFunclet && "funclets without FPs not yet implemented");
1557-
NumBytes = StackSize - X86FI->getCalleeSavedFrameSize();
1556+
NumBytes = StackSize -
1557+
(X86FI->getCalleeSavedFrameSize() + TailCallArgReserveSize);
15581558
}
15591559

15601560
// Update the offset adjustment, which is mainly used by codeview to translate
@@ -2011,6 +2011,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
20112011
uint64_t StackSize = MFI.getStackSize();
20122012
uint64_t MaxAlign = calculateMaxStackAlign(MF);
20132013
unsigned CSSize = X86FI->getCalleeSavedFrameSize();
2014+
unsigned TailCallArgReserveSize = -X86FI->getTCReturnAddrDelta();
20142015
bool HasFP = hasFP(MF);
20152016
uint64_t NumBytes = 0;
20162017

@@ -2024,14 +2025,14 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
20242025
} else if (HasFP) {
20252026
// Calculate required stack adjustment.
20262027
uint64_t FrameSize = StackSize - SlotSize;
2027-
NumBytes = FrameSize - CSSize;
2028+
NumBytes = FrameSize - CSSize - TailCallArgReserveSize;
20282029

20292030
// Callee-saved registers were pushed on stack before the stack was
20302031
// realigned.
20312032
if (TRI->hasStackRealignment(MF) && !IsWin64Prologue)
20322033
NumBytes = alignTo(FrameSize, MaxAlign);
20332034
} else {
2034-
NumBytes = StackSize - CSSize;
2035+
NumBytes = StackSize - CSSize - TailCallArgReserveSize;
20352036
}
20362037
uint64_t SEHStackAllocAmt = NumBytes;
20372038

@@ -2098,7 +2099,6 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
20982099

20992100
if (MBBI != MBB.end())
21002101
DL = MBBI->getDebugLoc();
2101-
21022102
// If there is an ADD32ri or SUB32ri of ESP immediately before this
21032103
// instruction, merge the two instructions.
21042104
if (NumBytes || MFI.hasVarSizedObjects())
@@ -2143,7 +2143,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
21432143
if (!hasFP(MF) && NeedsDwarfCFI) {
21442144
// Define the current CFA rule to use the provided offset.
21452145
BuildCFI(MBB, MBBI, DL,
2146-
MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + SlotSize));
2146+
MCCFIInstruction::cfiDefCfaOffset(
2147+
nullptr, CSSize + TailCallArgReserveSize + SlotSize));
21472148
}
21482149
--MBBI;
21492150
}
@@ -2226,7 +2227,6 @@ StackOffset X86FrameLowering::getFrameIndexReference(const MachineFunction &MF,
22262227
const X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
22272228
unsigned CSSize = X86FI->getCalleeSavedFrameSize();
22282229
uint64_t StackSize = MFI.getStackSize();
2229-
bool HasFP = hasFP(MF);
22302230
bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
22312231
int64_t FPDelta = 0;
22322232

@@ -2262,39 +2262,27 @@ StackOffset X86FrameLowering::getFrameIndexReference(const MachineFunction &MF,
22622262
"FPDelta isn't aligned per the Win64 ABI!");
22632263
}
22642264

2265-
2266-
if (TRI->hasBasePointer(MF)) {
2267-
assert(HasFP && "VLAs and dynamic stack realign, but no FP?!");
2268-
if (FI < 0) {
2269-
// Skip the saved EBP.
2270-
return StackOffset::getFixed(Offset + SlotSize + FPDelta);
2271-
} else {
2272-
assert(isAligned(MFI.getObjectAlign(FI), -(Offset + StackSize)));
2273-
return StackOffset::getFixed(Offset + StackSize);
2274-
}
2275-
} else if (TRI->hasStackRealignment(MF)) {
2276-
if (FI < 0) {
2277-
// Skip the saved EBP.
2278-
return StackOffset::getFixed(Offset + SlotSize + FPDelta);
2279-
} else {
2280-
assert(isAligned(MFI.getObjectAlign(FI), -(Offset + StackSize)));
2281-
return StackOffset::getFixed(Offset + StackSize);
2282-
}
2283-
// FIXME: Support tail calls
2284-
} else {
2285-
if (!HasFP)
2286-
return StackOffset::getFixed(Offset + StackSize);
2287-
2288-
// Skip the saved EBP.
2265+
if (FrameReg == TRI->getFramePtr()) {
2266+
// Skip saved EBP/RBP
22892267
Offset += SlotSize;
22902268

2269+
// Account for restricted Windows prologue.
2270+
Offset += FPDelta;
2271+
22912272
// Skip the RETADDR move area
22922273
int TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta();
22932274
if (TailCallReturnAddrDelta < 0)
22942275
Offset -= TailCallReturnAddrDelta;
2276+
2277+
return StackOffset::getFixed(Offset);
22952278
}
22962279

2297-
return StackOffset::getFixed(Offset + FPDelta);
2280+
// FrameReg is either the stack pointer or a base pointer. But the base is
2281+
// located at the end of the statically known StackSize so the distinction
2282+
// doesn't really matter.
2283+
if (TRI->hasStackRealignment(MF) || TRI->hasBasePointer(MF))
2284+
assert(isAligned(MFI.getObjectAlign(FI), -(Offset + StackSize)));
2285+
return StackOffset::getFixed(Offset + StackSize);
22982286
}
22992287

23002288
int X86FrameLowering::getWin64EHFrameIndexRef(const MachineFunction &MF, int FI,

0 commit comments

Comments
 (0)