[llvm] r315513 - [codeview] Implement FPO data assembler directives

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 12 14:37:36 PDT 2017


Should be fixed after r315600, sorry for the slow forward fix.

On Thu, Oct 12, 2017 at 8:51 AM, Matt Morehouse <mascasa at google.com> wrote:

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


More information about the llvm-commits mailing list