<div dir="ltr">Thanks!</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Jun 25, 2014 at 5:41 AM, NAKAMURA Takumi <span dir="ltr"><<a href="mailto:geek4civic@gmail.com" target="_blank">geek4civic@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: chapuni<br>
Date: Wed Jun 25 07:41:52 2014<br>
New Revision: 211691<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=211691&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=211691&view=rev</a><br>
Log:<br>
Re-apply r211399, "Generate native unwind info on Win64" with a fix to ignore SEH pseudo ops in X86 JIT emitter.<br>
<br>
--<br>
This patch enables LLVM to emit Win64-native unwind info rather than<br>
DWARF CFI. It handles all corner cases (I hope), including stack<br>
realignment.<br>
<br>
Because the unwind info is not flexible enough to describe stack frames<br>
with a gap of unknown size in the middle, such as the one caused by<br>
stack realignment, I modified register spilling code to place all spills<br>
into the fixed frame slots, so that they can be accessed relative to the<br>
frame pointer.<br>
<br>
Patch by Vadim Chugunov!<br>
<br>
Reviewed By: rnk<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D4081" target="_blank">http://reviews.llvm.org/D4081</a><br>
<br>
Added:<br>
llvm/trunk/test/CodeGen/X86/win64_eh.ll<br>
Modified:<br>
llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h<br>
llvm/trunk/include/llvm/MC/MCAsmInfo.h<br>
llvm/trunk/include/llvm/Target/TargetFrameLowering.h<br>
llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp<br>
llvm/trunk/lib/CodeGen/MachineFunction.cpp<br>
llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp<br>
llvm/trunk/lib/MC/MCObjectFileInfo.cpp<br>
llvm/trunk/lib/MC/MCStreamer.cpp<br>
llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp<br>
llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp<br>
llvm/trunk/lib/Target/X86/X86FrameLowering.cpp<br>
llvm/trunk/lib/Target/X86/X86FrameLowering.h<br>
llvm/trunk/lib/Target/X86/X86ISelLowering.cpp<br>
llvm/trunk/lib/Target/X86/X86InstrCompiler.td<br>
llvm/trunk/lib/Target/X86/X86MCInstLower.cpp<br>
llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll<br>
llvm/trunk/test/CodeGen/X86/2009-06-03-Win64SpillXMM.ll<br>
llvm/trunk/test/CodeGen/X86/avx-intel-ocl.ll<br>
llvm/trunk/test/CodeGen/X86/gcc_except_table.ll<br>
<br>
Modified: llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h (original)<br>
+++ llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h Wed Jun 25 07:41:52 2014<br>
@@ -484,6 +484,9 @@ public:<br>
///<br>
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable);<br>
<br>
+ /// CreateFixedSpillStackObject - Create a spill slot at a fixed location<br>
+ /// on the stack. Returns an index with a negative value.<br>
+ int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset);<br>
<br>
/// isFixedObjectIndex - Returns true if the specified index corresponds to a<br>
/// fixed stack object.<br>
<br>
Modified: llvm/trunk/include/llvm/MC/MCAsmInfo.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAsmInfo.h?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAsmInfo.h?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/MC/MCAsmInfo.h (original)<br>
+++ llvm/trunk/include/llvm/MC/MCAsmInfo.h Wed Jun 25 07:41:52 2014<br>
@@ -481,6 +481,7 @@ public:<br>
bool isExceptionHandlingDwarf() const {<br>
return (ExceptionsType == ExceptionHandling::DwarfCFI ||<br>
ExceptionsType == ExceptionHandling::ARM ||<br>
+ // Win64 handler data still uses DWARF LSDA encoding.<br>
ExceptionsType == ExceptionHandling::Win64);<br>
}<br>
bool doesDwarfUseRelocationsAcrossSections() const {<br>
<br>
Modified: llvm/trunk/include/llvm/Target/TargetFrameLowering.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetFrameLowering.h?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetFrameLowering.h?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Target/TargetFrameLowering.h (original)<br>
+++ llvm/trunk/include/llvm/Target/TargetFrameLowering.h Wed Jun 25 07:41:52 2014<br>
@@ -93,6 +93,19 @@ public:<br>
/// stack pointer.<br>
virtual bool isFPCloseToIncomingSP() const { return true; }<br>
<br>
+ /// assignCalleeSavedSpillSlots - Allows target to override spill slot<br>
+ /// assignment logic. If implemented, assignCalleeSavedSpillSlots() should<br>
+ /// assign frame slots to all CSI entries and return true. If this method<br>
+ /// returns false, spill slots will be assigned using generic implementation.<br>
+ /// assignCalleeSavedSpillSlots() may add, delete or rearrange elements of<br>
+ /// CSI.<br>
+ virtual bool<br>
+ assignCalleeSavedSpillSlots(MachineFunction &MF,<br>
+ const TargetRegisterInfo *TRI,<br>
+ std::vector<CalleeSavedInfo> &CSI) const {<br>
+ return false;<br>
+ }<br>
+<br>
/// getCalleeSavedSpillSlots - This method returns a pointer to an array of<br>
/// pairs, that contains an entry for each callee saved register that must be<br>
/// spilled to a particular stack location if it is spilled.<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp Wed Jun 25 07:41:52 2014<br>
@@ -77,9 +77,9 @@ void Win64Exception::beginFunction(const<br>
if (!shouldEmitPersonality)<br>
return;<br>
<br>
- MCSymbol *GCCHandlerSym =<br>
- Asm->GetExternalSymbolSymbol("_GCC_specific_handler");<br>
- Asm->OutStreamer.EmitWin64EHHandler(GCCHandlerSym, true, true);<br>
+ const MCSymbol *PersHandlerSym =<br>
+ TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI);<br>
+ Asm->OutStreamer.EmitWin64EHHandler(PersHandlerSym, true, true);<br>
<br>
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin",<br>
Asm->getFunctionNumber()));<br>
@@ -98,15 +98,8 @@ void Win64Exception::endFunction(const M<br>
MMI->TidyLandingPads();<br>
<br>
if (shouldEmitPersonality) {<br>
- const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();<br>
- const Function *Per = MMI->getPersonalities()[MMI->getPersonalityIndex()];<br>
- const MCSymbol *Sym =<br>
- TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI);<br>
-<br>
Asm->OutStreamer.PushSection();<br>
Asm->OutStreamer.EmitWin64EHHandlerData();<br>
- Asm->OutStreamer.EmitValue(MCSymbolRefExpr::Create(Sym, Asm->OutContext),<br>
- 4);<br>
emitExceptionTable();<br>
Asm->OutStreamer.PopSection();<br>
}<br>
<br>
Modified: llvm/trunk/lib/CodeGen/MachineFunction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineFunction.cpp?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineFunction.cpp?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/MachineFunction.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/MachineFunction.cpp Wed Jun 25 07:41:52 2014<br>
@@ -578,6 +578,21 @@ int MachineFrameInfo::CreateFixedObject(<br>
return -++NumFixedObjects;<br>
}<br>
<br>
+/// CreateFixedSpillStackObject - Create a spill slot at a fixed location<br>
+/// on the stack. Returns an index with a negative value.<br>
+int MachineFrameInfo::CreateFixedSpillStackObject(uint64_t Size,<br>
+ int64_t SPOffset) {<br>
+ unsigned StackAlign = getFrameLowering()->getStackAlignment();<br>
+ unsigned Align = MinAlign(SPOffset, StackAlign);<br>
+ Align = clampStackAlignment(!getFrameLowering()->isStackRealignable() ||<br>
+ !RealignOption,<br>
+ Align, getFrameLowering()->getStackAlignment());<br>
+ Objects.insert(Objects.begin(), StackObject(Size, Align, SPOffset,<br>
+ /*Immutable*/ true,<br>
+ /*isSS*/ true,<br>
+ /*Alloca*/ nullptr));<br>
+ return -++NumFixedObjects;<br>
+}<br>
<br>
BitVector<br>
MachineFrameInfo::getPristineRegs(const MachineBasicBlock *MBB) const {<br>
<br>
Modified: llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp Wed Jun 25 07:41:52 2014<br>
@@ -268,51 +268,56 @@ void PEI::calculateCalleeSavedRegisters(<br>
}<br>
}<br>
<br>
- if (CSI.empty())<br>
- return; // Early exit if no callee saved registers are modified!<br>
+ if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI)) {<br>
+ // If target doesn't implement this, use generic code.<br>
<br>
- unsigned NumFixedSpillSlots;<br>
- const TargetFrameLowering::SpillSlot *FixedSpillSlots =<br>
- TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots);<br>
-<br>
- // Now that we know which registers need to be saved and restored, allocate<br>
- // stack slots for them.<br>
- for (std::vector<CalleeSavedInfo>::iterator<br>
- I = CSI.begin(), E = CSI.end(); I != E; ++I) {<br>
- unsigned Reg = I->getReg();<br>
- const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg);<br>
+ if (CSI.empty())<br>
+ return; // Early exit if no callee saved registers are modified!<br>
<br>
- int FrameIdx;<br>
- if (RegInfo->hasReservedSpillSlot(F, Reg, FrameIdx)) {<br>
- I->setFrameIdx(FrameIdx);<br>
- continue;<br>
- }<br>
+ unsigned NumFixedSpillSlots;<br>
+ const TargetFrameLowering::SpillSlot *FixedSpillSlots =<br>
+ TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots);<br>
+<br>
+ // Now that we know which registers need to be saved and restored, allocate<br>
+ // stack slots for them.<br>
+ for (std::vector<CalleeSavedInfo>::iterator I = CSI.begin(), E = CSI.end();<br>
+ I != E; ++I) {<br>
+ unsigned Reg = I->getReg();<br>
+ const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg);<br>
+<br>
+ int FrameIdx;<br>
+ if (RegInfo->hasReservedSpillSlot(F, Reg, FrameIdx)) {<br>
+ I->setFrameIdx(FrameIdx);<br>
+ continue;<br>
+ }<br>
+<br>
+ // Check to see if this physreg must be spilled to a particular stack slot<br>
+ // on this target.<br>
+ const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots;<br>
+ while (FixedSlot != FixedSpillSlots + NumFixedSpillSlots &&<br>
+ FixedSlot->Reg != Reg)<br>
+ ++FixedSlot;<br>
+<br>
+ if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) {<br>
+ // Nope, just spill it anywhere convenient.<br>
+ unsigned Align = RC->getAlignment();<br>
+ unsigned StackAlign = TFI->getStackAlignment();<br>
+<br>
+ // We may not be able to satisfy the desired alignment specification of<br>
+ // the TargetRegisterClass if the stack alignment is smaller. Use the<br>
+ // min.<br>
+ Align = std::min(Align, StackAlign);<br>
+ FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true);<br>
+ if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx;<br>
+ if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx;<br>
+ } else {<br>
+ // Spill it to the stack where we must.<br>
+ FrameIdx =<br>
+ MFI->CreateFixedSpillStackObject(RC->getSize(), FixedSlot->Offset);<br>
+ }<br>
<br>
- // Check to see if this physreg must be spilled to a particular stack slot<br>
- // on this target.<br>
- const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots;<br>
- while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots &&<br>
- FixedSlot->Reg != Reg)<br>
- ++FixedSlot;<br>
-<br>
- if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) {<br>
- // Nope, just spill it anywhere convenient.<br>
- unsigned Align = RC->getAlignment();<br>
- unsigned StackAlign = TFI->getStackAlignment();<br>
-<br>
- // We may not be able to satisfy the desired alignment specification of<br>
- // the TargetRegisterClass if the stack alignment is smaller. Use the<br>
- // min.<br>
- Align = std::min(Align, StackAlign);<br>
- FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true);<br>
- if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx;<br>
- if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx;<br>
- } else {<br>
- // Spill it to the stack where we must.<br>
- FrameIdx = MFI->CreateFixedObject(RC->getSize(), FixedSlot->Offset, true);<br>
+ I->setFrameIdx(FrameIdx);<br>
}<br>
-<br>
- I->setFrameIdx(FrameIdx);<br>
}<br>
<br>
MFI->setCalleeSavedInfo(CSI);<br>
<br>
Modified: llvm/trunk/lib/MC/MCObjectFileInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectFileInfo.cpp?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectFileInfo.cpp?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/MC/MCObjectFileInfo.cpp (original)<br>
+++ llvm/trunk/lib/MC/MCObjectFileInfo.cpp Wed Jun 25 07:41:52 2014<br>
@@ -649,11 +649,16 @@ void MCObjectFileInfo::InitCOFFMCObjectF<br>
// though it contains relocatable pointers. In PIC mode, this is probably a<br>
// big runtime hit for C++ apps. Either the contents of the LSDA need to be<br>
// adjusted or this should be a data section.<br>
- LSDASection =<br>
- Ctx->getCOFFSection(".gcc_except_table",<br>
- COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |<br>
- COFF::IMAGE_SCN_MEM_READ,<br>
- SectionKind::getReadOnly());<br>
+ assert(T.isOSWindows() && "Windows is the only supported COFF target");<br>
+ if (T.getArch() == Triple::x86_64) {<br>
+ // On Windows 64 with SEH, the LSDA is emitted into the .xdata section<br>
+ LSDASection = 0;<br>
+ } else {<br>
+ LSDASection = Ctx->getCOFFSection(".gcc_except_table",<br>
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |<br>
+ COFF::IMAGE_SCN_MEM_READ,<br>
+ SectionKind::getReadOnly());<br>
+ }<br>
<br>
// Debug info.<br>
COFFDebugSymbolsSection =<br>
<br>
Modified: llvm/trunk/lib/MC/MCStreamer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/MC/MCStreamer.cpp (original)<br>
+++ llvm/trunk/lib/MC/MCStreamer.cpp Wed Jun 25 07:41:52 2014<br>
@@ -504,6 +504,8 @@ void MCStreamer::EmitWin64EHSetFrame(uns<br>
report_fatal_error("Frame register and offset already specified!");<br>
if (Offset & 0x0F)<br>
report_fatal_error("Misaligned frame pointer offset!");<br>
+ if (Offset > 240)<br>
+ report_fatal_error("Frame offset must be less than or equal to 240!");<br>
MCSymbol *Label = getContext().CreateTempSymbol();<br>
MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, Label, Register, Offset);<br>
EmitLabel(Label);<br>
<br>
Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp Wed Jun 25 07:41:52 2014<br>
@@ -143,8 +143,11 @@ getNonexecutableStackSection(MCContext &<br>
void X86MCAsmInfoMicrosoft::anchor() { }<br>
<br>
X86MCAsmInfoMicrosoft::X86MCAsmInfoMicrosoft(const Triple &Triple) {<br>
- if (Triple.getArch() == Triple::x86_64)<br>
+ if (Triple.getArch() == Triple::x86_64) {<br>
PrivateGlobalPrefix = ".L";<br>
+ PointerSize = 8;<br>
+ ExceptionsType = ExceptionHandling::Win64;<br>
+ }<br>
<br>
AssemblerDialect = AsmWriterFlavor;<br>
<br>
@@ -158,17 +161,18 @@ X86MCAsmInfoMicrosoft::X86MCAsmInfoMicro<br>
void X86MCAsmInfoGNUCOFF::anchor() { }<br>
<br>
X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple &Triple) {<br>
+ assert(Triple.isOSWindows() && "Windows is the only supported COFF target");<br>
if (Triple.getArch() == Triple::x86_64) {<br>
PrivateGlobalPrefix = ".L";<br>
PointerSize = 8;<br>
+ ExceptionsType = ExceptionHandling::Win64;<br>
+ } else {<br>
+ ExceptionsType = ExceptionHandling::DwarfCFI;<br>
}<br>
<br>
AssemblerDialect = AsmWriterFlavor;<br>
<br>
TextAlignFillValue = 0x90;<br>
<br>
- // Exceptions handling<br>
- ExceptionsType = ExceptionHandling::DwarfCFI;<br>
-<br>
UseIntegratedAssembler = true;<br>
}<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp Wed Jun 25 07:41:52 2014<br>
@@ -1131,6 +1131,16 @@ void Emitter<CodeEmitter>::emitInstructi<br>
case TargetOpcode::IMPLICIT_DEF:<br>
case TargetOpcode::KILL:<br>
break;<br>
+<br>
+ case X86::SEH_PushReg:<br>
+ case X86::SEH_SaveReg:<br>
+ case X86::SEH_SaveXMM:<br>
+ case X86::SEH_StackAlloc:<br>
+ case X86::SEH_SetFrame:<br>
+ case X86::SEH_PushFrame:<br>
+ case X86::SEH_EndPrologue:<br>
+ break;<br>
+<br>
case X86::MOVPC32r: {<br>
// This emits the "call" portion of this pseudo instruction.<br>
MCE.emitByte(BaseOpcode);<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86FrameLowering.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FrameLowering.cpp?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FrameLowering.cpp?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86FrameLowering.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86FrameLowering.cpp Wed Jun 25 07:41:52 2014<br>
@@ -29,6 +29,7 @@<br>
#include "llvm/MC/MCSymbol.h"<br>
#include "llvm/Support/CommandLine.h"<br>
#include "llvm/Target/TargetOptions.h"<br>
+#include "llvm/Support/Debug.h"<br>
<br>
using namespace llvm;<br>
<br>
@@ -305,9 +306,10 @@ static bool isEAXLiveIn(MachineFunction<br>
return false;<br>
}<br>
<br>
-void X86FrameLowering::emitCalleeSavedFrameMoves(<br>
- MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc DL,<br>
- unsigned FramePtr) const {<br>
+void<br>
+X86FrameLowering::emitCalleeSavedFrameMoves(MachineBasicBlock &MBB,<br>
+ MachineBasicBlock::iterator MBBI,<br>
+ DebugLoc DL) const {<br>
MachineFunction &MF = *MBB.getParent();<br>
MachineFrameInfo *MFI = MF.getFrameInfo();<br>
MachineModuleInfo &MMI = MF.getMMI();<br>
@@ -318,53 +320,11 @@ void X86FrameLowering::emitCalleeSavedFr<br>
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();<br>
if (CSI.empty()) return;<br>
<br>
- const X86RegisterInfo *RegInfo =<br>
- static_cast<const X86RegisterInfo *>(MF.getTarget().getRegisterInfo());<br>
- bool HasFP = hasFP(MF);<br>
-<br>
- // Calculate amount of bytes used for return address storing.<br>
- int stackGrowth = -RegInfo->getSlotSize();<br>
-<br>
- // FIXME: This is dirty hack. The code itself is pretty mess right now.<br>
- // It should be rewritten from scratch and generalized sometimes.<br>
-<br>
- // Determine maximum offset (minimum due to stack growth).<br>
- int64_t MaxOffset = 0;<br>
- for (std::vector<CalleeSavedInfo>::const_iterator<br>
- I = CSI.begin(), E = CSI.end(); I != E; ++I)<br>
- MaxOffset = std::min(MaxOffset,<br>
- MFI->getObjectOffset(I->getFrameIdx()));<br>
-<br>
// Calculate offsets.<br>
- int64_t saveAreaOffset = (HasFP ? 3 : 2) * stackGrowth;<br>
for (std::vector<CalleeSavedInfo>::const_iterator<br>
I = CSI.begin(), E = CSI.end(); I != E; ++I) {<br>
int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());<br>
unsigned Reg = I->getReg();<br>
- Offset = MaxOffset - Offset + saveAreaOffset;<br>
-<br>
- // Don't output a new machine move if we're re-saving the frame<br>
- // pointer. This happens when the PrologEpilogInserter has inserted an extra<br>
- // "PUSH" of the frame pointer -- the "emitPrologue" method automatically<br>
- // generates one when frame pointers are used. If we generate a "machine<br>
- // move" for this extra "PUSH", the linker will lose track of the fact that<br>
- // the frame pointer should have the value of the first "PUSH" when it's<br>
- // trying to unwind.<br>
- //<br>
- // FIXME: This looks inelegant. It's possibly correct, but it's covering up<br>
- // another bug. I.e., one where we generate a prolog like this:<br>
- //<br>
- // pushl %ebp<br>
- // movl %esp, %ebp<br>
- // pushl %ebp<br>
- // pushl %esi<br>
- // ...<br>
- //<br>
- // The immediate re-push of EBP is unnecessary. At the least, it's an<br>
- // optimization bug. EBP can be used as a scratch register in certain<br>
- // cases, but probably not when we have a frame pointer.<br>
- if (HasFP && FramePtr == Reg)<br>
- continue;<br>
<br>
unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);<br>
unsigned CFIIndex =<br>
@@ -396,6 +356,84 @@ static bool usesTheStack(const MachineFu<br>
/// automatically adjust the stack pointer. Adjust the stack pointer to allocate<br>
/// space for local variables. Also emit labels used by the exception handler to<br>
/// generate the exception handling frames.<br>
+<br>
+/*<br>
+ Here's a gist of what gets emitted:<br>
+<br>
+ ; Establish frame pointer, if needed<br>
+ [if needs FP]<br>
+ push %rbp<br>
+ .cfi_def_cfa_offset 16<br>
+ .cfi_offset %rbp, -16<br>
+ .seh_pushreg %rpb<br>
+ mov %rsp, %rbp<br>
+ .cfi_def_cfa_register %rbp<br>
+<br>
+ ; Spill general-purpose registers<br>
+ [for all callee-saved GPRs]<br>
+ pushq %<reg><br>
+ [if not needs FP]<br>
+ .cfi_def_cfa_offset (offset from RETADDR)<br>
+ .seh_pushreg %<reg><br>
+<br>
+ ; If the required stack alignment > default stack alignment<br>
+ ; rsp needs to be re-aligned. This creates a "re-alignment gap"<br>
+ ; of unknown size in the stack frame.<br>
+ [if stack needs re-alignment]<br>
+ and $MASK, %rsp<br>
+<br>
+ ; Allocate space for locals<br>
+ [if target is Windows and allocated space > 4096 bytes]<br>
+ ; Windows needs special care for allocations larger<br>
+ ; than one page.<br>
+ mov $NNN, %rax<br>
+ call ___chkstk_ms/___chkstk<br>
+ sub %rax, %rsp<br>
+ [else]<br>
+ sub $NNN, %rsp<br>
+<br>
+ [if needs FP]<br>
+ .seh_stackalloc (size of XMM spill slots)<br>
+ .seh_setframe %rbp, SEHFrameOffset ; = size of all spill slots<br>
+ [else]<br>
+ .seh_stackalloc NNN<br>
+<br>
+ ; Spill XMMs<br>
+ ; Note, that while only Windows 64 ABI specifies XMMs as callee-preserved,<br>
+ ; they may get spilled on any platform, if the current function<br>
+ ; calls @llvm.eh.unwind.init<br>
+ [if needs FP]<br>
+ [for all callee-saved XMM registers]<br>
+ movaps %<xmm reg>, -MMM(%rbp)<br>
+ [for all callee-saved XMM registers]<br>
+ .seh_savexmm %<xmm reg>, (-MMM + SEHFrameOffset)<br>
+ ; i.e. the offset relative to (%rbp - SEHFrameOffset)<br>
+ [else]<br>
+ [for all callee-saved XMM registers]<br>
+ movaps %<xmm reg>, KKK(%rsp)<br>
+ [for all callee-saved XMM registers]<br>
+ .seh_savexmm %<xmm reg>, KKK<br>
+<br>
+ .seh_endprologue<br>
+<br>
+ [if needs base pointer]<br>
+ mov %rsp, %rbx<br>
+<br>
+ ; Emit CFI info<br>
+ [if needs FP]<br>
+ [for all callee-saved registers]<br>
+ .cfi_offset %<reg>, (offset from %rbp)<br>
+ [else]<br>
+ .cfi_def_cfa_offset (offset from RETADDR)<br>
+ [for all callee-saved registers]<br>
+ .cfi_offset %<reg>, (offset from %rsp)<br>
+<br>
+ Notes:<br>
+ - .seh directives are emitted only for Windows 64 ABI<br>
+ - .cfi directives are emitted for all other ABIs<br>
+ - for 32-bit code, substitute %e?? registers for %r??<br>
+*/<br>
+<br>
void X86FrameLowering::emitPrologue(MachineFunction &MF) const {<br>
MachineBasicBlock &MBB = MF.front(); // Prologue goes in entry BB.<br>
MachineBasicBlock::iterator MBBI = MBB.begin();<br>
@@ -406,8 +444,6 @@ void X86FrameLowering::emitPrologue(Mach<br>
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();<br>
MachineModuleInfo &MMI = MF.getMMI();<br>
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();<br>
- bool needsFrameMoves = MMI.hasDebugInfo() ||<br>
- Fn->needsUnwindTableEntry();<br>
uint64_t MaxAlign = MFI->getMaxAlignment(); // Desired stack alignment.<br>
uint64_t StackSize = MFI->getStackSize(); // Number of bytes to allocate.<br>
bool HasFP = hasFP(MF);<br>
@@ -415,6 +451,12 @@ void X86FrameLowering::emitPrologue(Mach<br>
bool Is64Bit = STI.is64Bit();<br>
bool IsLP64 = STI.isTarget64BitLP64();<br>
bool IsWin64 = STI.isTargetWin64();<br>
+ bool IsSEH =<br>
+ MF.getTarget().getMCAsmInfo()->getExceptionHandlingType() ==<br>
+ ExceptionHandling::Win64; // Not necessarily synonymous with IsWin64.<br>
+ bool NeedsWin64SEH = IsSEH && Fn->needsUnwindTableEntry();<br>
+ bool NeedsDwarfCFI =<br>
+ !IsSEH && (MMI.hasDebugInfo() || Fn->needsUnwindTableEntry());<br>
bool UseLEA = STI.useLeaForSP();<br>
unsigned StackAlign = getStackAlignment();<br>
unsigned SlotSize = RegInfo->getSlotSize();<br>
@@ -512,7 +554,7 @@ void X86FrameLowering::emitPrologue(Mach<br>
.addReg(FramePtr, RegState::Kill)<br>
.setMIFlag(MachineInstr::FrameSetup);<br>
<br>
- if (needsFrameMoves) {<br>
+ if (NeedsDwarfCFI) {<br>
// Mark the place where EBP/RBP was saved.<br>
// Define the current CFA rule to use the provided offset.<br>
assert(StackSize);<br>
@@ -530,13 +572,19 @@ void X86FrameLowering::emitPrologue(Mach<br>
.addCFIIndex(CFIIndex);<br>
}<br>
<br>
+ if (NeedsWin64SEH) {<br>
+ BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg))<br>
+ .addImm(FramePtr)<br>
+ .setMIFlag(MachineInstr::FrameSetup);<br>
+ }<br>
+<br>
// Update EBP with the new base value.<br>
BuildMI(MBB, MBBI, DL,<br>
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), FramePtr)<br>
.addReg(StackPtr)<br>
.setMIFlag(MachineInstr::FrameSetup);<br>
<br>
- if (needsFrameMoves) {<br>
+ if (NeedsDwarfCFI) {<br>
// Mark effective beginning of when frame pointer becomes valid.<br>
// Define the current CFA to use the EBP/RBP register.<br>
unsigned DwarfFramePtr = RegInfo->getDwarfRegNum(FramePtr, true);<br>
@@ -546,9 +594,8 @@ void X86FrameLowering::emitPrologue(Mach<br>
.addCFIIndex(CFIIndex);<br>
}<br>
<br>
- // Mark the FramePtr as live-in in every block except the entry.<br>
- for (MachineFunction::iterator I = std::next(MF.begin()), E = MF.end();<br>
- I != E; ++I)<br>
+ // Mark the FramePtr as live-in in every block.<br>
+ for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)<br>
I->addLiveIn(FramePtr);<br>
} else {<br>
NumBytes = StackSize - X86FI->getCalleeSavedFrameSize();<br>
@@ -562,10 +609,10 @@ void X86FrameLowering::emitPrologue(Mach<br>
(MBBI->getOpcode() == X86::PUSH32r ||<br>
MBBI->getOpcode() == X86::PUSH64r)) {<br>
PushedRegs = true;<br>
- MBBI->setFlag(MachineInstr::FrameSetup);<br>
+ unsigned Reg = MBBI->getOperand(0).getReg();<br>
++MBBI;<br>
<br>
- if (!HasFP && needsFrameMoves) {<br>
+ if (!HasFP && NeedsDwarfCFI) {<br>
// Mark callee-saved push instruction.<br>
// Define the current CFA rule to use the provided offset.<br>
assert(StackSize);<br>
@@ -575,16 +622,15 @@ void X86FrameLowering::emitPrologue(Mach<br>
.addCFIIndex(CFIIndex);<br>
StackOffset += stackGrowth;<br>
}<br>
+<br>
+ if (NeedsWin64SEH) {<br>
+ BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg)).addImm(Reg).setMIFlag(<br>
+ MachineInstr::FrameSetup);<br>
+ }<br>
}<br>
<br>
// Realign stack after we pushed callee-saved registers (so that we'll be<br>
// able to calculate their offsets from the frame pointer).<br>
-<br>
- // NOTE: We push the registers before realigning the stack, so<br>
- // vector callee-saved (xmm) registers may be saved w/o proper<br>
- // alignment in this way. However, currently these regs are saved in<br>
- // stack slots (see X86FrameLowering::spillCalleeSavedRegisters()), so<br>
- // this shouldn't be a problem.<br>
if (RegInfo->needsStackRealignment(MF)) {<br>
assert(HasFP && "There should be a frame pointer if stack is realigned.");<br>
MachineInstr *MI =<br>
@@ -683,23 +729,85 @@ void X86FrameLowering::emitPrologue(Mach<br>
MI->setFlag(MachineInstr::FrameSetup);<br>
MBB.insert(MBBI, MI);<br>
}<br>
- } else if (NumBytes)<br>
+ } else if (NumBytes) {<br>
emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, IsLP64,<br>
UseLEA, TII, *RegInfo);<br>
+ }<br>
+<br>
+ int SEHFrameOffset = 0;<br>
+ if (NeedsWin64SEH) {<br>
+ if (HasFP) {<br>
+ // We need to set frame base offset low enough such that all saved<br>
+ // register offsets would be positive relative to it, but we can't<br>
+ // just use NumBytes, because .seh_setframe offset must be <=240.<br>
+ // So we pretend to have only allocated enough space to spill the<br>
+ // non-volatile registers.<br>
+ // We don't care about the rest of stack allocation, because unwinder<br>
+ // will restore SP to (BP - SEHFrameOffset)<br>
+ for (const CalleeSavedInfo &Info : MFI->getCalleeSavedInfo()) {<br>
+ int offset = MFI->getObjectOffset(Info.getFrameIdx());<br>
+ SEHFrameOffset = std::max(SEHFrameOffset, abs(offset));<br>
+ }<br>
+ SEHFrameOffset += SEHFrameOffset % 16; // ensure alignmant<br>
+<br>
+ // This only needs to account for XMM spill slots, GPR slots<br>
+ // are covered by .seh_pushreg's emitted above.<br>
+ BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_StackAlloc))<br>
+ .addImm(SEHFrameOffset - X86FI->getCalleeSavedFrameSize())<br>
+ .setMIFlag(MachineInstr::FrameSetup);<br>
+<br>
+ BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SetFrame))<br>
+ .addImm(FramePtr)<br>
+ .addImm(SEHFrameOffset)<br>
+ .setMIFlag(MachineInstr::FrameSetup);<br>
+ } else {<br>
+ // SP will be the base register for restoring XMMs<br>
+ if (NumBytes) {<br>
+ BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_StackAlloc))<br>
+ .addImm(NumBytes)<br>
+ .setMIFlag(MachineInstr::FrameSetup);<br>
+ }<br>
+ }<br>
+ }<br>
+<br>
+ // Skip the rest of register spilling code<br>
+ while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup))<br>
+ ++MBBI;<br>
+<br>
+ // Emit SEH info for non-GPRs<br>
+ if (NeedsWin64SEH) {<br>
+ for (const CalleeSavedInfo &Info : MFI->getCalleeSavedInfo()) {<br>
+ unsigned Reg = Info.getReg();<br>
+ if (X86::GR64RegClass.contains(Reg) || X86::GR32RegClass.contains(Reg))<br>
+ continue;<br>
+ assert(X86::FR64RegClass.contains(Reg) && "Unexpected register class");<br>
+<br>
+ int Offset = getFrameIndexOffset(MF, Info.getFrameIdx());<br>
+ Offset += SEHFrameOffset;<br>
+<br>
+ BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SaveXMM))<br>
+ .addImm(Reg)<br>
+ .addImm(Offset)<br>
+ .setMIFlag(MachineInstr::FrameSetup);<br>
+ }<br>
+<br>
+ BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_EndPrologue))<br>
+ .setMIFlag(MachineInstr::FrameSetup);<br>
+ }<br>
<br>
// If we need a base pointer, set it up here. It's whatever the value<br>
// of the stack pointer is at this point. Any variable size objects<br>
// will be allocated after this, so we can still use the base pointer<br>
// to reference locals.<br>
if (RegInfo->hasBasePointer(MF)) {<br>
- // Update the frame pointer with the current stack pointer.<br>
+ // Update the base pointer with the current stack pointer.<br>
unsigned Opc = Is64Bit ? X86::MOV64rr : X86::MOV32rr;<br>
BuildMI(MBB, MBBI, DL, TII.get(Opc), BasePtr)<br>
.addReg(StackPtr)<br>
.setMIFlag(MachineInstr::FrameSetup);<br>
}<br>
<br>
- if (( (!HasFP && NumBytes) || PushedRegs) && needsFrameMoves) {<br>
+ if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {<br>
// Mark end of stack pointer adjustment.<br>
if (!HasFP && NumBytes) {<br>
// Define the current CFA rule to use the provided offset.<br>
@@ -714,7 +822,7 @@ void X86FrameLowering::emitPrologue(Mach<br>
<br>
// Emit DWARF info specifying the offsets of the callee-saved registers.<br>
if (PushedRegs)<br>
- emitCalleeSavedFrameMoves(MBB, MBBI, DL, HasFP ? FramePtr : StackPtr);<br>
+ emitCalleeSavedFrameMoves(MBB, MBBI, DL);<br>
}<br>
}<br>
<br>
@@ -974,24 +1082,79 @@ int X86FrameLowering::getFrameIndexRefer<br>
return getFrameIndexOffset(MF, FI);<br>
}<br>
<br>
-bool X86FrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,<br>
- MachineBasicBlock::iterator MI,<br>
- const std::vector<CalleeSavedInfo> &CSI,<br>
- const TargetRegisterInfo *TRI) const {<br>
- if (CSI.empty())<br>
- return false;<br>
+bool X86FrameLowering::assignCalleeSavedSpillSlots(<br>
+ MachineFunction &MF, const TargetRegisterInfo *TRI,<br>
+ std::vector<CalleeSavedInfo> &CSI) const {<br>
+ MachineFrameInfo *MFI = MF.getFrameInfo();<br>
+ const X86RegisterInfo *RegInfo =<br>
+ static_cast<const X86RegisterInfo *>(MF.getTarget().getRegisterInfo());<br>
+ unsigned SlotSize = RegInfo->getSlotSize();<br>
+ X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();<br>
+<br>
+ unsigned CalleeSavedFrameSize = 0;<br>
+ int SpillSlotOffset = getOffsetOfLocalArea() + X86FI->getTCReturnAddrDelta();<br>
+<br>
+ if (hasFP(MF)) {<br>
+ // emitPrologue always spills frame register the first thing.<br>
+ SpillSlotOffset -= SlotSize;<br>
+ MFI->CreateFixedSpillStackObject(SlotSize, SpillSlotOffset);<br>
+<br>
+ // Since emitPrologue and emitEpilogue will handle spilling and restoring of<br>
+ // the frame register, we can delete it from CSI list and not have to worry<br>
+ // about avoiding it later.<br>
+ unsigned FPReg = RegInfo->getFrameRegister(MF);<br>
+ for (unsigned i = 0; i < CSI.size(); ++i) {<br>
+ if (CSI[i].getReg() == FPReg) {<br>
+ CSI.erase(CSI.begin() + i);<br>
+ break;<br>
+ }<br>
+ }<br>
+ }<br>
+<br>
+ // Assign slots for GPRs. It increases frame size.<br>
+ for (unsigned i = CSI.size(); i != 0; --i) {<br>
+ unsigned Reg = CSI[i - 1].getReg();<br>
+<br>
+ if (!X86::GR64RegClass.contains(Reg) && !X86::GR32RegClass.contains(Reg))<br>
+ continue;<br>
+<br>
+ SpillSlotOffset -= SlotSize;<br>
+ CalleeSavedFrameSize += SlotSize;<br>
+<br>
+ int SlotIndex = MFI->CreateFixedSpillStackObject(SlotSize, SpillSlotOffset);<br>
+ CSI[i - 1].setFrameIdx(SlotIndex);<br>
+ }<br>
+<br>
+ X86FI->setCalleeSavedFrameSize(CalleeSavedFrameSize);<br>
<br>
+ // Assign slots for XMMs.<br>
+ for (unsigned i = CSI.size(); i != 0; --i) {<br>
+ unsigned Reg = CSI[i - 1].getReg();<br>
+ if (X86::GR64RegClass.contains(Reg) || X86::GR32RegClass.contains(Reg))<br>
+ continue;<br>
+<br>
+ const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg);<br>
+ // ensure alignment<br>
+ SpillSlotOffset -= abs(SpillSlotOffset) % RC->getAlignment();<br>
+ // spill into slot<br>
+ SpillSlotOffset -= RC->getSize();<br>
+ int SlotIndex =<br>
+ MFI->CreateFixedSpillStackObject(RC->getSize(), SpillSlotOffset);<br>
+ CSI[i - 1].setFrameIdx(SlotIndex);<br>
+ MFI->ensureMaxAlignment(RC->getAlignment());<br>
+ }<br>
+<br>
+ return true;<br>
+}<br>
+<br>
+bool X86FrameLowering::spillCalleeSavedRegisters(<br>
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,<br>
+ const std::vector<CalleeSavedInfo> &CSI,<br>
+ const TargetRegisterInfo *TRI) const {<br>
DebugLoc DL = MBB.findDebugLoc(MI);<br>
<br>
MachineFunction &MF = *MBB.getParent();<br>
- const X86RegisterInfo *RegInfo =<br>
- static_cast<const X86RegisterInfo *>(MF.getTarget().getRegisterInfo());<br>
- unsigned SlotSize = RegInfo->getSlotSize();<br>
- unsigned FPReg = TRI->getFrameRegister(MF);<br>
- unsigned CalleeFrameSize = 0;<br>
-<br>
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();<br>
- X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();<br>
const X86Subtarget &STI = MF.getTarget().getSubtarget<X86Subtarget>();<br>
<br>
// Push GPRs. It increases frame size.<br>
@@ -1003,19 +1166,13 @@ bool X86FrameLowering::spillCalleeSavedR<br>
continue;<br>
// Add the callee-saved register as live-in. It's killed at the spill.<br>
MBB.addLiveIn(Reg);<br>
- if (Reg == FPReg)<br>
- // X86RegisterInfo::emitPrologue will handle spilling of frame register.<br>
- continue;<br>
- CalleeFrameSize += SlotSize;<br>
+<br>
BuildMI(MBB, MI, DL, TII.get(Opc)).addReg(Reg, RegState::Kill)<br>
.setMIFlag(MachineInstr::FrameSetup);<br>
}<br>
<br>
- X86FI->setCalleeSavedFrameSize(CalleeFrameSize);<br>
-<br>
// Make XMM regs spilled. X86 does not have ability of push/pop XMM.<br>
// It can be done by spilling XMMs to stack frame.<br>
- // Note that only Win64 ABI might spill XMMs.<br>
for (unsigned i = CSI.size(); i != 0; --i) {<br>
unsigned Reg = CSI[i-1].getReg();<br>
if (X86::GR64RegClass.contains(Reg) ||<br>
@@ -1027,6 +1184,9 @@ bool X86FrameLowering::spillCalleeSavedR<br>
<br>
TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i - 1].getFrameIdx(), RC,<br>
TRI);<br>
+ --MI;<br>
+ MI->setFlag(MachineInstr::FrameSetup);<br>
+ ++MI;<br>
}<br>
<br>
return true;<br>
@@ -1057,16 +1217,13 @@ bool X86FrameLowering::restoreCalleeSave<br>
}<br>
<br>
// POP GPRs.<br>
- unsigned FPReg = TRI->getFrameRegister(MF);<br>
unsigned Opc = STI.is64Bit() ? X86::POP64r : X86::POP32r;<br>
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {<br>
unsigned Reg = CSI[i].getReg();<br>
if (!X86::GR64RegClass.contains(Reg) &&<br>
!X86::GR32RegClass.contains(Reg))<br>
continue;<br>
- if (Reg == FPReg)<br>
- // X86RegisterInfo::emitEpilogue will handle restoring of frame register.<br>
- continue;<br>
+<br>
BuildMI(MBB, MI, DL, TII.get(Opc), Reg);<br>
}<br>
return true;<br>
@@ -1097,22 +1254,6 @@ X86FrameLowering::processFunctionBeforeC<br>
TailCallReturnAddrDelta - SlotSize, true);<br>
}<br>
<br>
- if (hasFP(MF)) {<br>
- assert((TailCallReturnAddrDelta <= 0) &&<br>
- "The Delta should always be zero or negative");<br>
- const TargetFrameLowering &TFI = *MF.getTarget().getFrameLowering();<br>
-<br>
- // Create a frame entry for the EBP register that must be saved.<br>
- int FrameIdx = MFI->CreateFixedObject(SlotSize,<br>
- -(int)SlotSize +<br>
- TFI.getOffsetOfLocalArea() +<br>
- TailCallReturnAddrDelta,<br>
- true);<br>
- assert(FrameIdx == MFI->getObjectIndexBegin() &&<br>
- "Slot for EBP register must be last in order to be found!");<br>
- (void)FrameIdx;<br>
- }<br>
-<br>
// Spill the BasePtr if it's used.<br>
if (RegInfo->hasBasePointer(MF))<br>
MF.getRegInfo().setPhysRegUsed(RegInfo->getBaseRegister());<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86FrameLowering.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FrameLowering.h?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FrameLowering.h?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86FrameLowering.h (original)<br>
+++ llvm/trunk/lib/Target/X86/X86FrameLowering.h Wed Jun 25 07:41:52 2014<br>
@@ -27,8 +27,8 @@ public:<br>
: TargetFrameLowering(StackGrowsDown, StackAl, LAO) {}<br>
<br>
void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB,<br>
- MachineBasicBlock::iterator MBBI, DebugLoc DL,<br>
- unsigned FramePtr) const;<br>
+ MachineBasicBlock::iterator MBBI,<br>
+ DebugLoc DL) const;<br>
<br>
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into<br>
/// the function.<br>
@@ -42,6 +42,11 @@ public:<br>
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,<br>
RegScavenger *RS = nullptr) const override;<br>
<br>
+ bool<br>
+ assignCalleeSavedSpillSlots(MachineFunction &MF,<br>
+ const TargetRegisterInfo *TRI,<br>
+ std::vector<CalleeSavedInfo> &CSI) const override;<br>
+<br>
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,<br>
MachineBasicBlock::iterator MI,<br>
const std::vector<CalleeSavedInfo> &CSI,<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Wed Jun 25 07:41:52 2014<br>
@@ -605,9 +605,8 @@ void X86TargetLowering::resetOperationAc<br>
}<br>
<br>
// FIXME - use subtarget debug flags<br>
- if (!Subtarget->isTargetDarwin() &&<br>
- !Subtarget->isTargetELF() &&<br>
- !Subtarget->isTargetCygMing()) {<br>
+ if (!Subtarget->isTargetDarwin() && !Subtarget->isTargetELF() &&<br>
+ !Subtarget->isTargetCygMing() && !Subtarget->isTargetWin64()) {<br>
setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);<br>
}<br>
<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86InstrCompiler.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrCompiler.td?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrCompiler.td?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86InstrCompiler.td (original)<br>
+++ llvm/trunk/lib/Target/X86/X86InstrCompiler.td Wed Jun 25 07:41:52 2014<br>
@@ -197,6 +197,26 @@ let isBranch = 1, isTerminator = 1, isCo<br>
}<br>
<br>
//===----------------------------------------------------------------------===//<br>
+// Pseudo instructions used by unwind info.<br>
+//<br>
+let isPseudo = 1 in {<br>
+ def SEH_PushReg : I<0, Pseudo, (outs), (ins i32imm:$reg),<br>
+ "#SEH_PushReg $reg", []>;<br>
+ def SEH_SaveReg : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst),<br>
+ "#SEH_SaveReg $reg, $dst", []>;<br>
+ def SEH_SaveXMM : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst),<br>
+ "#SEH_SaveXMM $reg, $dst", []>;<br>
+ def SEH_StackAlloc : I<0, Pseudo, (outs), (ins i32imm:$size),<br>
+ "#SEH_StackAlloc $size", []>;<br>
+ def SEH_SetFrame : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$offset),<br>
+ "#SEH_SetFrame $reg, $offset", []>;<br>
+ def SEH_PushFrame : I<0, Pseudo, (outs), (ins i1imm:$mode),<br>
+ "#SEH_PushFrame $mode", []>;<br>
+ def SEH_EndPrologue : I<0, Pseudo, (outs), (ins),<br>
+ "#SEH_EndPrologue", []>;<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
// Pseudo instructions used by segmented stacks.<br>
//<br>
<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86MCInstLower.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MCInstLower.cpp?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MCInstLower.cpp?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86MCInstLower.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86MCInstLower.cpp Wed Jun 25 07:41:52 2014<br>
@@ -13,6 +13,7 @@<br>
//===----------------------------------------------------------------------===//<br>
<br>
#include "X86AsmPrinter.h"<br>
+#include "X86RegisterInfo.h"<br>
#include "InstPrinter/X86ATTInstPrinter.h"<br>
#include "MCTargetDesc/X86BaseInfo.h"<br>
#include "llvm/ADT/SmallString.h"<br>
@@ -779,6 +780,9 @@ static void LowerPATCHPOINT(MCStreamer &<br>
<br>
void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {<br>
X86MCInstLower MCInstLowering(*MF, *this);<br>
+ const X86RegisterInfo *RI =<br>
+ static_cast<const X86RegisterInfo *>(TM.getRegisterInfo());<br>
+<br>
switch (MI->getOpcode()) {<br>
case TargetOpcode::DBG_VALUE:<br>
llvm_unreachable("Should be handled target independently");<br>
@@ -883,6 +887,39 @@ void X86AsmPrinter::EmitInstruction(cons<br>
.addReg(X86::R10)<br>
.addReg(X86::RAX));<br>
return;<br>
+<br>
+ case X86::SEH_PushReg:<br>
+ OutStreamer.EmitWin64EHPushReg(<br>
+ RI->getSEHRegNum(MI->getOperand(0).getImm()));<br>
+ return;<br>
+<br>
+ case X86::SEH_SaveReg:<br>
+ OutStreamer.EmitWin64EHSaveReg(RI->getSEHRegNum(MI->getOperand(0).getImm()),<br>
+ MI->getOperand(1).getImm());<br>
+ return;<br>
+<br>
+ case X86::SEH_SaveXMM:<br>
+ OutStreamer.EmitWin64EHSaveXMM(RI->getSEHRegNum(MI->getOperand(0).getImm()),<br>
+ MI->getOperand(1).getImm());<br>
+ return;<br>
+<br>
+ case X86::SEH_StackAlloc:<br>
+ OutStreamer.EmitWin64EHAllocStack(MI->getOperand(0).getImm());<br>
+ return;<br>
+<br>
+ case X86::SEH_SetFrame:<br>
+ OutStreamer.EmitWin64EHSetFrame(<br>
+ RI->getSEHRegNum(MI->getOperand(0).getImm()),<br>
+ MI->getOperand(1).getImm());<br>
+ return;<br>
+<br>
+ case X86::SEH_PushFrame:<br>
+ OutStreamer.EmitWin64EHPushFrame(MI->getOperand(0).getImm());<br>
+ return;<br>
+<br>
+ case X86::SEH_EndPrologue:<br>
+ OutStreamer.EmitWin64EHEndProlog();<br>
+ return;<br>
}<br>
<br>
MCInst TmpInst;<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll Wed Jun 25 07:41:52 2014<br>
@@ -1,12 +1,14 @@<br>
; RUN: llc < %s -mtriple=i686-pc-linux-gnu -o - | FileCheck %s --check-prefix=LIN<br>
-; RUN: llc < %s -mtriple=x86_64-pc-windows-gnu -o - | FileCheck %s --check-prefix=LIN<br>
; RUN: llc < %s -mtriple=i386-pc-mingw32 -o - | FileCheck %s --check-prefix=WIN<br>
; RUN: llc < %s -mtriple=i686-pc-windows-gnu -o - | FileCheck %s --check-prefix=WIN<br>
+; RUN: llc < %s -mtriple=x86_64-pc-windows-gnu -o - | FileCheck %s --check-prefix=WIN64<br>
<br>
; LIN: .cfi_personality 0, __gnat_eh_personality<br>
; LIN: .cfi_lsda 0, .Lexception0<br>
; WIN: .cfi_personality 0, ___gnat_eh_personality<br>
; WIN: .cfi_lsda 0, Lexception0<br>
+; WIN64: .seh_handler __gnat_eh_personality<br>
+; WIN64: .seh_handlerdata<br>
<br>
@error = external global i8<br>
<br>
@@ -15,7 +17,7 @@ entry:<br>
invoke void @raise()<br>
to label %eh_then unwind label %unwind<br>
<br>
-unwind: ; preds = %entry<br>
+unwind: ; preds = %entry<br>
%eh_ptr = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*)<br>
catch i8* @error<br>
%eh_select = extractvalue { i8*, i32 } %eh_ptr, 1<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/2009-06-03-Win64SpillXMM.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-06-03-Win64SpillXMM.ll?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-06-03-Win64SpillXMM.ll?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/2009-06-03-Win64SpillXMM.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/2009-06-03-Win64SpillXMM.ll Wed Jun 25 07:41:52 2014<br>
@@ -1,7 +1,7 @@<br>
; RUN: llc -mcpu=generic -mtriple=x86_64-mingw32 < %s | FileCheck %s<br>
; CHECK: subq $40, %rsp<br>
-; CHECK: movaps %xmm8, (%rsp)<br>
-; CHECK: movaps %xmm7, 16(%rsp)<br>
+; CHECK: movaps %xmm8, 16(%rsp)<br>
+; CHECK: movaps %xmm7, (%rsp)<br>
<br>
define i32 @a() nounwind {<br>
entry:<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/avx-intel-ocl.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-intel-ocl.ll?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-intel-ocl.ll?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/avx-intel-ocl.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/avx-intel-ocl.ll Wed Jun 25 07:41:52 2014<br>
@@ -7,21 +7,21 @@ declare <16 x float> @func_float16_ptr(<<br>
declare <16 x float> @func_float16(<16 x float>, <16 x float>)<br>
declare i32 @func_int(i32, i32)<br>
<br>
-; WIN64: testf16_inp<br>
+; WIN64-LABEL: testf16_inp<br>
; WIN64: vaddps {{.*}}, {{%ymm[0-1]}}<br>
; WIN64: vaddps {{.*}}, {{%ymm[0-1]}}<br>
; WIN64: leaq {{.*}}(%rsp), %rcx<br>
; WIN64: call<br>
; WIN64: ret<br>
<br>
-; X32: testf16_inp<br>
+; X32-LABEL: testf16_inp<br>
; X32: movl %eax, (%esp)<br>
; X32: vaddps {{.*}}, {{%ymm[0-1]}}<br>
; X32: vaddps {{.*}}, {{%ymm[0-1]}}<br>
; X32: call<br>
; X32: ret<br>
<br>
-; X64: testf16_inp<br>
+; X64-LABEL: testf16_inp<br>
; X64: vaddps {{.*}}, {{%ymm[0-1]}}<br>
; X64: vaddps {{.*}}, {{%ymm[0-1]}}<br>
; X64: leaq {{.*}}(%rsp), %rdi<br>
@@ -41,14 +41,14 @@ define <16 x float> @testf16_inp(<16 x f<br>
;test calling conventions - preserved registers<br>
<br>
; preserved ymm6-ymm15<br>
-; WIN64: testf16_regs<br>
+; WIN64-LABEL: testf16_regs<br>
; WIN64: call<br>
; WIN64: vaddps {{%ymm[6-7]}}, {{%ymm[0-1]}}, {{%ymm[0-1]}}<br>
; WIN64: vaddps {{%ymm[6-7]}}, {{%ymm[0-1]}}, {{%ymm[0-1]}}<br>
; WIN64: ret<br>
<br>
; preserved ymm8-ymm15<br>
-; X64: testf16_regs<br>
+; X64-LABEL: testf16_regs<br>
; X64: call<br>
; X64: vaddps {{%ymm[8-9]}}, {{%ymm[0-1]}}, {{%ymm[0-1]}}<br>
; X64: vaddps {{%ymm[8-9]}}, {{%ymm[0-1]}}, {{%ymm[0-1]}}<br>
@@ -65,28 +65,30 @@ define <16 x float> @testf16_regs(<16 x<br>
}<br>
<br>
; test calling conventions - prolog and epilog<br>
-; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rsp).*}} # 32-byte Spill<br>
-; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rsp).*}} # 32-byte Spill<br>
-; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rsp).*}} # 32-byte Spill<br>
-; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rsp).*}} # 32-byte Spill<br>
-; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rsp).*}} # 32-byte Spill<br>
-; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rsp).*}} # 32-byte Spill<br>
-; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rsp).*}} # 32-byte Spill<br>
-; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rsp).*}} # 32-byte Spill<br>
-; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rsp).*}} # 32-byte Spill<br>
-; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rsp).*}} # 32-byte Spill<br>
+; WIN64-LABEL: test_prolog_epilog<br>
+; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rbp).*}} # 32-byte Spill<br>
+; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rbp).*}} # 32-byte Spill<br>
+; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rbp).*}} # 32-byte Spill<br>
+; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rbp).*}} # 32-byte Spill<br>
+; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rbp).*}} # 32-byte Spill<br>
+; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rbp).*}} # 32-byte Spill<br>
+; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rbp).*}} # 32-byte Spill<br>
+; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rbp).*}} # 32-byte Spill<br>
+; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rbp).*}} # 32-byte Spill<br>
+; WIN64: vmovaps {{%ymm([6-9]|1[0-5])}}, {{.*(%rbp).*}} # 32-byte Spill<br>
; WIN64: call<br>
-; WIN64: vmovaps {{.*(%rsp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
-; WIN64: vmovaps {{.*(%rsp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
-; WIN64: vmovaps {{.*(%rsp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
-; WIN64: vmovaps {{.*(%rsp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
-; WIN64: vmovaps {{.*(%rsp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
-; WIN64: vmovaps {{.*(%rsp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
-; WIN64: vmovaps {{.*(%rsp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
-; WIN64: vmovaps {{.*(%rsp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
-; WIN64: vmovaps {{.*(%rsp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
-; WIN64: vmovaps {{.*(%rsp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
+; WIN64: vmovaps {{.*(%rbp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
+; WIN64: vmovaps {{.*(%rbp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
+; WIN64: vmovaps {{.*(%rbp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
+; WIN64: vmovaps {{.*(%rbp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
+; WIN64: vmovaps {{.*(%rbp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
+; WIN64: vmovaps {{.*(%rbp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
+; WIN64: vmovaps {{.*(%rbp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
+; WIN64: vmovaps {{.*(%rbp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
+; WIN64: vmovaps {{.*(%rbp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
+; WIN64: vmovaps {{.*(%rbp).*}}, {{%ymm([6-9]|1[0-5])}} # 32-byte Reload<br>
<br>
+; X64-LABEL: test_prolog_epilog<br>
; X64: vmovups {{%ymm([8-9]|1[0-5])}}, {{.*}}(%rsp) ## 32-byte Folded Spill<br>
; X64: vmovups {{%ymm([8-9]|1[0-5])}}, {{.*}}(%rsp) ## 32-byte Folded Spill<br>
; X64: vmovups {{%ymm([8-9]|1[0-5])}}, {{.*}}(%rsp) ## 32-byte Folded Spill<br>
@@ -111,12 +113,14 @@ define intel_ocl_bicc <16 x float> @test<br>
<br>
; test functions with integer parameters<br>
; pass parameters on stack for 32-bit platform<br>
+; X32-LABEL: test_int<br>
; X32: movl {{.*}}, 4(%esp)<br>
; X32: movl {{.*}}, (%esp)<br>
; X32: call<br>
; X32: addl {{.*}}, %eax<br>
<br>
; pass parameters in registers for 64-bit platform<br>
+; X64-LABEL: test_int<br>
; X64: leal {{.*}}, %edi<br>
; X64: movl {{.*}}, %esi<br>
; X64: call<br>
@@ -128,21 +132,21 @@ define i32 @test_int(i32 %a, i32 %b) nou<br>
ret i32 %c<br>
}<br>
<br>
-; WIN64: test_float4<br>
+; WIN64-LABEL: test_float4<br>
; WIN64-NOT: vzeroupper<br>
; WIN64: call<br>
; WIN64-NOT: vzeroupper<br>
; WIN64: call<br>
; WIN64: ret<br>
<br>
-; X64: test_float4<br>
+; X64-LABEL: test_float4<br>
; X64-NOT: vzeroupper<br>
; X64: call<br>
; X64-NOT: vzeroupper<br>
; X64: call<br>
; X64: ret<br>
<br>
-; X32: test_float4<br>
+; X32-LABEL: test_float4<br>
; X32: vzeroupper<br>
; X32: call<br>
; X32: vzeroupper<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/gcc_except_table.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/gcc_except_table.ll?rev=211691&r1=211690&r2=211691&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/gcc_except_table.ll?rev=211691&r1=211690&r2=211691&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/gcc_except_table.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/gcc_except_table.ll Wed Jun 25 07:41:52 2014<br>
@@ -13,14 +13,14 @@ define i32 @main() uwtable optsize ssp {<br>
; APPLE: GCC_except_table0:<br>
; APPLE: Lexception0:<br>
<br>
-; MINGW64: .cfi_startproc<br>
-; MINGW64: .cfi_personality 0, __gxx_personality_v0<br>
-; MINGW64: .cfi_lsda 0, .Lexception0<br>
-; MINGW64: .cfi_def_cfa_offset 16<br>
+; MINGW64: .seh_proc<br>
+; MINGW64: .seh_handler __gxx_personality_v0<br>
+; MINGW64: .seh_setframe 5, 0<br>
; MINGW64: callq _Unwind_Resume<br>
-; MINGW64: .cfi_endproc<br>
+; MINGW64: .seh_handlerdata<br>
; MINGW64: GCC_except_table0:<br>
; MINGW64: Lexception0:<br>
+; MINGW64: .seh_endproc<br>
<br>
; MINGW32: .cfi_startproc<br>
; MINGW32: .cfi_personality 0, ___gxx_personality_v0<br>
<br>
Added: llvm/trunk/test/CodeGen/X86/win64_eh.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win64_eh.ll?rev=211691&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win64_eh.ll?rev=211691&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/win64_eh.ll (added)<br>
+++ llvm/trunk/test/CodeGen/X86/win64_eh.ll Wed Jun 25 07:41:52 2014<br>
@@ -0,0 +1,170 @@<br>
+; RUN: llc < %s -O0 -mcpu=corei7 -mtriple=x86_64-pc-win32 | FileCheck %s -check-prefix=WIN64<br>
+; RUN: llc < %s -O0 -mcpu=corei7 -mtriple=x86_64-pc-mingw32 | FileCheck %s -check-prefix=WIN64<br>
+<br>
+; Check function without prolog<br>
+define void @foo0() uwtable {<br>
+entry:<br>
+ ret void<br>
+}<br>
+; WIN64-LABEL: foo0:<br>
+; WIN64: .seh_proc foo0<br>
+; WIN64: .seh_endprologue<br>
+; WIN64: ret<br>
+; WIN64: .seh_endproc<br>
+<br>
+; Checks a small stack allocation<br>
+define void @foo1() uwtable {<br>
+entry:<br>
+ %baz = alloca [2000 x i16], align 2<br>
+ ret void<br>
+}<br>
+; WIN64-LABEL: foo1:<br>
+; WIN64: .seh_proc foo1<br>
+; WIN64: subq $4000, %rsp<br>
+; WIN64: .seh_stackalloc 4000<br>
+; WIN64: .seh_endprologue<br>
+; WIN64: addq $4000, %rsp<br>
+; WIN64: ret<br>
+; WIN64: .seh_endproc<br>
+<br>
+; Checks a stack allocation requiring call to __chkstk/___chkstk_ms<br>
+define void @foo2() uwtable {<br>
+entry:<br>
+ %baz = alloca [4000 x i16], align 2<br>
+ ret void<br>
+}<br>
+; WIN64-LABEL: foo2:<br>
+; WIN64: .seh_proc foo2<br>
+; WIN64: movabsq $8000, %rax<br>
+; WIN64: callq {{__chkstk|___chkstk_ms}}<br>
+; WIN64: subq %rax, %rsp<br>
+; WIN64: .seh_stackalloc 8000<br>
+; WIN64: .seh_endprologue<br>
+; WIN64: addq $8000, %rsp<br>
+; WIN64: ret<br>
+; WIN64: .seh_endproc<br>
+<br>
+<br>
+; Checks stack push<br>
+define i32 @foo3(i32 %f_arg, i32 %e_arg, i32 %d_arg, i32 %c_arg, i32 %b_arg, i32 %a_arg) uwtable {<br>
+entry:<br>
+ %a = alloca i32<br>
+ %b = alloca i32<br>
+ %c = alloca i32<br>
+ %d = alloca i32<br>
+ %e = alloca i32<br>
+ %f = alloca i32<br>
+ store i32 %a_arg, i32* %a<br>
+ store i32 %b_arg, i32* %b<br>
+ store i32 %c_arg, i32* %c<br>
+ store i32 %d_arg, i32* %d<br>
+ store i32 %e_arg, i32* %e<br>
+ store i32 %f_arg, i32* %f<br>
+ %tmp = load i32* %a<br>
+ %tmp1 = mul i32 %tmp, 2<br>
+ %tmp2 = load i32* %b<br>
+ %tmp3 = mul i32 %tmp2, 3<br>
+ %tmp4 = add i32 %tmp1, %tmp3<br>
+ %tmp5 = load i32* %c<br>
+ %tmp6 = mul i32 %tmp5, 5<br>
+ %tmp7 = add i32 %tmp4, %tmp6<br>
+ %tmp8 = load i32* %d<br>
+ %tmp9 = mul i32 %tmp8, 7<br>
+ %tmp10 = add i32 %tmp7, %tmp9<br>
+ %tmp11 = load i32* %e<br>
+ %tmp12 = mul i32 %tmp11, 11<br>
+ %tmp13 = add i32 %tmp10, %tmp12<br>
+ %tmp14 = load i32* %f<br>
+ %tmp15 = mul i32 %tmp14, 13<br>
+ %tmp16 = add i32 %tmp13, %tmp15<br>
+ ret i32 %tmp16<br>
+}<br>
+; WIN64-LABEL: foo3:<br>
+; WIN64: .seh_proc foo3<br>
+; WIN64: pushq %rsi<br>
+; WIN64: .seh_pushreg 6<br>
+; WIN64: subq $24, %rsp<br>
+; WIN64: .seh_stackalloc 24<br>
+; WIN64: .seh_endprologue<br>
+; WIN64: addq $24, %rsp<br>
+; WIN64: popq %rsi<br>
+; WIN64: ret<br>
+; WIN64: .seh_endproc<br>
+<br>
+<br>
+; Check emission of eh handler and handler data<br>
+declare i32 @_d_eh_personality(i32, i32, i64, i8*, i8*)<br>
+declare void @_d_eh_resume_unwind(i8*)<br>
+<br>
+declare i32 @bar()<br>
+<br>
+define i32 @foo4() #0 {<br>
+entry:<br>
+ %step = alloca i32, align 4<br>
+ store i32 0, i32* %step<br>
+ %tmp = load i32* %step<br>
+<br>
+ %tmp1 = invoke i32 @bar()<br>
+ to label %finally unwind label %landingpad<br>
+<br>
+finally:<br>
+ store i32 1, i32* %step<br>
+ br label %endtryfinally<br>
+<br>
+landingpad:<br>
+ %landing_pad = landingpad { i8*, i32 } personality i32 (i32, i32, i64, i8*, i8*)* @_d_eh_personality<br>
+ cleanup<br>
+ %tmp3 = extractvalue { i8*, i32 } %landing_pad, 0<br>
+ store i32 2, i32* %step<br>
+ call void @_d_eh_resume_unwind(i8* %tmp3)<br>
+ unreachable<br>
+<br>
+endtryfinally:<br>
+ %tmp10 = load i32* %step<br>
+ ret i32 %tmp10<br>
+}<br>
+; WIN64-LABEL: foo4:<br>
+; WIN64: .seh_proc foo4<br>
+; WIN64: .seh_handler _d_eh_personality, @unwind, @except<br>
+; WIN64: subq $56, %rsp<br>
+; WIN64: .seh_stackalloc 56<br>
+; WIN64: .seh_endprologue<br>
+; WIN64: addq $56, %rsp<br>
+; WIN64: ret<br>
+; WIN64: .seh_handlerdata<br>
+; WIN64: .seh_endproc<br>
+<br>
+<br>
+; Check stack re-alignment and xmm spilling<br>
+define void @foo5() uwtable {<br>
+entry:<br>
+ %s = alloca i32, align 64<br>
+ call void asm sideeffect "", "~{rbx},~{rdi},~{xmm6},~{xmm7}"()<br>
+ ret void<br>
+}<br>
+; WIN64-LABEL: foo5:<br>
+; WIN64: .seh_proc foo5<br>
+; WIN64: pushq %rbp<br>
+; WIN64: .seh_pushreg 5<br>
+; WIN64: movq %rsp, %rbp<br>
+; WIN64: pushq %rdi<br>
+; WIN64: .seh_pushreg 7<br>
+; WIN64: pushq %rbx<br>
+; WIN64: .seh_pushreg 3<br>
+; WIN64: andq $-64, %rsp<br>
+; WIN64: subq $128, %rsp<br>
+; WIN64: .seh_stackalloc 48<br>
+; WIN64: .seh_setframe 5, 64<br>
+; WIN64: movaps %xmm7, -32(%rbp) # 16-byte Spill<br>
+; WIN64: movaps %xmm6, -48(%rbp) # 16-byte Spill<br>
+; WIN64: .seh_savexmm 6, 16<br>
+; WIN64: .seh_savexmm 7, 32<br>
+; WIN64: .seh_endprologue<br>
+; WIN64: movaps -48(%rbp), %xmm6 # 16-byte Reload<br>
+; WIN64: movaps -32(%rbp), %xmm7 # 16-byte Reload<br>
+; WIN64: leaq -16(%rbp), %rsp<br>
+; WIN64: popq %rbx<br>
+; WIN64: popq %rdi<br>
+; WIN64: popq %rbp<br>
+; WIN64: retq<br>
+; WIN64: .seh_endproc<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>