#include "X86Subtarget.h"
#include "X86TargetMachine.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/Analysis/LibCallSemantics.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
uint64_t MaxAlign = calculateMaxStackAlign(MF); // Desired stack alignment.
uint64_t StackSize = MFI->getStackSize(); // Number of bytes to allocate.
bool IsFunclet = MBB.isEHFuncletEntry();
+ bool IsClrFunclet =
+ IsFunclet &&
+ classifyEHPersonality(Fn->getPersonalityFn()) == EHPersonality::CoreCLR;
bool HasFP = hasFP(MF);
bool IsWin64CC = STI.isCallingConvWin64(Fn->getCallingConv());
bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
unsigned FramePtr = TRI->getFrameRegister(MF);
const unsigned MachineFramePtr =
STI.isTarget64BitILP32()
- ? getX86SubSuperRegister(FramePtr, MVT::i64, false)
- : FramePtr;
- unsigned BasePtr = TRI->getBaseRegister();
- DebugLoc DL;
-
- // Add RETADDR move area to callee saved frame size.
+ ? getX86SubSuperRegister(FramePtr, MVT::i64, false)\r
+ : FramePtr;\r
+ unsigned BasePtr = TRI->getBaseRegister();\r
+ \r
+ // Debug location must be unknown since the first debug location is used\r
+ // to determine the end of the prologue.\r
+ DebugLoc DL;\r
+\r
+ // Add RETADDR move area to callee saved frame size.\r
int TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta();
if (TailCallReturnAddrDelta && IsWin64Prologue)
report_fatal_error("Can't handle guaranteed tail call under win64 yet");
uint64_t NumBytes = 0;
int stackGrowth = -SlotSize;
- unsigned RDX = Uses64BitFramePtr ? X86::RDX : X86::EDX;
- if (IsWin64Prologue && IsFunclet) {
- // Immediately spill RDX into the home slot. The runtime cares about this.
+ // Find the funclet establisher parameter
+ unsigned Establisher = X86::NoRegister;
+ if (IsClrFunclet)
+ Establisher = Uses64BitFramePtr ? X86::RCX : X86::ECX;
+ else if (IsFunclet)
+ Establisher = Uses64BitFramePtr ? X86::RDX : X86::EDX;
+
+ if (IsWin64Prologue && IsFunclet & !IsClrFunclet) {
+ // Immediately spill establisher into the home slot.
+ // The runtime cares about this.
// MOV64mr %rdx, 16(%rsp)
unsigned MOVmr = Uses64BitFramePtr ? X86::MOV64mr : X86::MOV32mr;
addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(MOVmr)), StackPtr, true, 16)
- .addReg(RDX)
+ .addReg(Establisher)
.setMIFlag(MachineInstr::FrameSetup);
}
int SEHFrameOffset = 0;
if (IsWin64Prologue && HasFP) {
// Set RBP to a small fixed offset from RSP. In the funclet case, we base
- // this calculation on the incoming RDX, which holds the value of RSP from
- // the parent frame at the end of the prologue.
- unsigned SPOrRDX = !IsFunclet ? StackPtr : RDX;
+ // this calculation on the incoming establisher, which holds the value of
+ // RSP from the parent frame at the end of the prologue.
+ unsigned SPOrEstablisher = IsFunclet ? Establisher : StackPtr;
SEHFrameOffset = calculateSetFPREG(ParentFrameNumBytes);
if (SEHFrameOffset)
addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::LEA64r), FramePtr),
- SPOrRDX, false, SEHFrameOffset);
+ SPOrEstablisher, false, SEHFrameOffset);
else
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64rr), FramePtr)
- .addReg(SPOrRDX);
+ .addReg(SPOrEstablisher);
// If this is not a funclet, emit the CFI describing our frame pointer.
if (NeedsWinCFI && !IsFunclet)
bool X86FrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const {
assert(MBB.getParent() && "Block is not attached to a function!");
+ // Win64 has strict requirements in terms of epilogue and we are
+ // not taking a chance at messing with them.
+ // I.e., unless this block is already an exit block, we can't use
+ // it as an epilogue.
+ if (MBB.getParent()->getSubtarget<X86Subtarget>().isTargetWin64() &&
+ !MBB.succ_empty() && !MBB.isReturnBlock())
+ return false;
+
if (canUseLEAForSPInEpilogue(*MBB.getParent()))
return true;