<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>