<div dir="ltr">Should be fixed after r315600, sorry for the slow forward fix.</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 12, 2017 at 8:51 AM, Matt Morehouse <span dir="ltr"><<a href="mailto:mascasa@google.com" target="_blank">mascasa@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Reid,<div><br></div><div>This appears to still be causing the <a href="http://lab.llvm.org:8011/builders/sanitizer-windows/builds/18019" target="_blank">Windows sanitizer bot</a> to fail, albeit with a different error after your attempted fixes.  Now we're getting:</div><div><span style="color:rgb(0,0,0);font-family:"Courier New",courier,monotype,monospace;font-size:medium"><br></span></div><div><span style="color:rgb(0,0,0);font-family:"Courier New",courier,monotype,monospace;font-size:medium">fatal error: error in backend: no FPO data found for symbol ?ThrowAndCatch@@YAXXZ</span><br></div><div><span style="color:rgb(0,0,0);font-family:"Courier New",courier,monotype,monospace;font-size:medium"><br></span></div><div>Could you please take another look and/or revert?</div><div><br></div><div>Thanks,</div><div>Matt</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 11, 2017 at 2:24 PM, Reid Kleckner via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rnk<br>
Date: Wed Oct 11 14:24:33 2017<br>
New Revision: 315513<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=315513&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=315513&view=rev</a><br>
Log:<br>
[codeview] Implement FPO data assembler directives<br>
<br>
Summary:<br>
This adds a set of new directives that describe 32-bit x86 prologues.<br>
The directives are limited and do not expose the full complexity of<br>
codeview FPO data. They are merely a convenience for the compiler to<br>
generate more readable assembly so we don't need to generate tons of<br>
labels in CodeGen. If our prologue emission changes in the future, we<br>
can change the set of available directives to suit our needs. These are<br>
modelled after the .seh_ directives, which use a different format that<br>
interacts with exception handling.<br>
<br>
The directives are:<br>
  .cv_fpo_proc _foo<br>
  .cv_fpo_pushreg ebp/ebx/etc<br>
  .cv_fpo_setframe ebp/esi/etc<br>
  .cv_fpo_stackalloc 200<br>
  .cv_fpo_endprologue<br>
  .cv_fpo_endproc<br>
  .cv_fpo_data _foo<br>
<br>
I tried to follow the implementation of ARM EHABI CFI directives by<br>
sinking most directives out of MCStreamer and into X86TargetStreamer.<br>
This helps avoid polluting non-X86 code with WinCOFF specific logic.<br>
<br>
I used cdb to confirm that this can show locals in parent CSRs in a few<br>
cases, most importantly the one where we use ESI as a frame pointer,<br>
i.e. the one in <a href="http://crbug.com/756153#c28" rel="noreferrer" target="_blank">http://crbug.com/756153#c28</a><br>
<br>
Once we have cdb integration in debuginfo-tests, we can add integration<br>
tests there.<br>
<br>
Reviewers: majnemer, hans<br>
<br>
Subscribers: aemerson, mgorny, kristof.beyls, llvm-commits, hiraditya<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D38776" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3877<wbr>6</a><br>
<br>
Added:<br>
    llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86TargetStreamer.h<br>
    llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86WinCOFFTargetStrea<wbr>mer.cpp<br>
    llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-argsize.ll<br>
    llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-csrs.ll<br>
    llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-realign-alloca.ll<br>
    llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-shrink-wrap.ll<br>
    llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-stack-protect.ll<br>
    llvm/trunk/test/MC/COFF/cv-fpo<wbr>-csrs.s<br>
    llvm/trunk/test/MC/COFF/cv-fpo<wbr>-errors.s<br>
    llvm/trunk/test/MC/COFF/cv-fpo<wbr>-setframe.s<br>
Modified:<br>
    llvm/trunk/include/llvm/MC/MCC<wbr>odeView.h<br>
    llvm/trunk/include/llvm/MC/MCS<wbr>treamer.h<br>
    llvm/trunk/lib/CodeGen/AsmPrin<wbr>ter/CodeViewDebug.cpp<br>
    llvm/trunk/lib/MC/MCAsmStreame<wbr>r.cpp<br>
    llvm/trunk/lib/MC/MCParser/Asm<wbr>Parser.cpp<br>
    llvm/trunk/lib/Target/X86/AsmP<wbr>arser/X86AsmParser.cpp<br>
    llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/CMakeLists.txt<br>
    llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86MCTargetDesc.cpp<br>
    llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86MCTargetDesc.h<br>
    llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86WinCOFFStreamer.<wbr>cpp<br>
    llvm/trunk/lib/Target/X86/X86A<wbr>smPrinter.cpp<br>
    llvm/trunk/lib/Target/X86/X86A<wbr>smPrinter.h<br>
    llvm/trunk/lib/Target/X86/X86F<wbr>rameLowering.cpp<br>
    llvm/trunk/lib/Target/X86/X86M<wbr>CInstLower.cpp<br>
    llvm/trunk/lib/Target/X86/X86S<wbr>ubtarget.h<br>
    llvm/trunk/test/DebugInfo/COFF<wbr>/asan-module-ctor.ll<br>
    llvm/trunk/test/DebugInfo/COFF<wbr>/multifunction.ll<br>
    llvm/trunk/test/DebugInfo/COFF<wbr>/simple.ll<br>
<br>
Modified: llvm/trunk/include/llvm/MC/MCC<wbr>odeView.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCCodeView.h?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>MC/MCCodeView.h?rev=315513&r1=<wbr>315512&r2=315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/MC/MCC<wbr>odeView.h (original)<br>
+++ llvm/trunk/include/llvm/MC/MCC<wbr>odeView.h Wed Oct 11 14:24:33 2017<br>
@@ -276,6 +276,10 @@ public:<br>
   /// Emits the offset into the checksum table of the given file number.<br>
   void emitFileChecksumOffset(MCObjec<wbr>tStreamer &OS, unsigned FileNo);<br>
<br>
+  /// Add something to the string table.  Returns the final string as well as<br>
+  /// offset into the string table.<br>
+  std::pair<StringRef, unsigned> addToStringTable(StringRef S);<br>
+<br>
 private:<br>
   /// The current CodeView line information from the last .cv_loc directive.<br>
   MCCVLoc CurrentCVLoc = MCCVLoc(0, 0, 0, 0, false, true);<br>
@@ -290,10 +294,6 @@ private:<br>
<br>
   MCDataFragment *getStringTableFragment();<br>
<br>
-  /// Add something to the string table.  Returns the final string as well as<br>
-  /// offset into the string table.<br>
-  std::pair<StringRef, unsigned> addToStringTable(StringRef S);<br>
-<br>
   /// Get a string table offset.<br>
   unsigned getStringTableOffset(StringRef S);<br>
<br>
<br>
Modified: llvm/trunk/include/llvm/MC/MCS<wbr>treamer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>MC/MCStreamer.h?rev=315513&r1=<wbr>315512&r2=315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/MC/MCS<wbr>treamer.h (original)<br>
+++ llvm/trunk/include/llvm/MC/MCS<wbr>treamer.h Wed Oct 11 14:24:33 2017<br>
@@ -790,6 +790,9 @@ public:<br>
   /// directive.<br>
   virtual void EmitCVFileChecksumOffsetDirect<wbr>ive(unsigned FileNo) {}<br>
<br>
+  /// This implements the CodeView '.cv_fpo_data' assembler directive.<br>
+  virtual void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc = {}) {}<br>
+<br>
   /// Emit the absolute difference between two symbols.<br>
   ///<br>
   /// \pre Offset of \c Hi is greater than the offset \c Lo.<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrin<wbr>ter/CodeViewDebug.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/CodeGen/<wbr>AsmPrinter/CodeViewDebug.cpp?<wbr>rev=315513&r1=315512&r2=<wbr>315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/CodeGen/AsmPrin<wbr>ter/CodeViewDebug.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrin<wbr>ter/CodeViewDebug.cpp Wed Oct 11 14:24:33 2017<br>
@@ -808,6 +808,10 @@ void CodeViewDebug::emitDebugInfoFo<wbr>rFunc<br>
   if (FuncName.empty())<br>
     FuncName = GlobalValue::dropLLVMManglingE<wbr>scape(GV->getName());<br>
<br>
+  // Emit FPO data, but only on 32-bit x86. No other platforms use it.<br>
+  if (Triple(MMI->getModule()->getT<wbr>argetTriple()).getArch() == Triple::x86)<br>
+    OS.EmitCVFPOData(Fn);<br>
+<br>
   // Emit a symbol subsection, required by VS2012+ to find function boundaries.<br>
   OS.AddComment("Symbol subsection for " + Twine(FuncName));<br>
   MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsect<wbr>ionKind::Symbols);<br>
<br>
Modified: llvm/trunk/lib/MC/MCAsmStreame<wbr>r.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/MC/MCAsmS<wbr>treamer.cpp?rev=315513&r1=<wbr>315512&r2=315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/MC/MCAsmStreame<wbr>r.cpp (original)<br>
+++ llvm/trunk/lib/MC/MCAsmStreame<wbr>r.cpp Wed Oct 11 14:24:33 2017<br>
@@ -248,6 +248,7 @@ public:<br>
   void EmitCVStringTableDirective() override;<br>
   void EmitCVFileChecksumsDirective() override;<br>
   void EmitCVFileChecksumOffsetDirect<wbr>ive(unsigned FileNo) override;<br>
+  void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;<br>
<br>
   void EmitIdent(StringRef IdentString) override;<br>
   void EmitCFISections(bool EH, bool Debug) override;<br>
@@ -1252,6 +1253,12 @@ void MCAsmStreamer::EmitCVFileCheck<wbr>sumOf<br>
   EmitEOL();<br>
 }<br>
<br>
+void MCAsmStreamer::EmitCVFPOData(c<wbr>onst MCSymbol *ProcSym, SMLoc L) {<br>
+  OS << "\t.cv_fpo_data\t";<br>
+  ProcSym->print(OS, MAI);<br>
+  EmitEOL();<br>
+}<br>
+<br>
 void MCAsmStreamer::EmitIdent(Strin<wbr>gRef IdentString) {<br>
   assert(MAI-><wbr>hasIdentDirective() && ".ident directive not supported");<br>
   OS << "\t.ident\t";<br>
<br>
Modified: llvm/trunk/lib/MC/MCParser/Asm<wbr>Parser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/MC/MCPars<wbr>er/AsmParser.cpp?rev=315513&<wbr>r1=315512&r2=315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/MC/MCParser/Asm<wbr>Parser.cpp (original)<br>
+++ llvm/trunk/lib/MC/MCParser/Asm<wbr>Parser.cpp Wed Oct 11 14:24:33 2017<br>
@@ -503,6 +503,7 @@ private:<br>
     DK_CV_STRINGTABLE,<br>
     DK_CV_FILECHECKSUMS,<br>
     DK_CV_FILECHECKSUM_OFFSET,<br>
+    DK_CV_FPO_DATA,<br>
     DK_CFI_SECTIONS,<br>
     DK_CFI_STARTPROC,<br>
     DK_CFI_ENDPROC,<br>
@@ -580,6 +581,7 @@ private:<br>
   bool parseDirectiveCVStringTable();<br>
   bool parseDirectiveCVFileChecksums(<wbr>);<br>
   bool parseDirectiveCVFileChecksumOf<wbr>fset();<br>
+  bool parseDirectiveCVFPOData();<br>
<br>
   // .cfi directives<br>
   bool parseDirectiveCFIRegister(SMLo<wbr>c DirectiveLoc);<br>
@@ -2039,6 +2041,8 @@ bool AsmParser::parseStatement(Pars<wbr>eStat<br>
       return parseDirectiveCVFileChecksums(<wbr>);<br>
     case DK_CV_FILECHECKSUM_OFFSET:<br>
       return parseDirectiveCVFileChecksumOf<wbr>fset();<br>
+    case DK_CV_FPO_DATA:<br>
+      return parseDirectiveCVFPOData();<br>
     case DK_CFI_SECTIONS:<br>
       return parseDirectiveCFISections();<br>
     case DK_CFI_STARTPROC:<br>
@@ -3791,6 +3795,20 @@ bool AsmParser::parseDirectiveCVFil<wbr>eChec<br>
   return false;<br>
 }<br>
<br>
+/// parseDirectiveCVFPOData<br>
+/// ::= .cv_fpo_data procsym<br>
+bool AsmParser::parseDirectiveCVFPO<wbr>Data() {<br>
+  SMLoc DirLoc = getLexer().getLoc();<br>
+  StringRef ProcName;<br>
+  if (parseIdentifier(ProcName))<br>
+    return TokError("expected symbol name");<br>
+  if (parseEOL("unexpected tokens"))<br>
+    return addErrorSuffix(" in '.cv_fpo_data' directive");<br>
+  MCSymbol *ProcSym = getContext().getOrCreateSymbol<wbr>(ProcName);<br>
+  getStreamer().EmitCVFPOData(Pr<wbr>ocSym, DirLoc);<br>
+  return false;<br>
+}<br>
+<br>
 /// parseDirectiveCFISections<br>
 /// ::= .cfi_sections section [, section]<br>
 bool AsmParser::parseDirectiveCFISe<wbr>ctions() {<br>
@@ -5174,6 +5192,7 @@ void AsmParser::initializeDirective<wbr>KindM<br>
   DirectiveKindMap[".cv_stringt<wbr>able"] = DK_CV_STRINGTABLE;<br>
   DirectiveKindMap[".cv_fileche<wbr>cksums"] = DK_CV_FILECHECKSUMS;<br>
   DirectiveKindMap[".cv_fileche<wbr>cksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;<br>
+  DirectiveKindMap[".cv_fpo_data<wbr>"] = DK_CV_FPO_DATA;<br>
   DirectiveKindMap[".sleb128"] = DK_SLEB128;<br>
   DirectiveKindMap[".uleb128"] = DK_ULEB128;<br>
   DirectiveKindMap[".cfi_sectio<wbr>ns"] = DK_CFI_SECTIONS;<br>
<br>
Modified: llvm/trunk/lib/Target/X86/AsmP<wbr>arser/X86AsmParser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/AsmParser/X86AsmParser.cpp?<wbr>rev=315513&r1=315512&r2=315513<wbr>&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/AsmP<wbr>arser/X86AsmParser.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/AsmP<wbr>arser/X86AsmParser.cpp Wed Oct 11 14:24:33 2017<br>
@@ -7,11 +7,12 @@<br>
 //<br>
 //===------------------------<wbr>------------------------------<wbr>----------------===//<br>
<br>
+#include "InstPrinter/X86IntelInstPrint<wbr>er.h"<br>
 #include "MCTargetDesc/X86BaseInfo.h"<br>
+#include "MCTargetDesc/X86TargetStreame<wbr>r.h"<br>
 #include "X86AsmInstrumentation.h"<br>
 #include "X86AsmParserCommon.h"<br>
 #include "X86Operand.h"<br>
-#include "InstPrinter/X86IntelInstPrint<wbr>er.h"<br>
 #include "llvm/ADT/STLExtras.h"<br>
 #include "llvm/ADT/SmallString.h"<br>
 #include "llvm/ADT/SmallVector.h"<br>
@@ -80,6 +81,13 @@ private:<br>
     return Result;<br>
   }<br>
<br>
+  X86TargetStreamer &getTargetStreamer() {<br>
+    assert(getParser().getStreamer<wbr>().getTargetStreamer() &&<br>
+           "do not have a target streamer");<br>
+    MCTargetStreamer &TS = *getParser().getStreamer().get<wbr>TargetStreamer();<br>
+    return static_cast<X86TargetStreamer &>(TS);<br>
+  }<br>
+<br>
   unsigned MatchInstruction(const OperandVector &Operands, MCInst &Inst,<br>
                             uint64_t &ErrorInfo, bool matchingInlineAsm,<br>
                             unsigned VariantID = 0) {<br>
@@ -839,6 +847,15 @@ private:<br>
   bool ParseDirectiveWord(unsigned Size, SMLoc L);<br>
   bool ParseDirectiveCode(StringRef IDVal, SMLoc L);<br>
<br>
+  /// CodeView FPO data directives.<br>
+  bool parseDirectiveFPOProc(SMLoc L);<br>
+  bool parseDirectiveFPOSetFrame(SMLo<wbr>c L);<br>
+  bool parseDirectiveFPOPushReg(SMLoc L);<br>
+  bool parseDirectiveFPOStackAlloc(SM<wbr>Loc L);<br>
+  bool parseDirectiveFPOEndPrologue(S<wbr>MLoc L);<br>
+  bool parseDirectiveFPOEndProc(SMLoc L);<br>
+  bool parseDirectiveFPOData(SMLoc L);<br>
+<br>
   bool processInstruction(MCInst &Inst, const OperandVector &Ops);<br>
<br>
   /// Wrapper around MCStreamer::EmitInstruction(). Possibly adds<br>
@@ -3027,6 +3044,19 @@ bool X86AsmParser::ParseDirective(A<wbr>smTok<br>
     return false;<br>
   } else if (IDVal == ".even")<br>
     return parseDirectiveEven(DirectiveID<wbr>.getLoc());<br>
+  else if (IDVal == ".cv_fpo_proc")<br>
+    return parseDirectiveFPOProc(Directiv<wbr>eID.getLoc());<br>
+  else if (IDVal == ".cv_fpo_setframe")<br>
+    return parseDirectiveFPOSetFrame(Dire<wbr>ctiveID.getLoc());<br>
+  else if (IDVal == ".cv_fpo_pushreg")<br>
+    return parseDirectiveFPOPushReg(Direc<wbr>tiveID.getLoc());<br>
+  else if (IDVal == ".cv_fpo_stackalloc")<br>
+    return parseDirectiveFPOStackAlloc(Di<wbr>rectiveID.getLoc());<br>
+  else if (IDVal == ".cv_fpo_endprologue")<br>
+    return parseDirectiveFPOEndPrologue(D<wbr>irectiveID.getLoc());<br>
+  else if (IDVal == ".cv_fpo_endproc")<br>
+    return parseDirectiveFPOEndProc(Direc<wbr>tiveID.getLoc());<br>
+<br>
   return true;<br>
 }<br>
<br>
@@ -3124,6 +3154,71 @@ bool X86AsmParser::ParseDirectiveCo<wbr>de(St<br>
   return false;<br>
 }<br>
<br>
+// .cv_fpo_proc foo<br>
+bool X86AsmParser::parseDirectiveFP<wbr>OProc(SMLoc L) {<br>
+  MCAsmParser &Parser = getParser();<br>
+  StringRef ProcName;<br>
+  int64_t ParamsSize;<br>
+  if (Parser.parseIdentifier(ProcNa<wbr>me))<br>
+    return Parser.TokError("expected symbol name");<br>
+  if (Parser.parseIntToken(ParamsSi<wbr>ze, "expected parameter byte count"))<br>
+    return true;<br>
+  if (!isUIntN(32, ParamsSize))<br>
+    return Parser.TokError("parameters size out of range");<br>
+  if (Parser.parseEOL("unexpected tokens"))<br>
+    return addErrorSuffix(" in '.cv_fpo_proc' directive");<br>
+  MCSymbol *ProcSym = getContext().getOrCreateSymbol<wbr>(ProcName);<br>
+  return getTargetStreamer().emitFPOPro<wbr>c(ProcSym, ParamsSize, L);<br>
+}<br>
+<br>
+// .cv_fpo_setframe ebp<br>
+bool X86AsmParser::parseDirectiveFP<wbr>OSetFrame(SMLoc L) {<br>
+  MCAsmParser &Parser = getParser();<br>
+  unsigned Reg;<br>
+  SMLoc DummyLoc;<br>
+  if (ParseRegister(Reg, DummyLoc, DummyLoc) ||<br>
+      Parser.parseEOL("unexpected tokens"))<br>
+    return addErrorSuffix(" in '.cv_fpo_setframe' directive");<br>
+  return getTargetStreamer().emitFPOSet<wbr>Frame(Reg, L);<br>
+}<br>
+<br>
+// .cv_fpo_pushreg ebx<br>
+bool X86AsmParser::parseDirectiveFP<wbr>OPushReg(SMLoc L) {<br>
+  MCAsmParser &Parser = getParser();<br>
+  unsigned Reg;<br>
+  SMLoc DummyLoc;<br>
+  if (ParseRegister(Reg, DummyLoc, DummyLoc) ||<br>
+      Parser.parseEOL("unexpected tokens"))<br>
+    return addErrorSuffix(" in '.cv_fpo_pushreg' directive");<br>
+  return getTargetStreamer().emitFPOPus<wbr>hReg(Reg, L);<br>
+}<br>
+<br>
+// .cv_fpo_stackalloc 20<br>
+bool X86AsmParser::parseDirectiveFP<wbr>OStackAlloc(SMLoc L) {<br>
+  MCAsmParser &Parser = getParser();<br>
+  int64_t Offset;<br>
+  if (Parser.parseIntToken(Offset, "expected offset") ||<br>
+      Parser.parseEOL("unexpected tokens"))<br>
+    return addErrorSuffix(" in '.cv_fpo_stackalloc' directive");<br>
+  return getTargetStreamer().emitFPOSta<wbr>ckAlloc(Offset, L);<br>
+}<br>
+<br>
+// .cv_fpo_endprologue<br>
+bool X86AsmParser::parseDirectiveFP<wbr>OEndPrologue(SMLoc L) {<br>
+  MCAsmParser &Parser = getParser();<br>
+  if (Parser.parseEOL("unexpected tokens"))<br>
+    return addErrorSuffix(" in '.cv_fpo_endprologue' directive");<br>
+  return getTargetStreamer().emitFPOEnd<wbr>Prologue(L);<br>
+}<br>
+<br>
+// .cv_fpo_endproc<br>
+bool X86AsmParser::parseDirectiveFP<wbr>OEndProc(SMLoc L) {<br>
+  MCAsmParser &Parser = getParser();<br>
+  if (Parser.parseEOL("unexpected tokens"))<br>
+    return addErrorSuffix(" in '.cv_fpo_endproc' directive");<br>
+  return getTargetStreamer().emitFPOEnd<wbr>Proc(L);<br>
+}<br>
+<br>
 // Force static initialization.<br>
 extern "C" void LLVMInitializeX86AsmParser() {<br>
   RegisterMCAsmParser<X86AsmPar<wbr>ser> X(getTheX86_32Target());<br>
<br>
Modified: llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/CMakeLists.txt?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/MCTargetDesc/CMakeLists.txt?<wbr>rev=315513&r1=315512&r2=315513<wbr>&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/CMakeLists.txt Wed Oct 11 14:24:33 2017<br>
@@ -5,6 +5,7 @@ add_llvm_library(LLVMX86Desc<br>
   X86MCCodeEmitter.cpp<br>
   X86MachObjectWriter.cpp<br>
   X86ELFObjectWriter.cpp<br>
-  X86WinCOFFStreamer.cpp<br>
   X86WinCOFFObjectWriter.cpp<br>
+  X86WinCOFFStreamer.cpp<br>
+  X86WinCOFFTargetStreamer.cpp<br>
   )<br>
<br>
Modified: llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86MCTargetDesc.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/MCTargetDesc/X86MCTargetDesc<wbr>.cpp?rev=315513&r1=315512&r2=<wbr>315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86MCTargetDesc.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86MCTargetDesc.cpp Wed Oct 11 14:24:33 2017<br>
@@ -319,7 +319,13 @@ extern "C" void LLVMInitializeX86TargetM<br>
     // Register the code emitter.<br>
     TargetRegistry::RegisterMCCod<wbr>eEmitter(*T, createX86MCCodeEmitter);<br>
<br>
-    // Register the object streamer.<br>
+    // Register the obj target streamer.<br>
+    TargetRegistry::RegisterObject<wbr>TargetStreamer(*T,<br>
+                                                 <wbr>createX86ObjectTargetStreamer)<wbr>;<br>
+<br>
+    // Register the asm target streamer.<br>
+    TargetRegistry::RegisterAsmTar<wbr>getStreamer(*T, createX86AsmTargetStreamer);<br>
+<br>
     TargetRegistry::RegisterCOFFS<wbr>treamer(*T, createX86WinCOFFStreamer);<br>
<br>
     // Register the MCInstPrinter.<br>
<br>
Modified: llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86MCTargetDesc.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/MCTargetDesc/X86MCTargetDesc<wbr>.h?rev=315513&r1=315512&r2=<wbr>315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86MCTargetDesc.h (original)<br>
+++ llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86MCTargetDesc.h Wed Oct 11 14:24:33 2017<br>
@@ -77,6 +77,16 @@ MCAsmBackend *createX86_64AsmBackend(con<br>
                                      const Triple &TT, StringRef CPU,<br>
                                      const MCTargetOptions &Options);<br>
<br>
+/// Implements X86-only directives for assembly emission.<br>
+MCTargetStreamer *createX86AsmTargetStreamer(MC<wbr>Streamer &S,<br>
+                                             formatted_raw_ostream &OS,<br>
+                                             MCInstPrinter *InstPrint,<br>
+                                             bool isVerboseAsm);<br>
+<br>
+/// Implements X86-only directives for object files.<br>
+MCTargetStreamer *createX86ObjectTargetStreamer<wbr>(MCStreamer &OS,<br>
+                                                const MCSubtargetInfo &STI);<br>
+<br>
 /// Construct an X86 Windows COFF machine code streamer which will generate<br>
 /// PE/COFF format object files.<br>
 ///<br>
<br>
Added: llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86TargetStreamer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86TargetStreamer.h?rev=315513&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/MCTargetDesc/X86TargetStream<wbr>er.h?rev=315513&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86TargetStreamer.h (added)<br>
+++ llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86TargetStreamer.h Wed Oct 11 14:24:33 2017<br>
@@ -0,0 +1,34 @@<br>
+//===- X86TargetStreamer.h ------------------------------<wbr>*- C++ -*---------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef LLVM_LIB_TARGET_X86_MCTARGETDE<wbr>SC_X86TARGETSTREAMER_H<br>
+#define LLVM_LIB_TARGET_X86_MCTARGETDE<wbr>SC_X86TARGETSTREAMER_H<br>
+<br>
+#include "llvm/MC/MCStreamer.h"<br>
+<br>
+namespace llvm {<br>
+<br>
+/// X86 target streamer implementing x86-only assembly directives.<br>
+class X86TargetStreamer : public MCTargetStreamer {<br>
+public:<br>
+  X86TargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}<br>
+<br>
+  virtual bool emitFPOProc(const MCSymbol *ProcSym, unsigned ParamsSize,<br>
+                           SMLoc L = {}) = 0;<br>
+  virtual bool emitFPOEndPrologue(SMLoc L = {}) = 0;<br>
+  virtual bool emitFPOEndProc(SMLoc L = {}) = 0;<br>
+  virtual bool emitFPOData(const MCSymbol *ProcSym, SMLoc L = {}) = 0;<br>
+  virtual bool emitFPOPushReg(unsigned Reg, SMLoc L = {}) = 0;<br>
+  virtual bool emitFPOStackAlloc(unsigned StackAlloc, SMLoc L = {}) = 0;<br>
+  virtual bool emitFPOSetFrame(unsigned Reg, SMLoc L = {}) = 0;<br>
+};<br>
+<br>
+} // end namespace llvm<br>
+<br>
+#endif<br>
<br>
Modified: llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86WinCOFFStreamer.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/MCTargetDesc/X86WinCOFFStrea<wbr>mer.cpp?rev=315513&r1=315512&<wbr>r2=315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86WinCOFFStreamer.<wbr>cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86WinCOFFStreamer.<wbr>cpp Wed Oct 11 14:24:33 2017<br>
@@ -8,6 +8,7 @@<br>
 //===------------------------<wbr>------------------------------<wbr>----------------===//<br>
<br>
 #include "X86MCTargetDesc.h"<br>
+#include "X86TargetStreamer.h"<br>
 #include "llvm/MC/MCAsmBackend.h"<br>
 #include "llvm/MC/MCWin64EH.h"<br>
 #include "llvm/MC/MCWinCOFFStreamer.h"<br>
@@ -24,6 +25,7 @@ public:<br>
<br>
   void EmitWinEHHandlerData(SMLoc Loc) override;<br>
   void EmitWindowsUnwindTables() override;<br>
+  void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc) override;<br>
   void FinishImpl() override;<br>
 };<br>
<br>
@@ -41,6 +43,12 @@ void X86WinCOFFStreamer::EmitWindow<wbr>sUnwi<br>
   EHStreamer.Emit(*this);<br>
 }<br>
<br>
+void X86WinCOFFStreamer::EmitCVFPOD<wbr>ata(const MCSymbol *ProcSym, SMLoc Loc) {<br>
+  X86TargetStreamer *XTS =<br>
+      static_cast<X86TargetStreamer *>(getTargetStreamer());<br>
+  XTS->emitFPOData(ProcSym, Loc);<br>
+}<br>
+<br>
 void X86WinCOFFStreamer::FinishImpl<wbr>() {<br>
   EmitFrames(nullptr);<br>
   EmitWindowsUnwindTables();<br>
<br>
Added: llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86WinCOFFTargetStrea<wbr>mer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86WinCOFFTargetStreamer.cpp?rev=315513&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/MCTargetDesc/X86WinCOFFTarge<wbr>tStreamer.cpp?rev=315513&view=<wbr>auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86WinCOFFTargetStrea<wbr>mer.cpp (added)<br>
+++ llvm/trunk/lib/Target/X86/MCTa<wbr>rgetDesc/X86WinCOFFTargetStrea<wbr>mer.cpp Wed Oct 11 14:24:33 2017<br>
@@ -0,0 +1,415 @@<br>
+//===-- X86WinCOFFTargetStreamer.cpp ----------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "X86MCTargetDesc.h"<br>
+#include "X86TargetStreamer.h"<br>
+#include "llvm/DebugInfo/CodeView/CodeV<wbr>iew.h"<br>
+#include "llvm/MC/MCCodeView.h"<br>
+#include "llvm/MC/MCContext.h"<br>
+#include "llvm/MC/MCInstPrinter.h"<br>
+#include "llvm/MC/MCRegisterInfo.h"<br>
+#include "llvm/MC/MCSubtargetInfo.h"<br>
+#include "llvm/Support/FormattedStream.<wbr>h"<br>
+<br>
+using namespace llvm;<br>
+using namespace llvm::codeview;<br>
+<br>
+namespace {<br>
+/// Implements Windows x86-only directives for assembly emission.<br>
+class X86WinCOFFAsmTargetStreamer : public X86TargetStreamer {<br>
+  formatted_raw_ostream &OS;<br>
+  MCInstPrinter &InstPrinter;<br>
+<br>
+public:<br>
+  X86WinCOFFAsmTargetStreamer(MC<wbr>Streamer &S, formatted_raw_ostream &OS,<br>
+                              MCInstPrinter &InstPrinter)<br>
+      : X86TargetStreamer(S), OS(OS), InstPrinter(InstPrinter) {}<br>
+<br>
+  bool emitFPOProc(const MCSymbol *ProcSym, unsigned ParamsSize,<br>
+                   SMLoc L) override;<br>
+  bool emitFPOEndPrologue(SMLoc L) override;<br>
+  bool emitFPOEndProc(SMLoc L) override;<br>
+  bool emitFPOData(const MCSymbol *ProcSym, SMLoc L) override;<br>
+  bool emitFPOPushReg(unsigned Reg, SMLoc L) override;<br>
+  bool emitFPOStackAlloc(unsigned StackAlloc, SMLoc L) override;<br>
+  bool emitFPOSetFrame(unsigned Reg, SMLoc L) override;<br>
+};<br>
+<br>
+/// Represents a single FPO directive.<br>
+struct FPOInstruction {<br>
+  MCSymbol *Label;<br>
+  enum Operation {<br>
+    PushReg,<br>
+    StackAlloc,<br>
+    SetFrame,<br>
+  } Op;<br>
+  unsigned RegOrOffset;<br>
+};<br>
+<br>
+struct FPOData {<br>
+  const MCSymbol *Function = nullptr;<br>
+  MCSymbol *Begin = nullptr;<br>
+  MCSymbol *PrologueEnd = nullptr;<br>
+  MCSymbol *End = nullptr;<br>
+  unsigned ParamsSize = 0;<br>
+<br>
+  SmallVector<FPOInstruction, 5> Instructions;<br>
+};<br>
+<br>
+/// Implements Windows x86-only directives for object emission.<br>
+class X86WinCOFFTargetStreamer : public X86TargetStreamer {<br>
+  /// Map from function symbol to its FPO data.<br>
+  DenseMap<const MCSymbol *, std::unique_ptr<FPOData>> AllFPOData;<br>
+<br>
+  /// Current FPO data created by .cv_fpo_proc.<br>
+  std::unique_ptr<FPOData> CurFPOData;<br>
+<br>
+  bool haveOpenFPOData() { return !!CurFPOData; }<br>
+<br>
+  /// Diagnoses an error at L if we are not in an FPO prologue. Return true on<br>
+  /// error.<br>
+  bool checkInFPOPrologue(SMLoc L);<br>
+<br>
+  MCSymbol *emitFPOLabel();<br>
+<br>
+  MCContext &getContext() { return getStreamer().getContext(); }<br>
+<br>
+public:<br>
+  X86WinCOFFTargetStreamer(MCStr<wbr>eamer &S) : X86TargetStreamer(S) {}<br>
+<br>
+  bool emitFPOProc(const MCSymbol *ProcSym, unsigned ParamsSize,<br>
+                   SMLoc L) override;<br>
+  bool emitFPOEndPrologue(SMLoc L) override;<br>
+  bool emitFPOEndProc(SMLoc L) override;<br>
+  bool emitFPOData(const MCSymbol *ProcSym, SMLoc L) override;<br>
+  bool emitFPOPushReg(unsigned Reg, SMLoc L) override;<br>
+  bool emitFPOStackAlloc(unsigned StackAlloc, SMLoc L) override;<br>
+  bool emitFPOSetFrame(unsigned Reg, SMLoc L) override;<br>
+};<br>
+} // end namespace<br>
+<br>
+bool X86WinCOFFAsmTargetStreamer::e<wbr>mitFPOProc(const MCSymbol *ProcSym,<br>
+                                              unsigned ParamsSize, SMLoc L) {<br>
+  OS << "\t.cv_fpo_proc\t";<br>
+  ProcSym->print(OS, getStreamer().getContext().get<wbr>AsmInfo());<br>
+  OS << ' ' << ParamsSize << '\n';<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFAsmTargetStreamer::e<wbr>mitFPOEndPrologue(SMLoc L) {<br>
+  OS << "\t.cv_fpo_endprologue\n";<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFAsmTargetStreamer::e<wbr>mitFPOEndProc(SMLoc L) {<br>
+  OS << "\t.cv_fpo_endproc\n";<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFAsmTargetStreamer::e<wbr>mitFPOData(const MCSymbol *ProcSym,<br>
+                                              SMLoc L) {<br>
+  OS << "\t.cv_fpo_data\t";<br>
+  ProcSym->print(OS, getStreamer().getContext().get<wbr>AsmInfo());<br>
+  OS << '\n';<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFAsmTargetStreamer::e<wbr>mitFPOPushReg(unsigned Reg, SMLoc L) {<br>
+  OS << "\t.cv_fpo_pushreg\t";<br>
+  InstPrinter.printRegName(OS, Reg);<br>
+  OS << '\n';<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFAsmTargetStreamer::e<wbr>mitFPOStackAlloc(unsigned StackAlloc,<br>
+                                                    SMLoc L) {<br>
+  OS << "\t.cv_fpo_stackalloc\t" << StackAlloc << '\n';<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFAsmTargetStreamer::e<wbr>mitFPOSetFrame(unsigned Reg, SMLoc L) {<br>
+  OS << "\t.cv_fpo_setframe\t";<br>
+  InstPrinter.printRegName(OS, Reg);<br>
+  OS << '\n';<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFTargetStreamer::chec<wbr>kInFPOPrologue(SMLoc L) {<br>
+  if (!haveOpenFPOData() || CurFPOData->PrologueEnd) {<br>
+    getContext().reportError(<br>
+        L,<br>
+        "directive must appear between .cv_fpo_proc and .cv_fpo_endprologue");<br>
+    return true;<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+MCSymbol *X86WinCOFFTargetStreamer::emi<wbr>tFPOLabel() {<br>
+  MCSymbol *Label = getContext().createTempSymbol(<wbr>"cfi", true);<br>
+  getStreamer().EmitLabel(Label)<wbr>;<br>
+  return Label;<br>
+}<br>
+<br>
+bool X86WinCOFFTargetStreamer::emit<wbr>FPOProc(const MCSymbol *ProcSym,<br>
+                                           unsigned ParamsSize, SMLoc L) {<br>
+  if (haveOpenFPOData()) {<br>
+    getContext().reportError(<br>
+        L, "opening new .cv_fpo_proc before closing previous frame");<br>
+    return true;<br>
+  }<br>
+  CurFPOData = llvm::make_unique<FPOData>();<br>
+  CurFPOData->Function = ProcSym;<br>
+  CurFPOData->Begin = emitFPOLabel();<br>
+  CurFPOData->ParamsSize = ParamsSize;<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFTargetStreamer::emit<wbr>FPOEndProc(SMLoc L) {<br>
+  if (!haveOpenFPOData()) {<br>
+    getContext().reportError(L, ".cv_fpo_endproc must appear after .cv_proc");<br>
+    return true;<br>
+  }<br>
+  if (!CurFPOData->PrologueEnd) {<br>
+    // Complain if there were prologue setup instructions but no end prologue.<br>
+    if (!CurFPOData->Instructions.emp<wbr>ty()) {<br>
+      getContext().reportError(L, "missing .cv_fpo_endprologue");<br>
+      CurFPOData->Instructions.clear<wbr>();<br>
+    }<br>
+<br>
+    // Claim there is a zero-length prologue to make the label math work out<br>
+    // later.<br>
+    CurFPOData->PrologueEnd = CurFPOData->Begin;<br>
+  }<br>
+<br>
+  CurFPOData->End = emitFPOLabel();<br>
+  const MCSymbol *Fn = CurFPOData->Function;<br>
+  AllFPOData.insert({Fn, std::move(CurFPOData)});<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFTargetStreamer::emit<wbr>FPOSetFrame(unsigned Reg, SMLoc L) {<br>
+  if (checkInFPOPrologue(L))<br>
+    return true;<br>
+  FPOInstruction Inst;<br>
+  Inst.Label = emitFPOLabel();<br>
+  Inst.Op = FPOInstruction::SetFrame;<br>
+  Inst.RegOrOffset = Reg;<br>
+  CurFPOData->Instructions.push_<wbr>back(Inst);<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFTargetStreamer::emit<wbr>FPOPushReg(unsigned Reg, SMLoc L) {<br>
+  if (checkInFPOPrologue(L))<br>
+    return true;<br>
+  FPOInstruction Inst;<br>
+  Inst.Label = emitFPOLabel();<br>
+  Inst.Op = FPOInstruction::PushReg;<br>
+  Inst.RegOrOffset = Reg;<br>
+  CurFPOData->Instructions.push_<wbr>back(Inst);<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFTargetStreamer::emit<wbr>FPOStackAlloc(unsigned StackAlloc, SMLoc L) {<br>
+  if (checkInFPOPrologue(L))<br>
+    return true;<br>
+  FPOInstruction Inst;<br>
+  Inst.Label = emitFPOLabel();<br>
+  Inst.Op = FPOInstruction::StackAlloc;<br>
+  Inst.RegOrOffset = StackAlloc;<br>
+  CurFPOData->Instructions.push_<wbr>back(Inst);<br>
+  return false;<br>
+}<br>
+<br>
+bool X86WinCOFFTargetStreamer::emit<wbr>FPOEndPrologue(SMLoc L) {<br>
+  if (checkInFPOPrologue(L))<br>
+    return true;<br>
+  CurFPOData->PrologueEnd = emitFPOLabel();<br>
+  return false;<br>
+}<br>
+<br>
+namespace {<br>
+struct RegSaveOffset {<br>
+  RegSaveOffset(unsigned Reg, unsigned Offset) : Reg(Reg), Offset(Offset) {}<br>
+<br>
+  unsigned Reg = 0;<br>
+  unsigned Offset = 0;<br>
+};<br>
+<br>
+struct FPOStateMachine {<br>
+  explicit FPOStateMachine(const FPOData *FPO) : FPO(FPO) {}<br>
+<br>
+  const FPOData *FPO = nullptr;<br>
+  unsigned FrameReg = 0;<br>
+  unsigned FrameRegOff = 0;<br>
+  unsigned CurOffset = 0;<br>
+  unsigned LocalSize = 0;<br>
+  unsigned SavedRegSize = 0;<br>
+  unsigned Flags = 0; // FIXME: Set HasSEH / HasEH.<br>
+<br>
+  SmallString<128> FrameFunc;<br>
+<br>
+  SmallVector<RegSaveOffset, 4> RegSaveOffsets;<br>
+<br>
+  void emitFrameDataRecord(MCStreamer &OS, MCSymbol *Label);<br>
+};<br>
+} // end namespace<br>
+<br>
+static Printable printFPOReg(const MCRegisterInfo *MRI, unsigned LLVMReg) {<br>
+  return Printable([MRI, LLVMReg](raw_ostream &OS) {<br>
+    switch (LLVMReg) {<br>
+    // MSVC only seems to emit symbolic register names for EIP, EBP, and ESP,<br>
+    // but the format seems to support more than that, so we emit them.<br>
+    case X86::EAX: OS << "$eax"; break;<br>
+    case X86::EBX: OS << "$ebx"; break;<br>
+    case X86::ECX: OS << "$ecx"; break;<br>
+    case X86::EDX: OS << "$edx"; break;<br>
+    case X86::EDI: OS << "$edi"; break;<br>
+    case X86::ESI: OS << "$esi"; break;<br>
+    case X86::ESP: OS << "$esp"; break;<br>
+    case X86::EBP: OS << "$ebp"; break;<br>
+    case X86::EIP: OS << "$eip"; break;<br>
+    // Otherwise, get the codeview register number and print $N.<br>
+    default:<br>
+      OS << '$' << MRI->getCodeViewRegNum(LLVMReg<wbr>);<br>
+      break;<br>
+    }<br>
+  });<br>
+}<br>
+<br>
+void FPOStateMachine::emitFrameData<wbr>Record(MCStreamer &OS, MCSymbol *Label) {<br>
+  unsigned CurFlags = Flags;<br>
+  if (Label == FPO->Begin)<br>
+    CurFlags |= FrameData::IsFunctionStart;<br>
+<br>
+  // Compute the new FrameFunc string.<br>
+  FrameFunc.clear();<br>
+  raw_svector_ostream FuncOS(FrameFunc);<br>
+  const MCRegisterInfo *MRI = OS.getContext().getRegisterInf<wbr>o();<br>
+  if (FrameReg) {<br>
+    // CFA is FrameReg + FrameRegOff.<br>
+    FuncOS << "$T0 " << printFPOReg(MRI, FrameReg) << " " << FrameRegOff<br>
+           << " + = ";<br>
+  } else {<br>
+    // The address of return address is ESP + CurOffset, but we use .raSearch to<br>
+    // match MSVC. This seems to ask the debugger to subtract some combination<br>
+    // of LocalSize and SavedRegSize from ESP and grovel around in that memory<br>
+    // to find the address of a plausible return address.<br>
+    FuncOS << "$T0 .raSearch = ";<br>
+  }<br>
+<br>
+  // Caller's $eip should be dereferenced CFA, and $esp should be CFA plus 4.<br>
+  FuncOS << "$eip $T0 ^ = $esp $T0 4 + = ";<br>
+<br>
+  // Each saved register is stored at an unchanging negative CFA offset.<br>
+  for (RegSaveOffset RO : RegSaveOffsets)<br>
+    FuncOS << printFPOReg(MRI, RO.Reg) << " $T0 " << RO.Offset << " - ^ = ";<br>
+<br>
+  // Add it to the CV string table.<br>
+  CodeViewContext &CVCtx = OS.getContext().getCVContext()<wbr>;<br>
+  unsigned FrameFuncStrTabOff = CVCtx.addToStringTable(FuncOS.<wbr>str()).second;<br>
+<br>
+  // MSVC has only ever been observed to emit a MaxStackSize of zero.<br>
+  unsigned MaxStackSize = 0;<br>
+<br>
+  // The FrameData record format is:<br>
+  //   ulittle32_t RvaStart;<br>
+  //   ulittle32_t CodeSize;<br>
+  //   ulittle32_t LocalSize;<br>
+  //   ulittle32_t ParamsSize;<br>
+  //   ulittle32_t MaxStackSize;<br>
+  //   ulittle32_t FrameFunc; // String table offset<br>
+  //   ulittle16_t PrologSize;<br>
+  //   ulittle16_t SavedRegsSize;<br>
+  //   ulittle32_t Flags;<br>
+<br>
+  OS.emitAbsoluteSymbolDiff(Labe<wbr>l, FPO->Begin, 4); // RvaStart<br>
+  OS.emitAbsoluteSymbolDiff(FPO-<wbr>>End, Label, 4);   // CodeSize<br>
+  OS.EmitIntValue(LocalSize, 4);<br>
+  OS.EmitIntValue(FPO->ParamsSiz<wbr>e, 4);<br>
+  OS.EmitIntValue(MaxStackSize, 4);<br>
+  OS.EmitIntValue(FrameFuncStrTa<wbr>bOff, 4); // FrameFunc<br>
+  OS.emitAbsoluteSymbolDiff(FPO-<wbr>>PrologueEnd, Label, 2);<br>
+  OS.EmitIntValue(SavedRegSize, 2);<br>
+  OS.EmitIntValue(CurFlags, 4);<br>
+}<br>
+<br>
+/// Compute and emit the real CodeView FrameData subsection.<br>
+bool X86WinCOFFTargetStreamer::emit<wbr>FPOData(const MCSymbol *ProcSym, SMLoc L) {<br>
+  MCStreamer &OS = getStreamer();<br>
+  MCContext &Ctx = OS.getContext();<br>
+<br>
+  auto I = AllFPOData.find(ProcSym);<br>
+  if (I == AllFPOData.end()) {<br>
+    Ctx.reportError(L, Twine("no FPO data found for symbol ") +<br>
+                           ProcSym->getName());<br>
+    return true;<br>
+  }<br>
+  const FPOData *FPO = I->second.get();<br>
+  assert(FPO->Begin && FPO->End && FPO->PrologueEnd && "missing FPO label");<br>
+<br>
+  MCSymbol *FrameBegin = Ctx.createTempSymbol(),<br>
+           *FrameEnd = Ctx.createTempSymbol();<br>
+<br>
+  OS.EmitIntValue(unsigned(Debug<wbr>SubsectionKind::FrameData), 4);<br>
+  OS.emitAbsoluteSymbolDiff(Fram<wbr>eEnd, FrameBegin, 4);<br>
+  OS.EmitLabel(FrameBegin);<br>
+<br>
+  // Start with the RVA of the function in question.<br>
+  OS.EmitValue(MCSymbolRefExpr::<wbr>create(FPO->Function,<br>
+                                       MCSymbolRefExpr::VK_COFF_IMGR<wbr>EL32, Ctx),<br>
+               4);<br>
+<br>
+  // Emit a sequence of FrameData records.<br>
+  FPOStateMachine FSM(FPO);<br>
+<br>
+  FSM.emitFrameDataRecord(OS, FPO->Begin);<br>
+  for (const FPOInstruction &Inst : FPO->Instructions) {<br>
+    switch (Inst.Op) {<br>
+    case FPOInstruction::PushReg:<br>
+      FSM.CurOffset += 4;<br>
+      FSM.SavedRegSize += 4;<br>
+      FSM.RegSaveOffsets.push_back({<wbr>Inst.RegOrOffset, FSM.CurOffset});<br>
+      break;<br>
+    case FPOInstruction::SetFrame:<br>
+      FSM.FrameReg = Inst.RegOrOffset;<br>
+      FSM.FrameRegOff = FSM.CurOffset;<br>
+      break;<br>
+    case FPOInstruction::StackAlloc:<br>
+      FSM.CurOffset += Inst.RegOrOffset;<br>
+      FSM.LocalSize += Inst.RegOrOffset;<br>
+      // No need to emit FrameData for stack allocations with a frame pointer.<br>
+      if (FSM.FrameReg)<br>
+        continue;<br>
+      break;<br>
+    }<br>
+    FSM.emitFrameDataRecord(OS, Inst.Label);<br>
+  }<br>
+<br>
+  OS.EmitValueToAlignment(4, 0);<br>
+  OS.EmitLabel(FrameEnd);<br>
+  return false;<br>
+}<br>
+<br>
+MCTargetStreamer *llvm::createX86AsmTargetStrea<wbr>mer(MCStreamer &S,<br>
+                                                   formatted_raw_ostream &OS,<br>
+                                                   MCInstPrinter *InstPrinter,<br>
+                                                   bool IsVerboseAsm) {<br>
+  // FIXME: This makes it so we textually assemble COFF directives on ELF.<br>
+  // That's kind of nonsensical.<br>
+  return new X86WinCOFFAsmTargetStreamer(S, OS, *InstPrinter);<br>
+}<br>
+<br>
+MCTargetStreamer *<br>
+llvm::createX86ObjectTargetSt<wbr>reamer(MCStreamer &S, const MCSubtargetInfo &STI) {<br>
+  // No need to register a target streamer.<br>
+  if (!STI.getTargetTriple().isOSBi<wbr>nFormatCOFF())<br>
+    return nullptr;<br>
+  // Registers itself to the MCStreamer.<br>
+  return new X86WinCOFFTargetStreamer(S);<br>
+}<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86A<wbr>smPrinter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86AsmPrinter.cpp?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/X86AsmPrinter.cpp?rev=315513<wbr>&r1=315512&r2=315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/X86A<wbr>smPrinter.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86A<wbr>smPrinter.cpp Wed Oct 11 14:24:33 2017<br>
@@ -15,6 +15,7 @@<br>
 #include "X86AsmPrinter.h"<br>
 #include "InstPrinter/X86ATTInstPrinter<wbr>.h"<br>
 #include "MCTargetDesc/X86BaseInfo.h"<br>
+#include "MCTargetDesc/X86TargetStreame<wbr>r.h"<br>
 #include "X86InstrInfo.h"<br>
 #include "X86MachineFunctionInfo.h"<br>
 #include "llvm/BinaryFormat/COFF.h"<br>
@@ -51,9 +52,12 @@ bool X86AsmPrinter::runOnMachineFun<wbr>ction<br>
<br>
   SMShadowTracker.<wbr>startFunction(MF);<br>
   CodeEmitter.reset(TM.getTarge<wbr>t().createMCCodeEmitter(<br>
-      *MF.getSubtarget().getInstrInf<wbr>o(), *MF.getSubtarget().getRegister<wbr>Info(),<br>
+      *Subtarget->getInstrInfo(), *Subtarget->getRegisterInfo(),<br>
       MF.getContext()));<br>
<br>
+  EmitFPOData =<br>
+      Subtarget->isTargetWin32() && MF.getMMI().getModule()->getCo<wbr>deViewFlag();<br>
+<br>
   SetupMachineFunction(MF);<br>
<br>
   if (Subtarget->isTargetCOFF()) {<br>
@@ -72,10 +76,30 @@ bool X86AsmPrinter::runOnMachineFun<wbr>ction<br>
   // Emit the XRay table for this function.<br>
   emitXRayTable();<br>
<br>
+  EmitFPOData = false;<br>
+<br>
   // We didn't modify anything.<br>
   return false;<br>
 }<br>
<br>
+void X86AsmPrinter::EmitFunctionBod<wbr>yStart() {<br>
+  if (EmitFPOData) {<br>
+    X86TargetStreamer *XTS =<br>
+        static_cast<X86TargetStreamer *>(OutStreamer->getTargetStrea<wbr>mer());<br>
+    unsigned ParamsSize =<br>
+        MF->getInfo<X86MachineFunction<wbr>Info>()->getArgumentStackSize(<wbr>);<br>
+    XTS->emitFPOProc(CurrentFnSym, ParamsSize);<br>
+  }<br>
+}<br>
+<br>
+void X86AsmPrinter::EmitFunctionBod<wbr>yEnd() {<br>
+  if (EmitFPOData) {<br>
+    X86TargetStreamer *XTS =<br>
+        static_cast<X86TargetStreamer *>(OutStreamer->getTargetStrea<wbr>mer());<br>
+    XTS->emitFPOEndProc();<br>
+  }<br>
+}<br>
+<br>
 /// printSymbolOperand - Print a raw symbol reference operand.  This handles<br>
 /// jump tables, constant pools, global address and external symbols, all of<br>
 /// which print to a label with various suffixes for relocation types etc.<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86A<wbr>smPrinter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86AsmPrinter.h?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/X86AsmPrinter.h?rev=315513&<wbr>r1=315512&r2=315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/X86A<wbr>smPrinter.h (original)<br>
+++ llvm/trunk/lib/Target/X86/X86A<wbr>smPrinter.h Wed Oct 11 14:24:33 2017<br>
@@ -30,6 +30,7 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrin<br>
   StackMaps SM;<br>
   FaultMaps FM;<br>
   std::unique_ptr<<wbr>MCCodeEmitter> CodeEmitter;<br>
+  bool EmitFPOData = false;<br>
<br>
   // This utility class tracks the length of a stackmap instruction's 'shadow'.<br>
   // It is used by the X86AsmPrinter to ensure that the stackmap shadow<br>
@@ -99,6 +100,9 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrin<br>
   // function.<br>
   void EmitXRayTable();<br>
<br>
+  // Choose between emitting .seh_ directives and .cv_fpo_ directives.<br>
+  void EmitSEHInstruction(const MachineInstr *MI);<br>
+<br>
 public:<br>
   explicit X86AsmPrinter(TargetMachine &TM,<br>
                          std::unique_ptr<MCStreamer> Streamer)<br>
@@ -137,6 +141,8 @@ public:<br>
   }<br>
<br>
   bool runOnMachineFunction(MachineFu<wbr>nction &F) override;<br>
+  void EmitFunctionBodyStart() override;<br>
+  void EmitFunctionBodyEnd() override;<br>
 };<br>
<br>
 } // end namespace llvm<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86F<wbr>rameLowering.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FrameLowering.cpp?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/X86FrameLowering.cpp?rev=315<wbr>513&r1=315512&r2=315513&view=<wbr>diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/X86F<wbr>rameLowering.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86F<wbr>rameLowering.cpp Wed Oct 11 14:24:33 2017<br>
@@ -924,6 +924,7 @@ void X86FrameLowering::BuildStackAl<wbr>ignAN<br>
<br>
   Notes:<br>
   - .seh directives are emitted only for Windows 64 ABI<br>
+  - .cv_fpo directives are emitted on win32 when emitting CodeView<br>
   - .cfi directives are emitted for all other ABIs<br>
   - for 32-bit code, substitute %e?? registers for %r??<br>
 */<br>
@@ -949,7 +950,9 @@ void X86FrameLowering::emitPrologue<wbr>(Mach<br>
   bool HasFP = hasFP(MF);<br>
   bool IsWin64CC = STI.isCallingConvWin64(Fn->get<wbr>CallingConv());<br>
   bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()-<wbr>>usesWindowsCFI();<br>
-  bool NeedsWinCFI = IsWin64Prologue && Fn->needsUnwindTableEntry();<br>
+  bool NeedsWin64CFI = IsWin64Prologue && Fn->needsUnwindTableEntry();<br>
+  bool NeedsWinFPO = STI.isTargetWin32() && MMI.getModule()->getCodeViewFl<wbr>ag();<br>
+  bool NeedsWinCFI = NeedsWin64CFI || NeedsWinFPO;<br>
   bool NeedsDwarfCFI =<br>
       !IsWin64Prologue && (MMI.hasDebugInfo() || Fn->needsUnwindTableEntry());<br>
   unsigned FramePtr = TRI->getFrameRegister(MF);<br>
@@ -958,7 +961,7 @@ void X86FrameLowering::emitPrologue<wbr>(Mach<br>
           ? getX86SubSuperRegister(FramePt<wbr>r, 64) : FramePtr;<br>
   unsigned BasePtr = TRI->getBaseRegister();<br>
   bool HasWinCFI = false;<br>
-<br>
+<br>
   // Debug location must be unknown since the first debug location is used<br>
   // to determine the end of the prologue.<br>
   DebugLoc DL;<br>
@@ -1120,6 +1123,15 @@ void X86FrameLowering::emitPrologue<wbr>(Mach<br>
         BuildCFI(MBB, MBBI, DL, MCCFIInstruction::createDefCfa<wbr>Register(<br>
                                     nullptr, DwarfFramePtr));<br>
       }<br>
+<br>
+      if (NeedsWinFPO) {<br>
+        // .cv_fpo_setframe $FramePtr<br>
+        HasWinCFI = true;<br>
+        BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SetFrame))<br>
+            .addImm(FramePtr)<br>
+            .addImm(0)<br>
+            .setMIFlag(MachineInstr::Frame<wbr>Setup);<br>
+      }<br>
     }<br>
   } else {<br>
     assert(!IsFunclet && "funclets without FPs not yet implemented");<br>
@@ -1155,8 +1167,9 @@ void X86FrameLowering::emitPrologue<wbr>(Mach<br>
<br>
     if (NeedsWinCFI) {<br>
       HasWinCFI = true;<br>
-      BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg)).add<wbr>Imm(Reg).setMIFlag(<br>
-          MachineInstr::FrameSetup);<br>
+      BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg))<br>
+          .addImm(Reg)<br>
+          .setMIFlag(MachineInstr::Frame<wbr>Setup);<br>
     }<br>
   }<br>
<br>
@@ -1295,6 +1308,7 @@ void X86FrameLowering::emitPrologue<wbr>(Mach<br>
<br>
     // If this is not a funclet, emit the CFI describing our frame pointer.<br>
     if (NeedsWinCFI && !IsFunclet) {<br>
+      assert(!NeedsWinFPO && "this setframe incompatible with FPO data");<br>
       HasWinCFI = true;<br>
       BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SetFrame))<br>
           .addImm(FramePtr)<br>
@@ -1333,6 +1347,7 @@ void X86FrameLowering::emitPrologue<wbr>(Mach<br>
           Offset += SEHFrameOffset;<br>
<br>
           HasWinCFI = true;<br>
+          assert(!NeedsWinFPO && "SEH_SaveXMM incompatible with FPO data");<br>
           BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SaveXMM))<br>
               .addImm(Reg)<br>
               .addImm(Offset)<br>
@@ -1534,7 +1549,7 @@ void X86FrameLowering::emitEpilogue<wbr>(Mach<br>
       Is64BitILP32 ? getX86SubSuperRegister(FramePt<wbr>r, 64) : FramePtr;<br>
<br>
   bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()-<wbr>>usesWindowsCFI();<br>
-  bool NeedsWinCFI =<br>
+  bool NeedsWin64CFI =<br>
       IsWin64Prologue && MF.getFunction()->needsUnwindT<wbr>ableEntry();<br>
   bool IsFunclet = MBBI == MBB.end() ? false : isFuncletReturnInstr(*MBBI);<br>
<br>
@@ -1639,7 +1654,7 @@ void X86FrameLowering::emitEpilogue<wbr>(Mach<br>
   // into the epilogue.  To cope with that, we insert an epilogue marker here,<br>
   // then replace it with a 'nop' if it ends up immediately after a CALL in the<br>
   // final emitted code.<br>
-  if (NeedsWinCFI && MF.hasWinCFI())<br>
+  if (NeedsWin64CFI && MF.hasWinCFI())<br>
     BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_Epilogue));<br>
<br>
   if (Terminator == MBB.end() || !isTailCallOpcode(Terminator-><wbr>getOpcode())) {<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86M<wbr>CInstLower.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MCInstLower.cpp?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/X86MCInstLower.cpp?rev=31551<wbr>3&r1=315512&r2=315513&view=<wbr>diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/X86M<wbr>CInstLower.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86M<wbr>CInstLower.cpp Wed Oct 11 14:24:33 2017<br>
@@ -15,6 +15,7 @@<br>
 #include "InstPrinter/X86ATTInstPrinter<wbr>.h"<br>
 #include "InstPrinter/X86InstComments.h<wbr>"<br>
 #include "MCTargetDesc/X86BaseInfo.h"<br>
+#include "MCTargetDesc/X86TargetStreame<wbr>r.h"<br>
 #include "Utils/X86ShuffleDecode.h"<br>
 #include "X86AsmPrinter.h"<br>
 #include "X86RegisterInfo.h"<br>
@@ -1363,6 +1364,82 @@ static void printConstant(const Constant<br>
   }<br>
 }<br>
<br>
+void X86AsmPrinter::EmitSEHInstruct<wbr>ion(const MachineInstr *MI) {<br>
+  assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");<br>
+  assert(getSubtarget().isOSWind<wbr>ows() && "SEH_ instruction Windows only");<br>
+  const X86RegisterInfo *RI =<br>
+      MF->getSubtarget<X86Subtarget><wbr>().getRegisterInfo();<br>
+<br>
+  // Use the .cv_fpo directives if we're emitting CodeView on 32-bit x86.<br>
+  if (EmitFPOData) {<br>
+    X86TargetStreamer *XTS =<br>
+        static_cast<X86TargetStreamer *>(OutStreamer->getTargetStrea<wbr>mer());<br>
+    switch (MI->getOpcode()) {<br>
+    case X86::SEH_PushReg:<br>
+      XTS->emitFPOPushReg(MI->getOpe<wbr>rand(0).getImm());<br>
+      break;<br>
+    case X86::SEH_StackAlloc:<br>
+      XTS->emitFPOStackAlloc(MI->get<wbr>Operand(0).getImm());<br>
+      break;<br>
+    case X86::SEH_SetFrame:<br>
+      assert(MI->getOperand(1).getIm<wbr>m() == 0 &&<br>
+             ".cv_fpo_setframe takes no offset");<br>
+      XTS->emitFPOSetFrame(MI->getOp<wbr>erand(0).getImm());<br>
+      break;<br>
+    case X86::SEH_EndPrologue:<br>
+      XTS->emitFPOEndPrologue();<br>
+      break;<br>
+    case X86::SEH_SaveReg:<br>
+    case X86::SEH_SaveXMM:<br>
+    case X86::SEH_PushFrame:<br>
+      llvm_unreachable("SEH_ directive incompatible with FPO");<br>
+      break;<br>
+    default:<br>
+      llvm_unreachable("expected SEH_ instruction");<br>
+    }<br>
+    return;<br>
+  }<br>
+<br>
+  // Otherwise, use the .seh_ directives for all other Windows platforms.<br>
+  switch (MI->getOpcode()) {<br>
+  case X86::SEH_PushReg:<br>
+    OutStreamer->EmitWinCFIPushReg<wbr>(<br>
+        RI->getSEHRegNum(MI->getOperan<wbr>d(0).getImm()));<br>
+    break;<br>
+<br>
+  case X86::SEH_SaveReg:<br>
+    OutStreamer->EmitWinCFISaveReg<wbr>(RI->getSEHRegNum(MI-><wbr>getOperand(0).getImm()),<br>
+                                   MI->getOperand(1).getImm());<br>
+    break;<br>
+<br>
+  case X86::SEH_SaveXMM:<br>
+    OutStreamer->EmitWinCFISaveXMM<wbr>(RI->getSEHRegNum(MI-><wbr>getOperand(0).getImm()),<br>
+                                   MI->getOperand(1).getImm());<br>
+    break;<br>
+<br>
+  case X86::SEH_StackAlloc:<br>
+    OutStreamer->EmitWinCFIAllocSt<wbr>ack(MI->getOperand(0).getImm()<wbr>);<br>
+    break;<br>
+<br>
+  case X86::SEH_SetFrame:<br>
+    OutStreamer->EmitWinCFISetFram<wbr>e(<br>
+        RI->getSEHRegNum(MI->getOperan<wbr>d(0).getImm()),<br>
+        MI->getOperand(1).getImm());<br>
+    break;<br>
+<br>
+  case X86::SEH_PushFrame:<br>
+    OutStreamer->EmitWinCFIPushFra<wbr>me(MI->getOperand(0).getImm())<wbr>;<br>
+    break;<br>
+<br>
+  case X86::SEH_EndPrologue:<br>
+    OutStreamer->EmitWinCFIEndProl<wbr>og();<br>
+    break;<br>
+<br>
+  default:<br>
+    llvm_unreachable("expected SEH_ instruction");<br>
+  }<br>
+}<br>
+<br>
 void X86AsmPrinter::EmitInstruction<wbr>(const MachineInstr *MI) {<br>
   X86MCInstLower MCInstLowering(*MF, *this);<br>
   const X86RegisterInfo *RI = MF->getSubtarget<X86Subtarget><wbr>().getRegisterInfo();<br>
@@ -1540,41 +1617,13 @@ void X86AsmPrinter::EmitInstruction<wbr>(cons<br>
     return;<br>
<br>
   case X86::SEH_PushReg:<br>
-    assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");<br>
-    OutStreamer->EmitWinCFIPushReg<wbr>(RI->getSEHRegNum(MI-><wbr>getOperand(0).getImm()));<br>
-    return;<br>
-<br>
   case X86::SEH_SaveReg:<br>
-    assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");<br>
-    OutStreamer->EmitWinCFISaveReg<wbr>(RI->getSEHRegNum(MI-><wbr>getOperand(0).getImm()),<br>
-                                   MI->getOperand(1).getImm());<br>
-    return;<br>
-<br>
   case X86::SEH_SaveXMM:<br>
-    assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");<br>
-    OutStreamer->EmitWinCFISaveXMM<wbr>(RI->getSEHRegNum(MI-><wbr>getOperand(0).getImm()),<br>
-                                   MI->getOperand(1).getImm());<br>
-    return;<br>
-<br>
   case X86::SEH_StackAlloc:<br>
-    assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");<br>
-    OutStreamer->EmitWinCFIAllocSt<wbr>ack(MI->getOperand(0).getImm()<wbr>);<br>
-    return;<br>
-<br>
   case X86::SEH_SetFrame:<br>
-    assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");<br>
-    OutStreamer->EmitWinCFISetFram<wbr>e(RI->getSEHRegNum(MI-><wbr>getOperand(0).getImm()),<br>
-                                    MI->getOperand(1).getImm());<br>
-    return;<br>
-<br>
   case X86::SEH_PushFrame:<br>
-    assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");<br>
-    OutStreamer->EmitWinCFIPushFra<wbr>me(MI->getOperand(0).getImm())<wbr>;<br>
-    return;<br>
-<br>
   case X86::SEH_EndPrologue:<br>
-    assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");<br>
-    OutStreamer->EmitWinCFIEndProl<wbr>og();<br>
+    EmitSEHInstruction(MI);<br>
     return;<br>
<br>
   case X86::SEH_Epilogue: {<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86S<wbr>ubtarget.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.h?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/X86Subtarget.h?rev=315513&r1<wbr>=315512&r2=315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/X86S<wbr>ubtarget.h (original)<br>
+++ llvm/trunk/lib/Target/X86/X86S<wbr>ubtarget.h Wed Oct 11 14:24:33 2017<br>
@@ -592,13 +592,9 @@ public:<br>
<br>
   bool isOSWindows() const { return TargetTriple.isOSWindows(); }<br>
<br>
-  bool isTargetWin64() const {<br>
-    return In64BitMode && TargetTriple.isOSWindows();<br>
-  }<br>
+  bool isTargetWin64() const { return In64BitMode && isOSWindows(); }<br>
<br>
-  bool isTargetWin32() const {<br>
-    return !In64BitMode && (isTargetCygMing() || isTargetKnownWindowsMSVC());<br>
-  }<br>
+  bool isTargetWin32() const { return !In64BitMode && isOSWindows(); }<br>
<br>
   bool isPICStyleGOT() const { return PICStyle == PICStyles::GOT; }<br>
   bool isPICStyleRIPRel() const { return PICStyle == PICStyles::RIPRel; }<br>
<br>
Modified: llvm/trunk/test/DebugInfo/COFF<wbr>/asan-module-ctor.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/asan-module-ctor.ll?rev=315513&r1=315512&r2=315513&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/DebugInf<wbr>o/COFF/asan-module-ctor.ll?<wbr>rev=315513&r1=315512&r2=<wbr>315513&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/DebugInfo/COFF<wbr>/asan-module-ctor.ll (original)<br>
+++ llvm/trunk/test/DebugInfo/COFF<wbr>/asan-module-ctor.ll Wed Oct 11 14:24:33 2017<br>
@@ -10,7 +10,7 @@<br>
 ; The module ctor has no debug info.  All we have to do is don't crash.<br>
 ; X86: _asan.module_ctor:<br>
 ; X86-NEXT: L{{.*}}:<br>
-; X86-NEXT: # BB<br>
+; X86:      # BB<br>
 ; X86-NEXT: calll   ___asan_init_v3<br>
 ; X86-NEXT: retl<br>
<br>
<br>
Added: llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-argsize.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/fpo-argsize.ll?rev=315513&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/DebugInf<wbr>o/COFF/fpo-argsize.ll?rev=<wbr>315513&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-argsize.ll (added)<br>
+++ llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-argsize.ll Wed Oct 11 14:24:33 2017<br>
@@ -0,0 +1,454 @@<br>
+; RUN: llc < %s | grep cv_fpo_proc | FileCheck %s<br>
+<br>
+; C++ source:<br>
+; extern "C" {<br>
+; extern int g;<br>
+;<br>
+; void cdecl1(int a) { g += a; }<br>
+; void cdecl2(int a, int b) { g += a + b; }<br>
+; void cdecl3(int a, int b, int c) { g += a + b + c; }<br>
+;<br>
+; void __fastcall fastcall1(int a) { g += a; }<br>
+; void __fastcall fastcall2(int a, int b) { g += a + b; }<br>
+; void __fastcall fastcall3(int a, int b, int c) { g += a + b + c; }<br>
+;<br>
+; void __stdcall stdcall1(int a) { g += a; }<br>
+; void __stdcall stdcall2(int a, int b) { g += a + b; }<br>
+; void __stdcall stdcall3(int a, int b, int c) { g += a + b + c; }<br>
+; }<br>
+;<br>
+; struct Foo {<br>
+;   void thiscall1(int a);<br>
+;   void thiscall2(int a, int b);<br>
+;   void thiscall3(int a, int b, int c);<br>
+; };<br>
+;<br>
+; void Foo::thiscall1(int a) { g += a; }<br>
+; void Foo::thiscall2(int a, int b) { g += a + b; }<br>
+; void Foo::thiscall3(int a, int b, int c) { g += a + b + c; }<br>
+<br>
+; CHECK: .cv_fpo_proc    _cdecl1 4<br>
+; CHECK: .cv_fpo_proc    _cdecl2 8<br>
+; CHECK: .cv_fpo_proc    _cdecl3 12<br>
+<br>
+; First two args are in registers and don't count.<br>
+; CHECK: .cv_fpo_proc    @fastcall1@4 0<br>
+; CHECK: .cv_fpo_proc    @fastcall2@8 0<br>
+; CHECK: .cv_fpo_proc    @fastcall3@12 4<br>
+<br>
+; CHECK: .cv_fpo_proc    _stdcall1@4 4<br>
+; CHECK: .cv_fpo_proc    _stdcall2@8 8<br>
+; CHECK: .cv_fpo_proc    _stdcall3@12 12<br>
+<br>
+; 'this' is in ecx and doesn't count.<br>
+; CHECK: .cv_fpo_proc    "?thiscall1@Foo@@QAEXH@Z" 4<br>
+; CHECK: .cv_fpo_proc    "?thiscall2@Foo@@QAEXHH@Z" 8<br>
+; CHECK: .cv_fpo_proc    "?thiscall3@Foo@@QAEXHHH@Z" 12<br>
+<br>
+; ModuleID = 't.c'<br>
+source_filename = "t.c"<br>
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n<wbr>8:16:32-a:0:32-S32"<br>
+target triple = "i386-pc-windows-msvc19.11.255<wbr>08"<br>
+<br>
+%struct.Foo = type { i8 }<br>
+<br>
+@g = external global i32, align 4<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define void @cdecl1(i32 %a) #0 !dbg !8 {<br>
+entry:<br>
+  %a.addr = alloca i32, align 4<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !12, metadata !DIExpression()), !dbg !13<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !14<br>
+  %1 = load i32, i32* @g, align 4, !dbg !15<br>
+  %add = add nsw i32 %1, %0, !dbg !15<br>
+  store i32 %add, i32* @g, align 4, !dbg !15<br>
+  ret void, !dbg !16<br>
+}<br>
+<br>
+; Function Attrs: nounwind readnone speculatable<br>
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define void @cdecl2(i32 %a, i32 %b) #0 !dbg !17 {<br>
+entry:<br>
+  %b.addr = alloca i32, align 4<br>
+  %a.addr = alloca i32, align 4<br>
+  store i32 %b, i32* %b.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !20, metadata !DIExpression()), !dbg !21<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !22, metadata !DIExpression()), !dbg !23<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !24<br>
+  %1 = load i32, i32* %b.addr, align 4, !dbg !25<br>
+  %add = add nsw i32 %0, %1, !dbg !26<br>
+  %2 = load i32, i32* @g, align 4, !dbg !27<br>
+  %add1 = add nsw i32 %2, %add, !dbg !27<br>
+  store i32 %add1, i32* @g, align 4, !dbg !27<br>
+  ret void, !dbg !28<br>
+}<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define void @cdecl3(i32 %a, i32 %b, i32 %c) #0 !dbg !29 {<br>
+entry:<br>
+  %c.addr = alloca i32, align 4<br>
+  %b.addr = alloca i32, align 4<br>
+  %a.addr = alloca i32, align 4<br>
+  store i32 %c, i32* %c.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %c.addr, metadata !32, metadata !DIExpression()), !dbg !33<br>
+  store i32 %b, i32* %b.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !34, metadata !DIExpression()), !dbg !35<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !36, metadata !DIExpression()), !dbg !37<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !38<br>
+  %1 = load i32, i32* %b.addr, align 4, !dbg !39<br>
+  %add = add nsw i32 %0, %1, !dbg !40<br>
+  %2 = load i32, i32* %c.addr, align 4, !dbg !41<br>
+  %add1 = add nsw i32 %add, %2, !dbg !42<br>
+  %3 = load i32, i32* @g, align 4, !dbg !43<br>
+  %add2 = add nsw i32 %3, %add1, !dbg !43<br>
+  store i32 %add2, i32* @g, align 4, !dbg !43<br>
+  ret void, !dbg !44<br>
+}<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define x86_fastcallcc void @"\01@fastcall1@4"(i32 inreg %a) #0 !dbg !45 {<br>
+entry:<br>
+  %a.addr = alloca i32, align 4<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !47, metadata !DIExpression()), !dbg !48<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !49<br>
+  %1 = load i32, i32* @g, align 4, !dbg !50<br>
+  %add = add nsw i32 %1, %0, !dbg !50<br>
+  store i32 %add, i32* @g, align 4, !dbg !50<br>
+  ret void, !dbg !51<br>
+}<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define x86_fastcallcc void @"\01@fastcall2@8"(i32 inreg %a, i32 inreg %b) #0 !dbg !52 {<br>
+entry:<br>
+  %b.addr = alloca i32, align 4<br>
+  %a.addr = alloca i32, align 4<br>
+  store i32 %b, i32* %b.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !54, metadata !DIExpression()), !dbg !55<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !56, metadata !DIExpression()), !dbg !57<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !58<br>
+  %1 = load i32, i32* %b.addr, align 4, !dbg !59<br>
+  %add = add nsw i32 %0, %1, !dbg !60<br>
+  %2 = load i32, i32* @g, align 4, !dbg !61<br>
+  %add1 = add nsw i32 %2, %add, !dbg !61<br>
+  store i32 %add1, i32* @g, align 4, !dbg !61<br>
+  ret void, !dbg !62<br>
+}<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define x86_fastcallcc void @"\01@fastcall3@12"(i32 inreg %a, i32 inreg %b, i32 %c) #0 !dbg !63 {<br>
+entry:<br>
+  %c.addr = alloca i32, align 4<br>
+  %b.addr = alloca i32, align 4<br>
+  %a.addr = alloca i32, align 4<br>
+  store i32 %c, i32* %c.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %c.addr, metadata !65, metadata !DIExpression()), !dbg !66<br>
+  store i32 %b, i32* %b.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !67, metadata !DIExpression()), !dbg !68<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !69, metadata !DIExpression()), !dbg !70<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !71<br>
+  %1 = load i32, i32* %b.addr, align 4, !dbg !72<br>
+  %add = add nsw i32 %0, %1, !dbg !73<br>
+  %2 = load i32, i32* %c.addr, align 4, !dbg !74<br>
+  %add1 = add nsw i32 %add, %2, !dbg !75<br>
+  %3 = load i32, i32* @g, align 4, !dbg !76<br>
+  %add2 = add nsw i32 %3, %add1, !dbg !76<br>
+  store i32 %add2, i32* @g, align 4, !dbg !76<br>
+  ret void, !dbg !77<br>
+}<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define x86_stdcallcc void @"\01_stdcall1@4"(i32 %a) #0 !dbg !78 {<br>
+entry:<br>
+  %a.addr = alloca i32, align 4<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !80, metadata !DIExpression()), !dbg !81<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !82<br>
+  %1 = load i32, i32* @g, align 4, !dbg !83<br>
+  %add = add nsw i32 %1, %0, !dbg !83<br>
+  store i32 %add, i32* @g, align 4, !dbg !83<br>
+  ret void, !dbg !84<br>
+}<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define x86_stdcallcc void @"\01_stdcall2@8"(i32 %a, i32 %b) #0 !dbg !85 {<br>
+entry:<br>
+  %b.addr = alloca i32, align 4<br>
+  %a.addr = alloca i32, align 4<br>
+  store i32 %b, i32* %b.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !87, metadata !DIExpression()), !dbg !88<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !89, metadata !DIExpression()), !dbg !90<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !91<br>
+  %1 = load i32, i32* %b.addr, align 4, !dbg !92<br>
+  %add = add nsw i32 %0, %1, !dbg !93<br>
+  %2 = load i32, i32* @g, align 4, !dbg !94<br>
+  %add1 = add nsw i32 %2, %add, !dbg !94<br>
+  store i32 %add1, i32* @g, align 4, !dbg !94<br>
+  ret void, !dbg !95<br>
+}<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define x86_stdcallcc void @"\01_stdcall3@12"(i32 %a, i32 %b, i32 %c) #0 !dbg !96 {<br>
+entry:<br>
+  %c.addr = alloca i32, align 4<br>
+  %b.addr = alloca i32, align 4<br>
+  %a.addr = alloca i32, align 4<br>
+  store i32 %c, i32* %c.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %c.addr, metadata !98, metadata !DIExpression()), !dbg !99<br>
+  store i32 %b, i32* %b.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !100, metadata !DIExpression()), !dbg !101<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !102, metadata !DIExpression()), !dbg !103<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !104<br>
+  %1 = load i32, i32* %b.addr, align 4, !dbg !105<br>
+  %add = add nsw i32 %0, %1, !dbg !106<br>
+  %2 = load i32, i32* %c.addr, align 4, !dbg !107<br>
+  %add1 = add nsw i32 %add, %2, !dbg !108<br>
+  %3 = load i32, i32* @g, align 4, !dbg !109<br>
+  %add2 = add nsw i32 %3, %add1, !dbg !109<br>
+  store i32 %add2, i32* @g, align 4, !dbg !109<br>
+  ret void, !dbg !110<br>
+}<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define x86_thiscallcc void @"\01?thiscall1@Foo@@QAEXH@Z"(<wbr>%struct.Foo* %this, i32 %a) #0 align 2 !dbg !111 {<br>
+entry:<br>
+  %a.addr = alloca i32, align 4<br>
+  %this.addr = alloca %struct.Foo*, align 4<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !124, metadata !DIExpression()), !dbg !125<br>
+  store %struct.Foo* %this, %struct.Foo** %this.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata %struct.Foo** %this.addr, metadata !126, metadata !DIExpression()), !dbg !128<br>
+  %this1 = load %struct.Foo*, %struct.Foo** %this.addr, align 4<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !129<br>
+  %1 = load i32, i32* @g, align 4, !dbg !130<br>
+  %add = add nsw i32 %1, %0, !dbg !130<br>
+  store i32 %add, i32* @g, align 4, !dbg !130<br>
+  ret void, !dbg !131<br>
+}<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define x86_thiscallcc void @"\01?thiscall2@Foo@@QAEXHH@Z"<wbr>(%struct.Foo* %this, i32 %a, i32 %b) #0 align 2 !dbg !132 {<br>
+entry:<br>
+  %b.addr = alloca i32, align 4<br>
+  %a.addr = alloca i32, align 4<br>
+  %this.addr = alloca %struct.Foo*, align 4<br>
+  store i32 %b, i32* %b.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !133, metadata !DIExpression()), !dbg !134<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !135, metadata !DIExpression()), !dbg !136<br>
+  store %struct.Foo* %this, %struct.Foo** %this.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata %struct.Foo** %this.addr, metadata !137, metadata !DIExpression()), !dbg !138<br>
+  %this1 = load %struct.Foo*, %struct.Foo** %this.addr, align 4<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !139<br>
+  %1 = load i32, i32* %b.addr, align 4, !dbg !140<br>
+  %add = add nsw i32 %0, %1, !dbg !141<br>
+  %2 = load i32, i32* @g, align 4, !dbg !142<br>
+  %add2 = add nsw i32 %2, %add, !dbg !142<br>
+  store i32 %add2, i32* @g, align 4, !dbg !142<br>
+  ret void, !dbg !143<br>
+}<br>
+<br>
+; Function Attrs: noinline nounwind optnone<br>
+define x86_thiscallcc void @"\01?thiscall3@Foo@@QAEXHHH@Z<wbr>"(%struct.Foo* %this, i32 %a, i32 %b, i32 %c) #0 align 2 !dbg !144 {<br>
+entry:<br>
+  %c.addr = alloca i32, align 4<br>
+  %b.addr = alloca i32, align 4<br>
+  %a.addr = alloca i32, align 4<br>
+  %this.addr = alloca %struct.Foo*, align 4<br>
+  store i32 %c, i32* %c.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %c.addr, metadata !145, metadata !DIExpression()), !dbg !146<br>
+  store i32 %b, i32* %b.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !147, metadata !DIExpression()), !dbg !148<br>
+  store i32 %a, i32* %a.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !149, metadata !DIExpression()), !dbg !150<br>
+  store %struct.Foo* %this, %struct.Foo** %this.addr, align 4<br>
+  call void @llvm.dbg.declare(metadata %struct.Foo** %this.addr, metadata !151, metadata !DIExpression()), !dbg !152<br>
+  %this1 = load %struct.Foo*, %struct.Foo** %this.addr, align 4<br>
+  %0 = load i32, i32* %a.addr, align 4, !dbg !153<br>
+  %1 = load i32, i32* %b.addr, align 4, !dbg !154<br>
+  %add = add nsw i32 %0, %1, !dbg !155<br>
+  %2 = load i32, i32* %c.addr, align 4, !dbg !156<br>
+  %add2 = add nsw i32 %add, %2, !dbg !157<br>
+  %3 = load i32, i32* @g, align 4, !dbg !158<br>
+  %add3 = add nsw i32 %3, %add2, !dbg !158<br>
+  store i32 %add3, i32* @g, align 4, !dbg !158<br>
+  ret void, !dbg !159<br>
+}<br>
+<br>
+attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt<wbr>-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-lea<wbr>f" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="fal<wbr>se" "no-trapping-math"="false" "stack-protector-buffer-size"=<wbr>"8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,<wbr>+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }<br>
+attributes #1 = { nounwind readnone speculatable }<br>
+<br>
+!<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
+!llvm.module.flags = !{!3, !4, !5, !6}<br>
+!llvm.ident = !{!7}<br>
+<br>
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)<br>
+!1 = !DIFile(filename: "t.c", directory: "C:\5Csrc\5Cllvm-project\5Cbui<wbr>ld", checksumkind: CSK_MD5, checksum: "0ce3e4edcf2f8511157da4edb99fc<wbr>df4")<br>
+!2 = !{}<br>
+!3 = !{i32 1, !"NumRegisterParameters", i32 0}<br>
+!4 = !{i32 2, !"CodeView", i32 1}<br>
+!5 = !{i32 2, !"Debug Info Version", i32 3}<br>
+!6 = !{i32 1, !"wchar_size", i32 2}<br>
+!7 = !{!"clang version 6.0.0 "}<br>
+!8 = distinct !DISubprogram(name: "cdecl1", scope: !1, file: !1, line: 4, type: !9, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)<br>
+!9 = !DISubroutineType(types: !10)<br>
+!10 = !{null, !11}<br>
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
+!12 = !DILocalVariable(name: "a", arg: 1, scope: !8, file: !1, line: 4, type: !11)<br>
+!13 = !DILocation(line: 4, column: 17, scope: !8)<br>
+!14 = !DILocation(line: 4, column: 27, scope: !8)<br>
+!15 = !DILocation(line: 4, column: 24, scope: !8)<br>
+!16 = !DILocation(line: 4, column: 30, scope: !8)<br>
+!17 = distinct !DISubprogram(name: "cdecl2", scope: !1, file: !1, line: 5, type: !18, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)<br>
+!18 = !DISubroutineType(types: !19)<br>
+!19 = !{null, !11, !11}<br>
+!20 = !DILocalVariable(name: "b", arg: 2, scope: !17, file: !1, line: 5, type: !11)<br>
+!21 = !DILocation(line: 5, column: 24, scope: !17)<br>
+!22 = !DILocalVariable(name: "a", arg: 1, scope: !17, file: !1, line: 5, type: !11)<br>
+!23 = !DILocation(line: 5, column: 17, scope: !17)<br>
+!24 = !DILocation(line: 5, column: 34, scope: !17)<br>
+!25 = !DILocation(line: 5, column: 38, scope: !17)<br>
+!26 = !DILocation(line: 5, column: 36, scope: !17)<br>
+!27 = !DILocation(line: 5, column: 31, scope: !17)<br>
+!28 = !DILocation(line: 5, column: 41, scope: !17)<br>
+!29 = distinct !DISubprogram(name: "cdecl3", scope: !1, file: !1, line: 6, type: !30, isLocal: false, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)<br>
+!30 = !DISubroutineType(types: !31)<br>
+!31 = !{null, !11, !11, !11}<br>
+!32 = !DILocalVariable(name: "c", arg: 3, scope: !29, file: !1, line: 6, type: !11)<br>
+!33 = !DILocation(line: 6, column: 31, scope: !29)<br>
+!34 = !DILocalVariable(name: "b", arg: 2, scope: !29, file: !1, line: 6, type: !11)<br>
+!35 = !DILocation(line: 6, column: 24, scope: !29)<br>
+!36 = !DILocalVariable(name: "a", arg: 1, scope: !29, file: !1, line: 6, type: !11)<br>
+!37 = !DILocation(line: 6, column: 17, scope: !29)<br>
+!38 = !DILocation(line: 6, column: 41, scope: !29)<br>
+!39 = !DILocation(line: 6, column: 45, scope: !29)<br>
+!40 = !DILocation(line: 6, column: 43, scope: !29)<br>
+!41 = !DILocation(line: 6, column: 49, scope: !29)<br>
+!42 = !DILocation(line: 6, column: 47, scope: !29)<br>
+!43 = !DILocation(line: 6, column: 38, scope: !29)<br>
+!44 = !DILocation(line: 6, column: 52, scope: !29)<br>
+!45 = distinct !DISubprogram(name: "fastcall1", linkageName: "\01@fastcall1@4", scope: !1, file: !1, line: 8, type: !46, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)<br>
+!46 = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: !10)<br>
+!47 = !DILocalVariable(name: "a", arg: 1, scope: !45, file: !1, line: 8, type: !11)<br>
+!48 = !DILocation(line: 8, column: 31, scope: !45)<br>
+!49 = !DILocation(line: 8, column: 41, scope: !45)<br>
+!50 = !DILocation(line: 8, column: 38, scope: !45)<br>
+!51 = !DILocation(line: 8, column: 44, scope: !45)<br>
+!52 = distinct !DISubprogram(name: "fastcall2", linkageName: "\01@fastcall2@8", scope: !1, file: !1, line: 9, type: !53, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)<br>
+!53 = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: !19)<br>
+!54 = !DILocalVariable(name: "b", arg: 2, scope: !52, file: !1, line: 9, type: !11)<br>
+!55 = !DILocation(line: 9, column: 38, scope: !52)<br>
+!56 = !DILocalVariable(name: "a", arg: 1, scope: !52, file: !1, line: 9, type: !11)<br>
+!57 = !DILocation(line: 9, column: 31, scope: !52)<br>
+!58 = !DILocation(line: 9, column: 48, scope: !52)<br>
+!59 = !DILocation(line: 9, column: 52, scope: !52)<br>
+!60 = !DILocation(line: 9, column: 50, scope: !52)<br>
+!61 = !DILocation(line: 9, column: 45, scope: !52)<br>
+!62 = !DILocation(line: 9, column: 55, scope: !52)<br>
+!63 = distinct !DISubprogram(name: "fastcall3", linkageName: "\01@fastcall3@12", scope: !1, file: !1, line: 10, type: !64, isLocal: false, isDefinition: true, scopeLine: 10, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)<br>
+!64 = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: !31)<br>
+!65 = !DILocalVariable(name: "c", arg: 3, scope: !63, file: !1, line: 10, type: !11)<br>
+!66 = !DILocation(line: 10, column: 45, scope: !63)<br>
+!67 = !DILocalVariable(name: "b", arg: 2, scope: !63, file: !1, line: 10, type: !11)<br>
+!68 = !DILocation(line: 10, column: 38, scope: !63)<br>
+!69 = !DILocalVariable(name: "a", arg: 1, scope: !63, file: !1, line: 10, type: !11)<br>
+!70 = !DILocation(line: 10, column: 31, scope: !63)<br>
+!71 = !DILocation(line: 10, column: 55, scope: !63)<br>
+!72 = !DILocation(line: 10, column: 59, scope: !63)<br>
+!73 = !DILocation(line: 10, column: 57, scope: !63)<br>
+!74 = !DILocation(line: 10, column: 63, scope: !63)<br>
+!75 = !DILocation(line: 10, column: 61, scope: !63)<br>
+!76 = !DILocation(line: 10, column: 52, scope: !63)<br>
+!77 = !DILocation(line: 10, column: 66, scope: !63)<br>
+!78 = distinct !DISubprogram(name: "stdcall1", linkageName: "\01_stdcall1@4", scope: !1, file: !1, line: 12, type: !79, isLocal: false, isDefinition: true, scopeLine: 12, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)<br>
+!79 = !DISubroutineType(cc: DW_CC_BORLAND_stdcall, types: !10)<br>
+!80 = !DILocalVariable(name: "a", arg: 1, scope: !78, file: !1, line: 12, type: !11)<br>
+!81 = !DILocation(line: 12, column: 29, scope: !78)<br>
+!82 = !DILocation(line: 12, column: 39, scope: !78)<br>
+!83 = !DILocation(line: 12, column: 36, scope: !78)<br>
+!84 = !DILocation(line: 12, column: 42, scope: !78)<br>
+!85 = distinct !DISubprogram(name: "stdcall2", linkageName: "\01_stdcall2@8", scope: !1, file: !1, line: 13, type: !86, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)<br>
+!86 = !DISubroutineType(cc: DW_CC_BORLAND_stdcall, types: !19)<br>
+!87 = !DILocalVariable(name: "b", arg: 2, scope: !85, file: !1, line: 13, type: !11)<br>
+!88 = !DILocation(line: 13, column: 36, scope: !85)<br>
+!89 = !DILocalVariable(name: "a", arg: 1, scope: !85, file: !1, line: 13, type: !11)<br>
+!90 = !DILocation(line: 13, column: 29, scope: !85)<br>
+!91 = !DILocation(line: 13, column: 46, scope: !85)<br>
+!92 = !DILocation(line: 13, column: 50, scope: !85)<br>
+!93 = !DILocation(line: 13, column: 48, scope: !85)<br>
+!94 = !DILocation(line: 13, column: 43, scope: !85)<br>
+!95 = !DILocation(line: 13, column: 53, scope: !85)<br>
+!96 = distinct !DISubprogram(name: "stdcall3", linkageName: "\01_stdcall3@12", scope: !1, file: !1, line: 14, type: !97, isLocal: false, isDefinition: true, scopeLine: 14, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)<br>
+!97 = !DISubroutineType(cc: DW_CC_BORLAND_stdcall, types: !31)<br>
+!98 = !DILocalVariable(name: "c", arg: 3, scope: !96, file: !1, line: 14, type: !11)<br>
+!99 = !DILocation(line: 14, column: 43, scope: !96)<br>
+!100 = !DILocalVariable(name: "b", arg: 2, scope: !96, file: !1, line: 14, type: !11)<br>
+!101 = !DILocation(line: 14, column: 36, scope: !96)<br>
+!102 = !DILocalVariable(name: "a", arg: 1, scope: !96, file: !1, line: 14, type: !11)<br>
+!103 = !DILocation(line: 14, column: 29, scope: !96)<br>
+!104 = !DILocation(line: 14, column: 53, scope: !96)<br>
+!105 = !DILocation(line: 14, column: 57, scope: !96)<br>
+!106 = !DILocation(line: 14, column: 55, scope: !96)<br>
+!107 = !DILocation(line: 14, column: 61, scope: !96)<br>
+!108 = !DILocation(line: 14, column: 59, scope: !96)<br>
+!109 = !DILocation(line: 14, column: 50, scope: !96)<br>
+!110 = !DILocation(line: 14, column: 64, scope: !96)<br>
+!111 = distinct !DISubprogram(name: "thiscall1", linkageName: "\01?thiscall1@Foo@@QAEXH@Z", scope: !112, file: !1, line: 23, type: !115, isLocal: false, isDefinition: true, scopeLine: 23, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !114, variables: !2)<br>
+!112 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 17, size: 8, elements: !113, identifier: ".?AUFoo@@")<br>
+!113 = !{!114, !118, !121}<br>
+!114 = !DISubprogram(name: "thiscall1", linkageName: "\01?thiscall1@Foo@@QAEXH@Z", scope: !112, file: !1, line: 18, type: !115, isLocal: false, isDefinition: false, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: false)<br>
+!115 = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: !116)<br>
+!116 = !{null, !117, !11}<br>
+!117 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !112, size: 32, flags: DIFlagArtificial | DIFlagObjectPointer)<br>
+!118 = !DISubprogram(name: "thiscall2", linkageName: "\01?thiscall2@Foo@@QAEXHH@Z", scope: !112, file: !1, line: 19, type: !119, isLocal: false, isDefinition: false, scopeLine: 19, flags: DIFlagPrototyped, isOptimized: false)<br>
+!119 = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: !120)<br>
+!120 = !{null, !117, !11, !11}<br>
+!121 = !DISubprogram(name: "thiscall3", linkageName: "\01?thiscall3@Foo@@QAEXHHH@Z"<wbr>, scope: !112, file: !1, line: 20, type: !122, isLocal: false, isDefinition: false, scopeLine: 20, flags: DIFlagPrototyped, isOptimized: false)<br>
+!122 = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: !123)<br>
+!123 = !{null, !117, !11, !11, !11}<br>
+!124 = !DILocalVariable(name: "a", arg: 2, scope: !111, file: !1, line: 23, type: !11)<br>
+!125 = !DILocation(line: 23, column: 25, scope: !111)<br>
+!126 = !DILocalVariable(name: "this", arg: 1, scope: !111, type: !127, flags: DIFlagArtificial | DIFlagObjectPointer)<br>
+!127 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !112, size: 32)<br>
+!128 = !DILocation(line: 0, scope: !111)<br>
+!129 = !DILocation(line: 23, column: 35, scope: !111)<br>
+!130 = !DILocation(line: 23, column: 32, scope: !111)<br>
+!131 = !DILocation(line: 23, column: 38, scope: !111)<br>
+!132 = distinct !DISubprogram(name: "thiscall2", linkageName: "\01?thiscall2@Foo@@QAEXHH@Z", scope: !112, file: !1, line: 24, type: !119, isLocal: false, isDefinition: true, scopeLine: 24, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !118, variables: !2)<br>
+!133 = !DILocalVariable(name: "b", arg: 3, scope: !132, file: !1, line: 24, type: !11)<br>
+!134 = !DILocation(line: 24, column: 32, scope: !132)<br>
+!135 = !DILocalVariable(name: "a", arg: 2, scope: !132, file: !1, line: 24, type: !11)<br>
+!136 = !DILocation(line: 24, column: 25, scope: !132)<br>
+!137 = !DILocalVariable(name: "this", arg: 1, scope: !132, type: !127, flags: DIFlagArtificial | DIFlagObjectPointer)<br>
+!138 = !DILocation(line: 0, scope: !132)<br>
+!139 = !DILocation(line: 24, column: 42, scope: !132)<br>
+!140 = !DILocation(line: 24, column: 46, scope: !132)<br>
+!141 = !DILocation(line: 24, column: 44, scope: !132)<br>
+!142 = !DILocation(line: 24, column: 39, scope: !132)<br>
+!143 = !DILocation(line: 24, column: 49, scope: !132)<br>
+!144 = distinct !DISubprogram(name: "thiscall3", linkageName: "\01?thiscall3@Foo@@QAEXHHH@Z"<wbr>, scope: !112, file: !1, line: 25, type: !122, isLocal: false, isDefinition: true, scopeLine: 25, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !121, variables: !2)<br>
+!145 = !DILocalVariable(name: "c", arg: 4, scope: !144, file: !1, line: 25, type: !11)<br>
+!146 = !DILocation(line: 25, column: 39, scope: !144)<br>
+!147 = !DILocalVariable(name: "b", arg: 3, scope: !144, file: !1, line: 25, type: !11)<br>
+!148 = !DILocation(line: 25, column: 32, scope: !144)<br>
+!149 = !DILocalVariable(name: "a", arg: 2, scope: !144, file: !1, line: 25, type: !11)<br>
+!150 = !DILocation(line: 25, column: 25, scope: !144)<br>
+!151 = !DILocalVariable(name: "this", arg: 1, scope: !144, type: !127, flags: DIFlagArtificial | DIFlagObjectPointer)<br>
+!152 = !DILocation(line: 0, scope: !144)<br>
+!153 = !DILocation(line: 25, column: 49, scope: !144)<br>
+!154 = !DILocation(line: 25, column: 53, scope: !144)<br>
+!155 = !DILocation(line: 25, column: 51, scope: !144)<br>
+!156 = !DILocation(line: 25, column: 57, scope: !144)<br>
+!157 = !DILocation(line: 25, column: 55, scope: !144)<br>
+!158 = !DILocation(line: 25, column: 46, scope: !144)<br>
+!159 = !DILocation(line: 25, column: 60, scope: !144)<br>
<br>
Added: llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-csrs.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/fpo-csrs.ll?rev=315513&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/DebugInf<wbr>o/COFF/fpo-csrs.ll?rev=315513&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-csrs.ll (added)<br>
+++ llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-csrs.ll Wed Oct 11 14:24:33 2017<br>
@@ -0,0 +1,559 @@<br>
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM<br>
+; RUN: llc -filetype=obj < %s | llvm-readobj -codeview | FileCheck %s --check-prefix=OBJ<br>
+<br>
+; C source:<br>
+; int getval(void);<br>
+; void usevals(int, ...);<br>
+; int csr1() {<br>
+;   int a = getval();<br>
+;   usevals(a);<br>
+;   usevals(a);<br>
+;   return a;<br>
+; }<br>
+; int csr2() {<br>
+;   int a = getval();<br>
+;   int b = getval();<br>
+;   usevals(a, b);<br>
+;   usevals(a, b);<br>
+;   return a;<br>
+; }<br>
+; int csr3() {<br>
+;   int a = getval();<br>
+;   int b = getval();<br>
+;   int c = getval();<br>
+;   usevals(a, b, c);<br>
+;   usevals(a, b, c);<br>
+;   return a;<br>
+; }<br>
+; int csr4() {<br>
+;   int a = getval();<br>
+;   int b = getval();<br>
+;   int c = getval();<br>
+;   int d = getval();<br>
+;   usevals(a, b, c, d);<br>
+;   usevals(a, b, c, d);<br>
+;   return a;<br>
+; }<br>
+; int spill() {<br>
+;   int a = getval();<br>
+;   int b = getval();<br>
+;   int c = getval();<br>
+;   int d = getval();<br>
+;   int e = getval();<br>
+;   usevals(a, b, c, d, e);<br>
+;   usevals(a, b, c, d, e);<br>
+;   return a;<br>
+; }<br>
+<br>
+; ModuleID = 't.c'<br>
+source_filename = "t.c"<br>
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n<wbr>8:16:32-a:0:32-S32"<br>
+target triple = "i386-pc-windows-msvc19.11.255<wbr>08"<br>
+<br>
+; Function Attrs: nounwind<br>
+define i32 @csr1() local_unnamed_addr #0 !dbg !8 {<br>
+entry:<br>
+  %call = tail call i32 @getval() #3, !dbg !14<br>
+  tail call void @llvm.dbg.value(metadata i32 %call, metadata !13, metadata !DIExpression()), !dbg !15<br>
+  tail call void (i32, ...) @usevals(i32 %call) #3, !dbg !16<br>
+  tail call void (i32, ...) @usevals(i32 %call) #3, !dbg !17<br>
+  ret i32 %call, !dbg !18<br>
+}<br>
+<br>
+; ASM-LABEL: _csr1:                                  # @csr1<br>
+; ASM:         .cv_fpo_proc    _csr1<br>
+; ASM:         pushl   %esi<br>
+; ASM:         .cv_fpo_pushreg %esi<br>
+; ASM:         .cv_fpo_endprologue<br>
+; ASM:         #DEBUG_VALUE: csr1:a <- %ESI<br>
+; ASM:         retl<br>
+; ASM:         .cv_fpo_endproc<br>
+<br>
+; OBJ-LABEL: SubSectionType: FrameData (0xF5)<br>
+; OBJ-NEXT: SubSectionSize:<br>
+; OBJ-NEXT: LinkageName: _csr1<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x0<br>
+; OBJ-NEXT:   CodeSize: 0x1E<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + =<br>
+; OBJ-NEXT:   PrologSize: 0x1<br>
+; OBJ-NEXT:   SavedRegsSize: 0x0<br>
+; OBJ-NEXT:   Flags [ (0x4)<br>
+; OBJ-NEXT:     IsFunctionStart (0x4)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x1<br>
+; OBJ-NEXT:   CodeSize: 0x1D<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $esi $T0 4 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x0<br>
+; OBJ-NEXT:   SavedRegsSize: 0x4<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NOT: FrameData<br>
+<br>
+declare i32 @getval() local_unnamed_addr #1<br>
+<br>
+declare void @usevals(i32, ...) local_unnamed_addr #1<br>
+<br>
+; Function Attrs: nounwind<br>
+define i32 @csr2() local_unnamed_addr #0 !dbg !19 {<br>
+entry:<br>
+  %call = tail call i32 @getval() #3, !dbg !23<br>
+  tail call void @llvm.dbg.value(metadata i32 %call, metadata !21, metadata !DIExpression()), !dbg !24<br>
+  %call1 = tail call i32 @getval() #3, !dbg !25<br>
+  tail call void @llvm.dbg.value(metadata i32 %call1, metadata !22, metadata !DIExpression()), !dbg !26<br>
+  tail call void (i32, ...) @usevals(i32 %call, i32 %call1) #3, !dbg !27<br>
+  tail call void (i32, ...) @usevals(i32 %call, i32 %call1) #3, !dbg !28<br>
+  ret i32 %call, !dbg !29<br>
+}<br>
+<br>
+; ASM-LABEL: _csr2:                                  # @csr2<br>
+; ASM:         .cv_fpo_proc    _csr2<br>
+; ASM:         pushl   %edi<br>
+; ASM:         .cv_fpo_pushreg %edi<br>
+; ASM:         pushl   %esi<br>
+; ASM:         .cv_fpo_pushreg %esi<br>
+; ASM:         .cv_fpo_endprologue<br>
+; ASM:         #DEBUG_VALUE: csr2:a <- %ESI<br>
+; ASM:         #DEBUG_VALUE: csr2:b <- %EDI<br>
+; ASM:         retl<br>
+; ASM:         .cv_fpo_endproc<br>
+<br>
+; OBJ-LABEL: SubSectionType: FrameData (0xF5)<br>
+; OBJ-NEXT: SubSectionSize:<br>
+; OBJ-NEXT: LinkageName: _csr2<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x0<br>
+; OBJ-NEXT:   CodeSize: 0x29<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + =<br>
+; OBJ-NEXT:   PrologSize: 0x2<br>
+; OBJ-NEXT:   SavedRegsSize: 0x0<br>
+; OBJ-NEXT:   Flags [ (0x4)<br>
+; OBJ-NEXT:     IsFunctionStart (0x4)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x1<br>
+; OBJ-NEXT:   CodeSize: 0x28<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $edi $T0 4 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x1<br>
+; OBJ-NEXT:   SavedRegsSize: 0x4<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x2<br>
+; OBJ-NEXT:   CodeSize: 0x27<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $edi $T0 4 - ^ = $esi $T0 8 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x0<br>
+; OBJ-NEXT:   SavedRegsSize: 0x8<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NOT: FrameData<br>
+<br>
+; Function Attrs: nounwind<br>
+define i32 @csr3() local_unnamed_addr #0 !dbg !30 {<br>
+entry:<br>
+  %call = tail call i32 @getval() #3, !dbg !35<br>
+  tail call void @llvm.dbg.value(metadata i32 %call, metadata !32, metadata !DIExpression()), !dbg !36<br>
+  %call1 = tail call i32 @getval() #3, !dbg !37<br>
+  tail call void @llvm.dbg.value(metadata i32 %call1, metadata !33, metadata !DIExpression()), !dbg !38<br>
+  %call2 = tail call i32 @getval() #3, !dbg !39<br>
+  tail call void @llvm.dbg.value(metadata i32 %call2, metadata !34, metadata !DIExpression()), !dbg !40<br>
+  tail call void (i32, ...) @usevals(i32 %call, i32 %call1, i32 %call2) #3, !dbg !41<br>
+  tail call void (i32, ...) @usevals(i32 %call, i32 %call1, i32 %call2) #3, !dbg !42<br>
+  ret i32 %call, !dbg !43<br>
+}<br>
+<br>
+; ASM-LABEL: _csr3:                                  # @csr3<br>
+; ASM:         .cv_fpo_proc    _csr3<br>
+; ASM:         pushl   %ebx<br>
+; ASM:         .cv_fpo_pushreg %ebx<br>
+; ASM:         pushl   %edi<br>
+; ASM:         .cv_fpo_pushreg %edi<br>
+; ASM:         pushl   %esi<br>
+; ASM:         .cv_fpo_pushreg %esi<br>
+; ASM:         .cv_fpo_endprologue<br>
+; ASM:         #DEBUG_VALUE: csr3:a <- %ESI<br>
+; ASM:         #DEBUG_VALUE: csr3:b <- %EDI<br>
+; ASM:         #DEBUG_VALUE: csr3:c <- %EBX<br>
+; ASM:         retl<br>
+; ASM:         .cv_fpo_endproc<br>
+<br>
+; OBJ-LABEL: SubSectionType: FrameData (0xF5)<br>
+; OBJ-NEXT: SubSectionSize:<br>
+; OBJ-NEXT: LinkageName: _csr3<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x0<br>
+; OBJ-NEXT:   CodeSize: 0x34<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + =<br>
+; OBJ-NEXT:   PrologSize: 0x3<br>
+; OBJ-NEXT:   SavedRegsSize: 0x0<br>
+; OBJ-NEXT:   Flags [ (0x4)<br>
+; OBJ-NEXT:     IsFunctionStart (0x4)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x1<br>
+; OBJ-NEXT:   CodeSize: 0x33<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x2<br>
+; OBJ-NEXT:   SavedRegsSize: 0x4<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x2<br>
+; OBJ-NEXT:   CodeSize: 0x32<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = $edi $T0 8 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x1<br>
+; OBJ-NEXT:   SavedRegsSize: 0x8<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x3<br>
+; OBJ-NEXT:   CodeSize: 0x31<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebx $T0 4 - ^ = $edi $T0 8 - ^ = $esi $T0 12 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x0<br>
+; OBJ-NEXT:   SavedRegsSize: 0xC<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NOT: FrameData<br>
+<br>
+; Function Attrs: nounwind<br>
+define i32 @csr4() local_unnamed_addr #0 !dbg !44 {<br>
+entry:<br>
+  %call = tail call i32 @getval() #3, !dbg !50<br>
+  tail call void @llvm.dbg.value(metadata i32 %call, metadata !46, metadata !DIExpression()), !dbg !51<br>
+  %call1 = tail call i32 @getval() #3, !dbg !52<br>
+  tail call void @llvm.dbg.value(metadata i32 %call1, metadata !47, metadata !DIExpression()), !dbg !53<br>
+  %call2 = tail call i32 @getval() #3, !dbg !54<br>
+  tail call void @llvm.dbg.value(metadata i32 %call2, metadata !48, metadata !DIExpression()), !dbg !55<br>
+  %call3 = tail call i32 @getval() #3, !dbg !56<br>
+  tail call void @llvm.dbg.value(metadata i32 %call3, metadata !49, metadata !DIExpression()), !dbg !57<br>
+  tail call void (i32, ...) @usevals(i32 %call, i32 %call1, i32 %call2, i32 %call3) #3, !dbg !58<br>
+  tail call void (i32, ...) @usevals(i32 %call, i32 %call1, i32 %call2, i32 %call3) #3, !dbg !59<br>
+  ret i32 %call, !dbg !60<br>
+}<br>
+<br>
+; ASM-LABEL: _csr4:                                  # @csr4<br>
+; ASM:         .cv_fpo_proc    _csr4<br>
+; ASM:         pushl   %ebp<br>
+; ASM:         .cv_fpo_pushreg %ebp<br>
+; ASM:         pushl   %ebx<br>
+; ASM:         .cv_fpo_pushreg %ebx<br>
+; ASM:         pushl   %edi<br>
+; ASM:         .cv_fpo_pushreg %edi<br>
+; ASM:         pushl   %esi<br>
+; ASM:         .cv_fpo_pushreg %esi<br>
+; ASM:         .cv_fpo_endprologue<br>
+; ASM:         #DEBUG_VALUE: csr4:a <- %ESI<br>
+; ASM:         #DEBUG_VALUE: csr4:b <- %EDI<br>
+; ASM:         #DEBUG_VALUE: csr4:c <- %EBX<br>
+; ASM:         #DEBUG_VALUE: csr4:d <- %EBP<br>
+; ASM:         retl<br>
+; ASM:         .cv_fpo_endproc<br>
+<br>
+; OBJ-LABEL: SubSectionType: FrameData (0xF5)<br>
+; OBJ-NEXT: SubSectionSize:<br>
+; OBJ-NEXT: LinkageName: _csr4<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x0<br>
+; OBJ-NEXT:   CodeSize: 0x3F<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + =<br>
+; OBJ-NEXT:   PrologSize: 0x4<br>
+; OBJ-NEXT:   SavedRegsSize: 0x0<br>
+; OBJ-NEXT:   Flags [ (0x4)<br>
+; OBJ-NEXT:     IsFunctionStart (0x4)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x1<br>
+; OBJ-NEXT:   CodeSize: 0x3E<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x3<br>
+; OBJ-NEXT:   SavedRegsSize: 0x4<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x2<br>
+; OBJ-NEXT:   CodeSize: 0x3D<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x2<br>
+; OBJ-NEXT:   SavedRegsSize: 0x8<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x3<br>
+; OBJ-NEXT:   CodeSize: 0x3C<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ = $edi $T0 12 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x1<br>
+; OBJ-NEXT:   SavedRegsSize: 0xC<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x4<br>
+; OBJ-NEXT:   CodeSize: 0x3B<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ = $edi $T0 12 - ^ = $esi $T0 16 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x0<br>
+; OBJ-NEXT:   SavedRegsSize: 0x10<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NOT: FrameData<br>
+<br>
+; Function Attrs: nounwind<br>
+define i32 @spill() local_unnamed_addr #0 !dbg !61 {<br>
+entry:<br>
+  %call = tail call i32 @getval() #3, !dbg !68<br>
+  tail call void @llvm.dbg.value(metadata i32 %call, metadata !63, metadata !DIExpression()), !dbg !69<br>
+  %call1 = tail call i32 @getval() #3, !dbg !70<br>
+  tail call void @llvm.dbg.value(metadata i32 %call1, metadata !64, metadata !DIExpression()), !dbg !71<br>
+  %call2 = tail call i32 @getval() #3, !dbg !72<br>
+  tail call void @llvm.dbg.value(metadata i32 %call2, metadata !65, metadata !DIExpression()), !dbg !73<br>
+  %call3 = tail call i32 @getval() #3, !dbg !74<br>
+  tail call void @llvm.dbg.value(metadata i32 %call3, metadata !66, metadata !DIExpression()), !dbg !75<br>
+  %call4 = tail call i32 @getval() #3, !dbg !76<br>
+  tail call void @llvm.dbg.value(metadata i32 %call4, metadata !67, metadata !DIExpression()), !dbg !77<br>
+  tail call void (i32, ...) @usevals(i32 %call, i32 %call1, i32 %call2, i32 %call3, i32 %call4) #3, !dbg !78<br>
+  tail call void (i32, ...) @usevals(i32 %call, i32 %call1, i32 %call2, i32 %call3, i32 %call4) #3, !dbg !79<br>
+  ret i32 %call, !dbg !80<br>
+}<br>
+<br>
+; ASM-LABEL: _spill:                                  # @spill<br>
+; ASM:         .cv_fpo_proc    _spill<br>
+; ASM:         pushl   %ebp<br>
+; ASM:         .cv_fpo_pushreg %ebp<br>
+; ASM:         pushl   %ebx<br>
+; ASM:         .cv_fpo_pushreg %ebx<br>
+; ASM:         pushl   %edi<br>
+; ASM:         .cv_fpo_pushreg %edi<br>
+; ASM:         pushl   %esi<br>
+; ASM:         .cv_fpo_pushreg %esi<br>
+; ASM:         subl    $8, %esp<br>
+; ASM:         .cv_fpo_stackalloc 8<br>
+; ASM:         .cv_fpo_endprologue<br>
+; ASM:         retl<br>
+; ASM:         .cv_fpo_endproc<br>
+<br>
+; OBJ-LABEL: SubSectionType: FrameData (0xF5)<br>
+; OBJ-NEXT: SubSectionSize:<br>
+; OBJ-NEXT: LinkageName: _spill<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x0<br>
+; OBJ-NEXT:   CodeSize: 0x5A<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + =<br>
+; OBJ-NEXT:   PrologSize: 0x7<br>
+; OBJ-NEXT:   SavedRegsSize: 0x0<br>
+; OBJ-NEXT:   Flags [ (0x4)<br>
+; OBJ-NEXT:     IsFunctionStart (0x4)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x1<br>
+; OBJ-NEXT:   CodeSize: 0x59<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x6<br>
+; OBJ-NEXT:   SavedRegsSize: 0x4<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x2<br>
+; OBJ-NEXT:   CodeSize: 0x58<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x5<br>
+; OBJ-NEXT:   SavedRegsSize: 0x8<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x3<br>
+; OBJ-NEXT:   CodeSize: 0x57<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ = $edi $T0 12 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x4<br>
+; OBJ-NEXT:   SavedRegsSize: 0xC<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x4<br>
+; OBJ-NEXT:   CodeSize: 0x56<br>
+; OBJ-NEXT:   LocalSize: 0x0<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ = $edi $T0 12 - ^ = $esi $T0 16 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x3<br>
+; OBJ-NEXT:   SavedRegsSize: 0x10<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NEXT: FrameData {<br>
+; OBJ-NEXT:   RvaStart: 0x7<br>
+; OBJ-NEXT:   CodeSize: 0x53<br>
+; OBJ-NEXT:   LocalSize: 0x8<br>
+; OBJ-NEXT:   ParamsSize: 0x0<br>
+; OBJ-NEXT:   MaxStackSize: 0x0<br>
+; OBJ-NEXT:   FrameFunc: $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $ebx $T0 8 - ^ = $edi $T0 12 - ^ = $esi $T0 16 - ^ =<br>
+; OBJ-NEXT:   PrologSize: 0x0<br>
+; OBJ-NEXT:   SavedRegsSize: 0x10<br>
+; OBJ-NEXT:   Flags [ (0x0)<br>
+; OBJ-NEXT:   ]<br>
+; OBJ-NEXT: }<br>
+; OBJ-NOT: FrameData<br>
+<br>
+; Function Attrs: nounwind readnone speculatable<br>
+declare void @llvm.dbg.value(metadata, metadata, metadata) #2<br>
+<br>
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt<wbr>-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false<wbr>" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="fal<wbr>se" "no-trapping-math"="false" "stack-protector-buffer-size"=<wbr>"8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,<wbr>+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }<br>
+attributes #1 = { "correctly-rounded-divide-sqrt<wbr>-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false<wbr>" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="fal<wbr>se" "no-trapping-math"="false" "stack-protector-buffer-size"=<wbr>"8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,<wbr>+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }<br>
+attributes #2 = { nounwind readnone speculatable }<br>
+attributes #3 = { nounwind }<br>
+<br>
+!<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
+!llvm.module.flags = !{!3, !4, !5, !6}<br>
+!llvm.ident = !{!7}<br>
+<br>
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)<br>
+!1 = !DIFile(filename: "t.c", directory: "C:\5Csrc\5Cllvm-project\5Cbui<wbr>ld", checksumkind: CSK_MD5, checksum: "0b1c85f8a0bfb41380df1fcaeadde<wbr>306")<br>
+!2 = !{}<br>
+!3 = !{i32 1, !"NumRegisterParameters", i32 0}<br>
+!4 = !{i32 2, !"CodeView", i32 1}<br>
+!5 = !{i32 2, !"Debug Info Version", i32 3}<br>
+!6 = !{i32 1, !"wchar_size", i32 2}<br>
+!7 = !{!"clang version 6.0.0 "}<br>
+!8 = distinct !DISubprogram(name: "csr1", scope: !1, file: !1, line: 3, type: !9, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, variables: !12)<br>
+!9 = !DISubroutineType(types: !10)<br>
+!10 = !{!11}<br>
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
+!12 = !{!13}<br>
+!13 = !DILocalVariable(name: "a", scope: !8, file: !1, line: 4, type: !11)<br>
+!14 = !DILocation(line: 4, column: 11, scope: !8)<br>
+!15 = !DILocation(line: 4, column: 7, scope: !8)<br>
+!16 = !DILocation(line: 5, column: 3, scope: !8)<br>
+!17 = !DILocation(line: 6, column: 3, scope: !8)<br>
+!18 = !DILocation(line: 7, column: 3, scope: !8)<br>
+!19 = distinct !DISubprogram(name: "csr2", scope: !1, file: !1, line: 9, type: !9, isLocal: false, isDefinition: true, scopeLine: 9, isOptimized: true, unit: !0, variables: !20)<br>
+!20 = !{!21, !22}<br>
+!21 = !DILocalVariable(name: "a", scope: !19, file: !1, line: 10, type: !11)<br>
+!22 = !DILocalVariable(name: "b", scope: !19, file: !1, line: 11, type: !11)<br>
+!23 = !DILocation(line: 10, column: 11, scope: !19)<br>
+!24 = !DILocation(line: 10, column: 7, scope: !19)<br>
+!25 = !DILocation(line: 11, column: 11, scope: !19)<br>
+!26 = !DILocation(line: 11, column: 7, scope: !19)<br>
+!27 = !DILocation(line: 12, column: 3, scope: !19)<br>
+!28 = !DILocation(line: 13, column: 3, scope: !19)<br>
+!29 = !DILocation(line: 14, column: 3, scope: !19)<br>
+!30 = distinct !DISubprogram(name: "csr3", scope: !1, file: !1, line: 16, type: !9, isLocal: false, isDefinition: true, scopeLine: 16, isOptimized: true, unit: !0, variables: !31)<br>
+!31 = !{!32, !33, !34}<br>
+!32 = !DILocalVariable(name: "a", scope: !30, file: !1, line: 17, type: !11)<br>
+!33 = !DILocalVariable(name: "b", scope: !30, file: !1, line: 18, type: !11)<br>
+!34 = !DILocalVariable(name: "c", scope: !30, file: !1, line: 19, type: !11)<br>
+!35 = !DILocation(line: 17, column: 11, scope: !30)<br>
+!36 = !DILocation(line: 17, column: 7, scope: !30)<br>
+!37 = !DILocation(line: 18, column: 11, scope: !30)<br>
+!38 = !DILocation(line: 18, column: 7, scope: !30)<br>
+!39 = !DILocation(line: 19, column: 11, scope: !30)<br>
+!40 = !DILocation(line: 19, column: 7, scope: !30)<br>
+!41 = !DILocation(line: 20, column: 3, scope: !30)<br>
+!42 = !DILocation(line: 21, column: 3, scope: !30)<br>
+!43 = !DILocation(line: 22, column: 3, scope: !30)<br>
+!44 = distinct !DISubprogram(name: "csr4", scope: !1, file: !1, line: 24, type: !9, isLocal: false, isDefinition: true, scopeLine: 24, isOptimized: true, unit: !0, variables: !45)<br>
+!45 = !{!46, !47, !48, !49}<br>
+!46 = !DILocalVariable(name: "a", scope: !44, file: !1, line: 25, type: !11)<br>
+!47 = !DILocalVariable(name: "b", scope: !44, file: !1, line: 26, type: !11)<br>
+!48 = !DILocalVariable(name: "c", scope: !44, file: !1, line: 27, type: !11)<br>
+!49 = !DILocalVariable(name: "d", scope: !44, file: !1, line: 28, type: !11)<br>
+!50 = !DILocation(line: 25, column: 11, scope: !44)<br>
+!51 = !DILocation(line: 25, column: 7, scope: !44)<br>
+!52 = !DILocation(line: 26, column: 11, scope: !44)<br>
+!53 = !DILocation(line: 26, column: 7, scope: !44)<br>
+!54 = !DILocation(line: 27, column: 11, scope: !44)<br>
+!55 = !DILocation(line: 27, column: 7, scope: !44)<br>
+!56 = !DILocation(line: 28, column: 11, scope: !44)<br>
+!57 = !DILocation(line: 28, column: 7, scope: !44)<br>
+!58 = !DILocation(line: 29, column: 3, scope: !44)<br>
+!59 = !DILocation(line: 30, column: 3, scope: !44)<br>
+!60 = !DILocation(line: 31, column: 3, scope: !44)<br>
+!61 = distinct !DISubprogram(name: "spill", scope: !1, file: !1, line: 33, type: !9, isLocal: false, isDefinition: true, scopeLine: 33, isOptimized: true, unit: !0, variables: !62)<br>
+!62 = !{!63, !64, !65, !66, !67}<br>
+!63 = !DILocalVariable(name: "a", scope: !61, file: !1, line: 34, type: !11)<br>
+!64 = !DILocalVariable(name: "b", scope: !61, file: !1, line: 35, type: !11)<br>
+!65 = !DILocalVariable(name: "c", scope: !61, file: !1, line: 36, type: !11)<br>
+!66 = !DILocalVariable(name: "d", scope: !61, file: !1, line: 37, type: !11)<br>
+!67 = !DILocalVariable(name: "e", scope: !61, file: !1, line: 38, type: !11)<br>
+!68 = !DILocation(line: 34, column: 11, scope: !61)<br>
+!69 = !DILocation(line: 34, column: 7, scope: !61)<br>
+!70 = !DILocation(line: 35, column: 11, scope: !61)<br>
+!71 = !DILocation(line: 35, column: 7, scope: !61)<br>
+!72 = !DILocation(line: 36, column: 11, scope: !61)<br>
+!73 = !DILocation(line: 36, column: 7, scope: !61)<br>
+!74 = !DILocation(line: 37, column: 11, scope: !61)<br>
+!75 = !DILocation(line: 37, column: 7, scope: !61)<br>
+!76 = !DILocation(line: 38, column: 11, scope: !61)<br>
+!77 = !DILocation(line: 38, column: 7, scope: !61)<br>
+!78 = !DILocation(line: 39, column: 3, scope: !61)<br>
+!79 = !DILocation(line: 40, column: 3, scope: !61)<br>
+!80 = !DILocation(line: 41, column: 3, scope: !61)<br>
<br>
Added: llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-realign-alloca.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/fpo-realign-alloca.ll?rev=315513&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/DebugInf<wbr>o/COFF/fpo-realign-alloca.ll?<wbr>rev=315513&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-realign-alloca.ll (added)<br>
+++ llvm/trunk/test/DebugInfo/COFF<wbr>/fpo-realign-alloca.ll Wed Oct 11 14:24:33 2017<br>
@@ -0,0 +1,110 @@<br>
+; RUN: llc < %s | FileCheck %s<br>
+<br>
+; C source:<br>
+; void usethings(double *, void *p);<br>
+; int realign_and_alloca(int n) {<br>
+;   double d = 0;<br>
+;   void *p = __builtin_alloca(n);<br>
+;   usethings(&d, p);<br>
+;   return 0;<br>
+; }<br>
+<br>
+; CHECK: _realign_and_alloca:                    # @realign_and_alloca<br>
+; CHECK:         .cv_fpo_proc    _realign_and_alloca 4<br>
+; CHECK:         pushl   %ebp<br>
+; CHECK:         .cv_fpo_pushreg %ebp<br>
+; CHECK:         movl    %esp, %ebp<br>
+; CHECK:         .cv_fpo_setframe        %ebp<br>
+; CHECK:         pushl   %esi<br>
+; CHECK:         .cv_fpo_pushreg %esi<br>
+;       We don't seem to need to describe this AND because at this point CSRs<br>
+;       are stored relative to EBP, but it's suspicious.<br>
+; CHECK:         andl    $-16, %esp<br>
+; CHECK:         subl    $32, %esp<br>
+; CHECK:         .cv_fpo_stackalloc      32<br>
+; CHECK:         .cv_fpo_endprologue<br>
+; CHECK:         movl    %esp, %esi<br>
+; CHECK:         leal    8(%esi),<br>
+; CHECK:         calll   _usethings<br>
+; CHECK:         addl    $8, %esp<br>
+; CHECK:         xorl    %eax, %eax<br>
+; CHECK:         leal    -4(%ebp), %esp<br>
+; CHECK:         popl    %esi<br>
+; CHECK:         popl    %ebp<br>
+; CHECK:         retl<br>
+; CHECK:         .cv_fpo_endproc<br>
+<br>
+<br>
+; ModuleID = 't.c'<br>
+source_filename = "t.c"<br>
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n<wbr>8:16:32-a:0:32-S32"<br>
+target triple = "i386-pc-windows-msvc19.11.255<wbr>08"<br>
+<br>
+; Function Attrs: nounwind<br>
+define i32 @realign_and_alloca(i32 %n) local_unnamed_addr #0 !dbg !8 {<br>
+entry:<br>
+  %d = alloca double, align 8<br>
+  tail call void @llvm.dbg.value(metadata i32 %n, metadata !13, metadata !DIExpression()), !dbg !18<br>
+  %0 = bitcast double* %d to i8*, !dbg !19<br>
+  call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %0) #4, !dbg !19<br>
+  tail call void @llvm.dbg.value(metadata double 0.000000e+00, metadata !14, metadata !DIExpression()), !dbg !20<br>
+  store double 0.000000e+00, double* %d, align 8, !dbg !20, !tbaa !21<br>
+  %1 = alloca i8, i32 %n, align 16, !dbg !25<br>
+  tail call void @llvm.dbg.value(metadata i8* %1, metadata !16, metadata !DIExpression()), !dbg !26<br>
+  tail call void @llvm.dbg.value(metadata double* %d, metadata !14, metadata !DIExpression()), !dbg !20<br>
+  call void @usethings(double* nonnull %d, i8* nonnull %1) #4, !dbg !27<br>
+  call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %0) #4, !dbg !28<br>
+  ret i32 0, !dbg !29<br>
+}<br>
+<br>
+; Function Attrs: argmemonly nounwind<br>
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1<br>
+<br>
+declare void @usethings(double*, i8*) local_unnamed_addr #2<br>
+<br>
+; Function Attrs: argmemonly nounwind<br>
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1<br>
+<br>
+; Function Attrs: nounwind readnone speculatable<br>
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3<br>
+<br>
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt<wbr>-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false<wbr>" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="fal<wbr>se" "no-trapping-math"="false" "stack-protector-buffer-size"=<wbr>"8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,<wbr>+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }<br>
+attributes #1 = { argmemonly nounwind }<br>
+attributes #2 = { "correctly-rounded-divide-sqrt<wbr>-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false<wbr>" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-ze...<br><br>[Message clipped]  </blockquote></div><br></div>
</blockquote></div><br></div>