[llvm] r259130 - Reland "[CodeView] Use assembler directives for line tables"
David Blaikie via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 28 19:30:06 PST 2016
Looks like you've introduced a dependency from the AsmPrinter library to
the DebugInfo/CodeView library & may need to update AsmPrinter's
CMakeLists.txt to add that dependency?
On Thu, Jan 28, 2016 at 4:49 PM, Reid Kleckner via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: rnk
> Date: Thu Jan 28 18:49:42 2016
> New Revision: 259130
>
> URL: http://llvm.org/viewvc/llvm-project?rev=259130&view=rev
> Log:
> Reland "[CodeView] Use assembler directives for line tables"
>
> This reverts commit r259126 and relands r259117.
>
> This time with updated library dependencies.
>
> Added:
> llvm/trunk/include/llvm/MC/MCCodeView.h
> llvm/trunk/lib/MC/MCCodeView.cpp
> llvm/trunk/test/MC/COFF/cv-loc.s
> Modified:
> llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h
> llvm/trunk/include/llvm/MC/MCContext.h
> llvm/trunk/include/llvm/MC/MCObjectStreamer.h
> llvm/trunk/include/llvm/MC/MCStreamer.h
> llvm/trunk/include/llvm/MC/StringTableBuilder.h
> llvm/trunk/include/llvm/Support/COFF.h
> llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
> llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
> llvm/trunk/lib/CodeGen/AsmPrinter/LLVMBuild.txt
> llvm/trunk/lib/MC/CMakeLists.txt
> llvm/trunk/lib/MC/MCAsmStreamer.cpp
> llvm/trunk/lib/MC/MCContext.cpp
> llvm/trunk/lib/MC/MCObjectStreamer.cpp
> llvm/trunk/lib/MC/MCParser/AsmParser.cpp
> llvm/trunk/lib/MC/MCStreamer.cpp
> llvm/trunk/lib/MC/StringTableBuilder.cpp
> llvm/trunk/test/DebugInfo/COFF/asm.ll
> llvm/trunk/test/DebugInfo/COFF/multifile.ll
> llvm/trunk/test/DebugInfo/COFF/multifunction.ll
> llvm/trunk/test/DebugInfo/COFF/simple.ll
> llvm/trunk/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll
> llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
> llvm/trunk/unittests/MC/StringTableBuilderTest.cpp
>
> Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h (original)
> +++ llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h Thu Jan 28 18:49:42
> 2016
> @@ -21,16 +21,19 @@ using llvm::support::ulittle32_t;
>
> class LineInfo {
> public:
> - static const uint32_t AlwaysStepIntoLineNumber = 0xfeefee;
> - static const uint32_t NeverStepIntoLineNumber = 0xf00f00;
> + enum : uint32_t {
> + AlwaysStepIntoLineNumber = 0xfeefee,
> + NeverStepIntoLineNumber = 0xf00f00
> + };
> +
> + enum : int { EndLineDeltaShift = 24 };
> +
> + enum : uint32_t {
> + StartLineMask = 0x00ffffff,
> + EndLineDeltaMask = 0x7f000000,
> + StatementFlag = 0x80000000u
> + };
>
> -private:
> - static const uint32_t StartLineMask = 0x00ffffff;
> - static const uint32_t EndLineDeltaMask = 0x7f000000;
> - static const int EndLineDeltaShift = 24;
> - static const uint32_t StatementFlag = 0x80000000u;
> -
> -public:
> LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement);
>
> uint32_t getStartLine() const { return LineData & StartLineMask; }
> @@ -151,6 +154,10 @@ struct FileChecksum {
> // Checksum bytes follow.
> };
>
> +enum LineFlags : uint32_t {
> + HaveColumns = 1, // CV_LINES_HAVE_COLUMNS
> +};
> +
> } // namespace codeview
> } // namespace llvm
>
>
> Added: llvm/trunk/include/llvm/MC/MCCodeView.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCCodeView.h?rev=259130&view=auto
>
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCCodeView.h (added)
> +++ llvm/trunk/include/llvm/MC/MCCodeView.h Thu Jan 28 18:49:42 2016
> @@ -0,0 +1,162 @@
> +//===- MCCodeView.h - Machine Code CodeView support -------------*- C++
> -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +//
> +// Holds state from .cv_file and .cv_loc directives for later emission.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_MC_MCCODEVIEW_H
> +#define LLVM_MC_MCCODEVIEW_H
> +
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/ADT/StringMap.h"
> +#include "llvm/MC/MCObjectStreamer.h"
> +#include "llvm/MC/MCFragment.h"
> +#include <map>
> +#include <vector>
> +
> +namespace llvm {
> +class MCContext;
> +class MCObjectStreamer;
> +class MCStreamer;
> +
> +/// \brief Instances of this class represent the information from a
> +/// .cv_loc directive.
> +class MCCVLoc {
> + uint32_t FunctionId;
> + uint32_t FileNum;
> + uint32_t Line;
> + uint16_t Column;
> + uint16_t PrologueEnd : 1;
> + uint16_t IsStmt : 1;
> +
> +private: // MCContext manages these
> + friend class MCContext;
> + MCCVLoc(unsigned functionid, unsigned fileNum, unsigned line, unsigned
> column,
> + bool prologueend, bool isstmt)
> + : FunctionId(functionid), FileNum(fileNum), Line(line),
> Column(column),
> + PrologueEnd(prologueend), IsStmt(isstmt) {}
> +
> + // Allow the default copy constructor and assignment operator to be used
> + // for an MCCVLoc object.
> +
> +public:
> + unsigned getFunctionId() const { return FunctionId; }
> +
> + /// \brief Get the FileNum of this MCCVLoc.
> + unsigned getFileNum() const { return FileNum; }
> +
> + /// \brief Get the Line of this MCCVLoc.
> + unsigned getLine() const { return Line; }
> +
> + /// \brief Get the Column of this MCCVLoc.
> + unsigned getColumn() const { return Column; }
> +
> + bool isPrologueEnd() const { return PrologueEnd; }
> + bool isStmt() const { return IsStmt; }
> +
> + void setFunctionId(unsigned FID) { FunctionId = FID; }
> +
> + /// \brief Set the FileNum of this MCCVLoc.
> + void setFileNum(unsigned fileNum) { FileNum = fileNum; }
> +
> + /// \brief Set the Line of this MCCVLoc.
> + void setLine(unsigned line) { Line = line; }
> +
> + /// \brief Set the Column of this MCCVLoc.
> + void setColumn(unsigned column) {
> + assert(column <= UINT16_MAX);
> + Column = column;
> + }
> +
> + void setPrologueEnd(bool PE) { PrologueEnd = PE; }
> + void setIsStmt(bool IS) { IsStmt = IS; }
> +};
> +
> +/// \brief Instances of this class represent the line information for
> +/// the CodeView line table entries. Which is created after a machine
> +/// instruction is assembled and uses an address from a temporary label
> +/// created at the current address in the current section and the info
> from
> +/// the last .cv_loc directive seen as stored in the context.
> +class MCCVLineEntry : public MCCVLoc {
> + MCSymbol *Label;
> +
> +private:
> + // Allow the default copy constructor and assignment operator to be used
> + // for an MCCVLineEntry object.
> +
> +public:
> + // Constructor to create an MCCVLineEntry given a symbol and the dwarf
> loc.
> + MCCVLineEntry(MCSymbol *label, const MCCVLoc loc)
> + : MCCVLoc(loc), Label(label) {}
> +
> + MCSymbol *getLabel() const { return Label; }
> +
> + // This is called when an instruction is assembled into the specified
> + // section and if there is information from the last .cv_loc directive
> that
> + // has yet to have a line entry made for it is made.
> + static void Make(MCObjectStreamer *MCOS);
> +};
> +
> +/// Holds state from .cv_file and .cv_loc directives for later emission.
> +class CodeViewContext {
> +public:
> + CodeViewContext();
> + ~CodeViewContext();
> +
> + bool isValidFileNumber(unsigned FileNumber) const;
> + bool addFile(unsigned FileNumber, StringRef Filename);
> + ArrayRef<StringRef> getFilenames() { return Filenames; }
> +
> + /// \brief Add a line entry.
> + void addLineEntry(const MCCVLineEntry &LineEntry) {
> + MCCVLines[LineEntry.getFunctionId()].push_back(LineEntry);
> + }
> +
> + ArrayRef<MCCVLineEntry> getFunctionLineEntries(unsigned FuncId) {
> + assert(MCCVLines.find(FuncId) != MCCVLines.end());
> + return MCCVLines.find(FuncId)->second;
> + }
> +
> + /// Emits a line table substream.
> + void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
> + const MCSymbol *FuncBegin,
> + const MCSymbol *FuncEnd);
> +
> + /// Emits the string table substream.
> + void emitStringTable(MCObjectStreamer &OS);
> +
> + /// Emits the file checksum substream.
> + void emitFileChecksums(MCObjectStreamer &OS);
> +
> +private:
> + /// Map from string to string table offset.
> + StringMap<unsigned> StringTable;
> +
> + /// The fragment that ultimately holds our strings.
> + MCDataFragment *StrTabFragment = nullptr;
> + bool InsertedStrTabFragment = false;
> +
> + MCDataFragment *getStringTableFragment();
> +
> + /// Add something to the string table.
> + StringRef addToStringTable(StringRef S);
> +
> + /// Get a string table offset.
> + unsigned getStringTableOffset(StringRef S);
> +
> + /// An array of absolute paths. Eventually this may include the file
> checksum.
> + SmallVector<StringRef, 4> Filenames;
> +
> + /// A collection of MCDwarfLineEntry for each section.
> + std::map<int, std::vector<MCCVLineEntry>> MCCVLines;
> +};
> +
> +} // end namespace llvm
> +#endif
>
> Modified: llvm/trunk/include/llvm/MC/MCContext.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCContext.h?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCContext.h (original)
> +++ llvm/trunk/include/llvm/MC/MCContext.h Thu Jan 28 18:49:42 2016
> @@ -16,6 +16,7 @@
> #include "llvm/ADT/SmallVector.h"
> #include "llvm/ADT/StringMap.h"
> #include "llvm/ADT/Twine.h"
> +#include "llvm/MC/MCCodeView.h"
> #include "llvm/MC/MCDwarf.h"
> #include "llvm/MC/MCSubtargetInfo.h"
> #include "llvm/MC/SectionKind.h"
> @@ -42,6 +43,7 @@ namespace llvm {
> class MCSectionMachO;
> class MCSectionELF;
> class MCSectionCOFF;
> + class CodeViewContext;
>
> /// Context object for machine code objects. This class owns all of the
> /// sections that it creates.
> @@ -66,6 +68,8 @@ namespace llvm {
> /// The MCObjectFileInfo for this target.
> const MCObjectFileInfo *MOFI;
>
> + std::unique_ptr<CodeViewContext> CVContext;
> +
> /// Allocator object used for creating machine code objects.
> ///
> /// We use a bump pointer allocator to avoid the need to track all
> allocated
> @@ -135,6 +139,10 @@ namespace llvm {
> MCDwarfLoc CurrentDwarfLoc;
> bool DwarfLocSeen;
>
> + /// The current CodeView line information from the last .cv_loc
> directive.
> + MCCVLoc CurrentCVLoc = MCCVLoc(0, 0, 0, 0, false, true);
> + bool CVLocSeen = false;
> +
> /// Generate dwarf debugging info for assembly source files.
> bool GenDwarfForAssembly;
>
> @@ -237,6 +245,8 @@ namespace llvm {
>
> const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; }
>
> + CodeViewContext &getCVContext();
> +
> void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels =
> Value; }
> void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels =
> Value; }
>
> @@ -505,6 +515,35 @@ namespace llvm {
>
> /// @}
>
> +
> + /// \name CodeView Management
> + /// @{
> +
> + /// Creates an entry in the cv file table.
> + unsigned getCVFile(StringRef FileName, unsigned FileNumber);
> +
> + /// Saves the information from the currently parsed .cv_loc directive
> + /// and sets CVLocSeen. When the next instruction is assembled an
> entry
> + /// in the line number table with this information and the address of
> the
> + /// instruction will be created.
> + void setCurrentCVLoc(unsigned FunctionId, unsigned FileNo, unsigned
> Line,
> + unsigned Column, bool PrologueEnd, bool IsStmt) {
> + CurrentCVLoc.setFunctionId(FunctionId);
> + CurrentCVLoc.setFileNum(FileNo);
> + CurrentCVLoc.setLine(Line);
> + CurrentCVLoc.setColumn(Column);
> + CurrentCVLoc.setPrologueEnd(PrologueEnd);
> + CurrentCVLoc.setIsStmt(IsStmt);
> + CVLocSeen = true;
> + }
> + void clearCVLocSeen() { CVLocSeen = false; }
> +
> + bool getCVLocSeen() { return CVLocSeen; }
> + const MCCVLoc &getCurrentCVLoc() { return CurrentCVLoc; }
> +
> + bool isValidCVFileNumber(unsigned FileNumber);
> + /// @}
> +
> char *getSecureLogFile() { return SecureLogFile; }
> raw_fd_ostream *getSecureLog() { return SecureLog.get(); }
> bool getSecureLogUsed() { return SecureLogUsed; }
>
> Modified: llvm/trunk/include/llvm/MC/MCObjectStreamer.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectStreamer.h?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCObjectStreamer.h (original)
> +++ llvm/trunk/include/llvm/MC/MCObjectStreamer.h Thu Jan 28 18:49:42 2016
> @@ -59,7 +59,6 @@ public:
> void EmitFrames(MCAsmBackend *MAB);
> void EmitCFISections(bool EH, bool Debug) override;
>
> -protected:
> MCFragment *getCurrentFragment() const;
>
> void insert(MCFragment *F) {
> @@ -73,6 +72,7 @@ protected:
> /// fragment is not a data fragment.
> MCDataFragment *getOrCreateDataFragment();
>
> +protected:
> bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection);
>
> /// If any labels have been emitted but not assigned fragments, ensure
> that
> @@ -122,6 +122,13 @@ public:
> unsigned PointerSize);
> void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
> const MCSymbol *Label);
> + void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned
> Line,
> + unsigned Column, bool PrologueEnd, bool IsStmt,
> + StringRef FileName) override;
> + void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol
> *Begin,
> + const MCSymbol *End) override;
> + void EmitCVStringTableDirective() override;
> + void EmitCVFileChecksumsDirective() override;
> void EmitGPRel32Value(const MCExpr *Value) override;
> void EmitGPRel64Value(const MCExpr *Value) override;
> bool EmitRelocDirective(const MCExpr &Offset, StringRef Name,
>
> Modified: llvm/trunk/include/llvm/MC/MCStreamer.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCStreamer.h (original)
> +++ llvm/trunk/include/llvm/MC/MCStreamer.h Thu Jan 28 18:49:42 2016
> @@ -640,6 +640,27 @@ public:
> unsigned Isa, unsigned Discriminator,
> StringRef FileName);
>
> + /// \brief Associate a filename with a specified logical file number.
> This
> + /// implements the '.cv_file 4 "foo.c"' assembler directive.
> + virtual unsigned EmitCVFileDirective(unsigned FileNo, StringRef
> Filename);
> +
> + /// \brief This implements the CodeView '.cv_loc' assembler directive.
> + virtual void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
> + unsigned Line, unsigned Column,
> + bool PrologueEnd, bool IsStmt,
> + StringRef FileName);
> +
> + /// \brief This implements the CodeView '.cv_linetable' assembler
> directive.
> + virtual void EmitCVLinetableDirective(unsigned FunctionId,
> + const MCSymbol *FnStart,
> + const MCSymbol *FnEnd);
> +
> + /// \brief This implements the CodeView '.cv_stringtable' assembler
> directive.
> + virtual void EmitCVStringTableDirective() {}
> +
> + /// \brief This implements the CodeView '.cv_filechecksums' assembler
> directive.
> + virtual void EmitCVFileChecksumsDirective() {}
> +
> /// Emit the absolute difference between two symbols.
> ///
> /// \pre Offset of \c Hi is greater than the offset \c Lo.
>
> Modified: llvm/trunk/include/llvm/MC/StringTableBuilder.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/StringTableBuilder.h?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/StringTableBuilder.h (original)
> +++ llvm/trunk/include/llvm/MC/StringTableBuilder.h Thu Jan 28 18:49:42
> 2016
> @@ -27,6 +27,8 @@ private:
> size_t Size = 0;
> Kind K;
>
> + void finalizeStringTable(bool Optimize);
> +
> public:
> StringTableBuilder(Kind K);
>
> @@ -39,6 +41,10 @@ public:
> /// be added after this point.
> void finalize();
>
> + /// Finalize the string table without reording it. In this mode, offsets
> + /// returned by add will still be valid.
> + void finalizeInOrder();
> +
> /// \brief Retrieve the string table data. Can only be used after the
> table
> /// is finalized.
> StringRef data() const {
>
> Modified: llvm/trunk/include/llvm/Support/COFF.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/COFF.h?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Support/COFF.h (original)
> +++ llvm/trunk/include/llvm/Support/COFF.h Thu Jan 28 18:49:42 2016
> @@ -656,17 +656,7 @@ namespace COFF {
> }
> };
>
> - enum CodeViewLine : unsigned {
> - CVL_LineNumberStartBits = 24,
> - CVL_LineNumberEndDeltaBits = 7,
> - CVL_LineNumberEndDeltaMask = (1U << CVL_LineNumberEndDeltaBits) - 1,
> - CVL_MaxLineNumber = (1U << CVL_LineNumberStartBits) - 1,
> - CVL_IsStatement = 1U << 31,
> - CVL_MaxColumnNumber = UINT16_MAX,
> - };
> -
> enum CodeViewIdentifiers {
> - DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS = 0x1,
> DEBUG_SECTION_MAGIC = 0x4,
> };
>
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Thu Jan 28
> 18:49:42 2016
> @@ -13,6 +13,7 @@
>
> #include "CodeViewDebug.h"
> #include "llvm/DebugInfo/CodeView/CodeView.h"
> +#include "llvm/DebugInfo/CodeView/Line.h"
> #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
> #include "llvm/MC/MCExpr.h"
> #include "llvm/MC/MCSymbol.h"
> @@ -74,6 +75,18 @@ StringRef CodeViewDebug::getFullFilepath
> return Filepath;
> }
>
> +unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {
> + unsigned NextId = FileIdMap.size() + 1;
> + auto Insertion = FileIdMap.insert(std::make_pair(F, NextId));
> + if (Insertion.second) {
> + // We have to compute the full filepath and emit a .cv_file directive.
> + StringRef FullPath = getFullFilepath(F);
> + NextId = Asm->OutStreamer->EmitCVFileDirective(NextId, FullPath);
> + assert(NextId == FileIdMap.size() && ".cv_file directive failed");
> + }
> + return Insertion.first->second;
> +}
> +
> void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
> const MachineFunction *MF) {
> // Skip this instruction if it has the same location as the previous
> one.
> @@ -85,15 +98,26 @@ void CodeViewDebug::maybeRecordLocation(
> return;
>
> // Skip this line if it is longer than the maximum we can record.
> - if (DL.getLine() > COFF::CVL_MaxLineNumber)
> + LineInfo LI(DL.getLine(), DL.getLine(), /*IsStatement=*/true);
> + if (LI.getStartLine() != DL.getLine() || LI.isAlwaysStepInto() ||
> + LI.isNeverStepInto())
> return;
>
> - CurFn->LastLoc = DL;
> + ColumnInfo CI(DL.getCol(), /*EndColumn=*/0);
> + if (CI.getStartColumn() != DL.getCol())
> + return;
>
> - MCSymbol *MCL = Asm->MMI->getContext().createTempSymbol();
> - Asm->OutStreamer->EmitLabel(MCL);
> - CurFn->Instrs.push_back(MCL);
> - LabelsAndLocs[MCL] = DL;
> + if (!CurFn->HaveLineInfo)
> + CurFn->HaveLineInfo = true;
> + unsigned FileId = 0;
> + if (CurFn->LastLoc.get() && CurFn->LastLoc->getFile() == DL->getFile())
> + FileId = CurFn->LastFileId;
> + else
> + FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile());
> + CurFn->LastLoc = DL;
> + Asm->OutStreamer->EmitCVLocDirective(CurFn->FuncId, FileId,
> DL.getLine(),
> + DL.getCol(), /*PrologueEnd=*/false,
> + /*IsStmt=*/false,
> DL->getFilename());
> }
>
> CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
> @@ -128,39 +152,17 @@ void CodeViewDebug::endModule() {
> // of the payload followed by the payload itself. The subsections are
> 4-byte
> // aligned.
>
> - // Emit per-function debug information. This code is extracted into a
> - // separate function for readability.
> - for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I)
> - emitDebugInfoForFunction(VisitedFunctions[I]);
> + // Emit per-function debug information.
> + for (auto &P : FnDebugInfo)
> + emitDebugInfoForFunction(P.first, P.second);
>
> // This subsection holds a file index to offset in string table table.
> Asm->OutStreamer->AddComment("File index to string table offset
> subsection");
> - Asm->EmitInt32(unsigned(ModuleSubstreamKind::FileChecksums));
> - size_t NumFilenames = FileNameRegistry.Infos.size();
> - Asm->EmitInt32(8 * NumFilenames);
> - for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
> - StringRef Filename = FileNameRegistry.Filenames[I];
> - // For each unique filename, just write its offset in the string
> table.
> - Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset);
> - // The function name offset is not followed by any additional data.
> - Asm->EmitInt32(0);
> - }
> + Asm->OutStreamer->EmitCVFileChecksumsDirective();
>
> // This subsection holds the string table.
> Asm->OutStreamer->AddComment("String table");
> - Asm->EmitInt32(unsigned(ModuleSubstreamKind::StringTable));
> - Asm->EmitInt32(FileNameRegistry.LastOffset);
> - // The payload starts with a null character.
> - Asm->EmitInt8(0);
> -
> - for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
> - // Just emit unique filenames one by one, separated by a null
> character.
> - Asm->OutStreamer->EmitBytes(FileNameRegistry.Filenames[I]);
> - Asm->EmitInt8(0);
> - }
> -
> - // No more subsections. Fill with zeros to align the end of the section
> by 4.
> - Asm->OutStreamer->EmitFill((-FileNameRegistry.LastOffset) % 4, 0);
> + Asm->OutStreamer->EmitCVStringTableDirective();
>
> clear();
> }
> @@ -177,21 +179,13 @@ static void EmitLabelDiff(MCStreamer &St
> Streamer.EmitValue(AddrDelta, Size);
> }
>
> -static const DIFile *getFileFromLoc(DebugLoc DL) {
> - return DL.get()->getScope()->getFile();
> -}
> -
> -void CodeViewDebug::emitDebugInfoForFunction(const Function *GV) {
> +void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
> + FunctionInfo &FI) {
> // For each function there is a separate subsection
> // which holds the PC to file:line table.
> const MCSymbol *Fn = Asm->getSymbol(GV);
> assert(Fn);
>
> - const FunctionInfo &FI = FnDebugInfo[GV];
> - if (FI.Instrs.empty())
> - return;
> - assert(FI.End && "Don't know where the function ends?");
> -
> StringRef FuncName;
> if (auto *SP = getDISubprogram(GV))
> FuncName = SP->getDisplayName();
> @@ -238,102 +232,8 @@ void CodeViewDebug::emitDebugInfoForFunc
> // Every subsection must be aligned to a 4-byte boundary.
> Asm->OutStreamer->EmitFill((-FuncName.size()) % 4, 0);
>
> - // PCs/Instructions are grouped into segments sharing the same filename.
> - // Pre-calculate the lengths (in instructions) of these segments and
> store
> - // them in a map for convenience. Each index in the map is the
> sequential
> - // number of the respective instruction that starts a new segment.
> - DenseMap<size_t, size_t> FilenameSegmentLengths;
> - size_t LastSegmentEnd = 0;
> - const DIFile *PrevFile = getFileFromLoc(LabelsAndLocs[FI.Instrs[0]]);
> - for (size_t J = 1, F = FI.Instrs.size(); J != F; ++J) {
> - const DIFile *CurFile = getFileFromLoc(LabelsAndLocs[FI.Instrs[J]]);
> - if (PrevFile == CurFile)
> - continue;
> - FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd;
> - LastSegmentEnd = J;
> - PrevFile = CurFile;
> - }
> - FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() -
> LastSegmentEnd;
> -
> - // Emit a line table subsection, required to do PC-to-file:line lookup.
> - Asm->OutStreamer->AddComment("Line table subsection for " +
> Twine(FuncName));
> - Asm->EmitInt32(unsigned(ModuleSubstreamKind::Lines));
> - MCSymbol *LineTableBegin = Asm->MMI->getContext().createTempSymbol(),
> - *LineTableEnd = Asm->MMI->getContext().createTempSymbol();
> - EmitLabelDiff(*Asm->OutStreamer, LineTableBegin, LineTableEnd);
> - Asm->OutStreamer->EmitLabel(LineTableBegin);
> -
> - // Identify the function this subsection is for.
> - Asm->OutStreamer->EmitCOFFSecRel32(Fn);
> - Asm->OutStreamer->EmitCOFFSectionIndex(Fn);
> - // Insert flags after a 16-bit section index.
> - Asm->EmitInt16(COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS);
> -
> - // Length of the function's code, in bytes.
> - EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End);
> -
> - // PC-to-linenumber lookup table:
> - MCSymbol *FileSegmentEnd = nullptr;
> -
> - // The start of the last segment:
> - size_t LastSegmentStart = 0;
> -
> - auto FinishPreviousChunk = [&] {
> - if (!FileSegmentEnd)
> - return;
> - for (size_t ColSegI = LastSegmentStart,
> - ColSegEnd = ColSegI +
> FilenameSegmentLengths[LastSegmentStart];
> - ColSegI != ColSegEnd; ++ColSegI) {
> - unsigned ColumnNumber = LabelsAndLocs[FI.Instrs[ColSegI]].getCol();
> - // Truncate the column number if it is longer than the maximum we
> can
> - // record.
> - if (ColumnNumber > COFF::CVL_MaxColumnNumber)
> - ColumnNumber = 0;
> - Asm->EmitInt16(ColumnNumber); // Start column
> - Asm->EmitInt16(0); // End column
> - }
> - Asm->OutStreamer->EmitLabel(FileSegmentEnd);
> - };
> -
> - for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) {
> - MCSymbol *Instr = FI.Instrs[J];
> - assert(LabelsAndLocs.count(Instr));
> -
> - if (FilenameSegmentLengths.count(J)) {
> - // We came to a beginning of a new filename segment.
> - FinishPreviousChunk();
> - const DIFile *File = getFileFromLoc(LabelsAndLocs[FI.Instrs[J]]);
> - StringRef CurFilename = getFullFilepath(File);
> - size_t IndexInFileTable = FileNameRegistry.add(CurFilename);
> - // Each segment starts with the offset of the filename
> - // in the string table.
> - Asm->OutStreamer->AddComment(
> - "Segment for file '" + Twine(CurFilename) + "' begins");
> - MCSymbol *FileSegmentBegin =
> Asm->MMI->getContext().createTempSymbol();
> - Asm->OutStreamer->EmitLabel(FileSegmentBegin);
> - Asm->EmitInt32(8 * IndexInFileTable);
> -
> - // Number of PC records in the lookup table.
> - size_t SegmentLength = FilenameSegmentLengths[J];
> - Asm->EmitInt32(SegmentLength);
> -
> - // Full size of the segment for this filename, including the prev
> two
> - // records.
> - FileSegmentEnd = Asm->MMI->getContext().createTempSymbol();
> - EmitLabelDiff(*Asm->OutStreamer, FileSegmentBegin, FileSegmentEnd);
> - LastSegmentStart = J;
> - }
> -
> - // The first PC with the given linenumber and the linenumber itself.
> - EmitLabelDiff(*Asm->OutStreamer, Fn, Instr);
> - uint32_t LineNumber = LabelsAndLocs[Instr].getLine();
> - assert(LineNumber <= COFF::CVL_MaxLineNumber);
> - uint32_t LineData = LineNumber | COFF::CVL_IsStatement;
> - Asm->EmitInt32(LineData);
> - }
> -
> - FinishPreviousChunk();
> - Asm->OutStreamer->EmitLabel(LineTableEnd);
> + // We have an assembler directive that takes care of the whole line
> table.
> + Asm->OutStreamer->EmitCVLinetableDirective(FI.FuncId, Fn, FI.End);
> }
>
> void CodeViewDebug::beginFunction(const MachineFunction *MF) {
> @@ -344,8 +244,8 @@ void CodeViewDebug::beginFunction(const
>
> const Function *GV = MF->getFunction();
> assert(FnDebugInfo.count(GV) == false);
> - VisitedFunctions.push_back(GV);
> CurFn = &FnDebugInfo[GV];
> + CurFn->FuncId = NextFuncId++;
>
> // Find the end of the function prolog.
> // FIXME: is there a simpler a way to do this? Can we just search
> @@ -384,9 +284,9 @@ void CodeViewDebug::endFunction(const Ma
> assert(FnDebugInfo.count(GV));
> assert(CurFn == &FnDebugInfo[GV]);
>
> - if (CurFn->Instrs.empty()) {
> + // Don't emit anything if we don't have any line tables.
> + if (!CurFn->HaveLineInfo) {
> FnDebugInfo.erase(GV);
> - VisitedFunctions.pop_back();
> } else {
> CurFn->End = Asm->getFunctionEnd();
> }
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h Thu Jan 28 18:49:42
> 2016
> @@ -37,72 +37,38 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
> // to the end of the function.
> struct FunctionInfo {
> DebugLoc LastLoc;
> - SmallVector<MCSymbol *, 10> Instrs;
> - MCSymbol *End;
> - FunctionInfo() : End(nullptr) {}
> + MCSymbol *End = nullptr;
> + unsigned FuncId = 0;
> + unsigned LastFileId;
> + bool HaveLineInfo = false;
> };
> FunctionInfo *CurFn;
>
> - typedef DenseMap<const Function *, FunctionInfo> FnDebugInfoTy;
> - FnDebugInfoTy FnDebugInfo;
> - // Store the functions we've visited in a vector so we can maintain a
> stable
> - // order while emitting subsections.
> - SmallVector<const Function *, 10> VisitedFunctions;
> -
> - DenseMap<MCSymbol *, DebugLoc> LabelsAndLocs;
> -
> - // FileNameRegistry - Manages filenames observed while generating debug
> info
> - // by filtering out duplicates and bookkeeping the offsets in the string
> - // table to be generated.
> - struct FileNameRegistryTy {
> - SmallVector<StringRef, 10> Filenames;
> - struct PerFileInfo {
> - size_t FilenameID, StartOffset;
> - };
> - StringMap<PerFileInfo> Infos;
> -
> - // The offset in the string table where we'll write the next unique
> - // filename.
> - size_t LastOffset;
> -
> - FileNameRegistryTy() {
> - clear();
> - }
> -
> - // Add Filename to the registry, if it was not observed before.
> - size_t add(StringRef Filename) {
> - size_t OldSize = Infos.size();
> - bool Inserted;
> - StringMap<PerFileInfo>::iterator It;
> - std::tie(It, Inserted) = Infos.insert(
> - std::make_pair(Filename, PerFileInfo{OldSize, LastOffset}));
> - if (Inserted) {
> - LastOffset += Filename.size() + 1;
> - Filenames.push_back(Filename);
> - }
> - return It->second.FilenameID;
> - }
> -
> - void clear() {
> - LastOffset = 1;
> - Infos.clear();
> - Filenames.clear();
> - }
> - } FileNameRegistry;
> + unsigned NextFuncId = 0;
> +
> + /// Remember some debug info about each function. Keep it in a stable
> order to
> + /// emit at the end of the TU.
> + MapVector<const Function *, FunctionInfo> FnDebugInfo;
> +
> + /// Map from DIFile to .cv_file id.
> + DenseMap<const DIFile *, unsigned> FileIdMap;
>
> typedef std::map<const DIFile *, std::string> FileToFilepathMapTy;
> FileToFilepathMapTy FileToFilepathMap;
> StringRef getFullFilepath(const DIFile *S);
>
> + unsigned maybeRecordFile(const DIFile *F);
> +
> void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF);
>
> void clear() {
> assert(CurFn == nullptr);
> - FileNameRegistry.clear();
> - LabelsAndLocs.clear();
> + FileIdMap.clear();
> + FnDebugInfo.clear();
> + FileToFilepathMap.clear();
> }
>
> - void emitDebugInfoForFunction(const Function *GV);
> + void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
>
> public:
> CodeViewDebug(AsmPrinter *Asm);
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/LLVMBuild.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/LLVMBuild.txt?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/LLVMBuild.txt (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/LLVMBuild.txt Thu Jan 28 18:49:42
> 2016
> @@ -19,4 +19,4 @@
> type = Library
> name = AsmPrinter
> parent = Libraries
> -required_libraries = Analysis CodeGen Core MC MCParser Support Target
> TransformUtils
> +required_libraries = Analysis CodeGen Core DebugInfoCodeView MC MCParser
> Support Target TransformUtils
>
> Modified: llvm/trunk/lib/MC/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/CMakeLists.txt?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/CMakeLists.txt (original)
> +++ llvm/trunk/lib/MC/CMakeLists.txt Thu Jan 28 18:49:42 2016
> @@ -10,6 +10,7 @@ add_llvm_library(LLVMMC
> MCAssembler.cpp
> MCCodeEmitter.cpp
> MCCodeGenInfo.cpp
> + MCCodeView.cpp
> MCContext.cpp
> MCDwarf.cpp
> MCELFObjectTargetWriter.cpp
>
> Modified: llvm/trunk/lib/MC/MCAsmStreamer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCAsmStreamer.cpp (original)
> +++ llvm/trunk/lib/MC/MCAsmStreamer.cpp Thu Jan 28 18:49:42 2016
> @@ -199,6 +199,15 @@ public:
> StringRef FileName) override;
> MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
>
> + unsigned EmitCVFileDirective(unsigned FileNo, StringRef Filename)
> override;
> + void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned
> Line,
> + unsigned Column, bool PrologueEnd, bool IsStmt,
> + StringRef FileName) override;
> + void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol
> *FnStart,
> + const MCSymbol *FnEnd) override;
> + void EmitCVStringTableDirective() override;
> + void EmitCVFileChecksumsDirective() override;
> +
> void EmitIdent(StringRef IdentString) override;
> void EmitCFISections(bool EH, bool Debug) override;
> void EmitCFIDefCfa(int64_t Register, int64_t Offset) override;
> @@ -954,6 +963,69 @@ MCSymbol *MCAsmStreamer::getDwarfLineTab
> return MCStreamer::getDwarfLineTableSymbol(0);
> }
>
> +unsigned MCAsmStreamer::EmitCVFileDirective(unsigned FileNo,
> + StringRef Filename) {
> + if (!getContext().getCVFile(Filename, FileNo))
> + return 0;
> +
> + OS << "\t.cv_file\t" << FileNo << ' ';
> +
> + PrintQuotedString(Filename, OS);
> + EmitEOL();
> +
> + return FileNo;
> +}
> +
> +void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned
> FileNo,
> + unsigned Line, unsigned Column,
> + bool PrologueEnd, bool IsStmt,
> + StringRef FileName) {
> + OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
> + << Column;
> + if (PrologueEnd)
> + OS << " prologue_end";
> +
> + unsigned OldIsStmt = getContext().getCurrentCVLoc().isStmt();
> + if (IsStmt != OldIsStmt) {
> + OS << " is_stmt ";
> +
> + if (IsStmt)
> + OS << "1";
> + else
> + OS << "0";
> + }
> +
> + if (IsVerboseAsm) {
> + OS.PadToColumn(MAI->getCommentColumn());
> + OS << MAI->getCommentString() << ' ' << FileName << ':'
> + << Line << ':' << Column;
> + }
> + EmitEOL();
> + this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
> + PrologueEnd, IsStmt, FileName);
> +}
> +
> +void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
> + const MCSymbol *FnStart,
> + const MCSymbol *FnEnd) {
> + OS << "\t.cv_linetable\t" << FunctionId << ", ";
> + FnStart->print(OS, MAI);
> + OS << ", ";
> + FnEnd->print(OS, MAI);
> + EmitEOL();
> + this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd);
> +}
> +
> +void MCAsmStreamer::EmitCVStringTableDirective() {
> + OS << "\t.cv_stringtable";
> + EmitEOL();
> +}
> +
> +void MCAsmStreamer::EmitCVFileChecksumsDirective() {
> + OS << "\t.cv_filechecksums";
> + EmitEOL();
> +}
> +
> void MCAsmStreamer::EmitIdent(StringRef IdentString) {
> assert(MAI->hasIdentDirective() && ".ident directive not supported");
> OS << "\t.ident\t";
>
> Added: llvm/trunk/lib/MC/MCCodeView.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCCodeView.cpp?rev=259130&view=auto
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCCodeView.cpp (added)
> +++ llvm/trunk/lib/MC/MCCodeView.cpp Thu Jan 28 18:49:42 2016
> @@ -0,0 +1,222 @@
> +//===- MCCodeView.h - Machine Code CodeView support -------------*- C++
> -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +//
> +// Holds state from .cv_file and .cv_loc directives for later emission.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/MC/MCCodeView.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/DebugInfo/CodeView/CodeView.h"
> +#include "llvm/DebugInfo/CodeView/Line.h"
> +#include "llvm/MC/MCContext.h"
> +#include "llvm/MC/MCObjectStreamer.h"
> +#include "llvm/Support/COFF.h"
> +
> +using namespace llvm;
> +using namespace llvm::codeview;
> +
> +CodeViewContext::CodeViewContext() {}
> +
> +CodeViewContext::~CodeViewContext() {
> + // If someone inserted strings into the string table but never actually
> + // emitted them somewhere, clean up the fragment.
> + if (!InsertedStrTabFragment)
> + delete StrTabFragment;
> +}
> +
> +/// This is a valid number for use with .cv_loc if we've already seen a
> .cv_file
> +/// for it.
> +bool CodeViewContext::isValidFileNumber(unsigned FileNumber) const {
> + unsigned Idx = FileNumber - 1;
> + if (Idx < Filenames.size())
> + return !Filenames[Idx].empty();
> + return false;
> +}
> +
> +bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) {
> + assert(FileNumber > 0);
> + Filename = addToStringTable(Filename);
> + unsigned Idx = FileNumber - 1;
> + if (Idx >= Filenames.size())
> + Filenames.resize(Idx + 1);
> +
> + if (Filename.empty())
> + Filename = "<stdin>";
> +
> + if (!Filenames[Idx].empty())
> + return false;
> +
> + // FIXME: We should store the string table offset of the filename,
> rather than
> + // the filename itself for efficiency.
> + Filename = addToStringTable(Filename);
> +
> + Filenames[Idx] = Filename;
> + return true;
> +}
> +
> +MCDataFragment *CodeViewContext::getStringTableFragment() {
> + if (!StrTabFragment) {
> + StrTabFragment = new MCDataFragment();
> + // Start a new string table out with a null byte.
> + StrTabFragment->getContents().push_back('\0');
> + }
> + return StrTabFragment;
> +}
> +
> +StringRef CodeViewContext::addToStringTable(StringRef S) {
> + SmallVectorImpl<char> &Contents =
> getStringTableFragment()->getContents();
> + auto Insertion =
> + StringTable.insert(std::make_pair(S, unsigned(Contents.size())));
> + // Return the string from the table, since it is stable.
> + S = Insertion.first->first();
> + if (Insertion.second) {
> + // The string map key is always null terminated.
> + Contents.append(S.begin(), S.end() + 1);
> + }
> + return S;
> +}
> +
> +unsigned CodeViewContext::getStringTableOffset(StringRef S) {
> + // A string table offset of zero is always the empty string.
> + if (S.empty())
> + return 0;
> + auto I = StringTable.find(S);
> + assert(I != StringTable.end());
> + return I->second;
> +}
> +
> +void CodeViewContext::emitStringTable(MCObjectStreamer &OS) {
> + MCContext &Ctx = OS.getContext();
> + MCSymbol *StringBegin = Ctx.createTempSymbol("strtab_begin"),
> + *StringEnd = Ctx.createTempSymbol("strtab_end");
> +
> + OS.EmitIntValue(unsigned(ModuleSubstreamKind::StringTable), 4);
> + OS.emitAbsoluteSymbolDiff(StringEnd, StringBegin, 4);
> + OS.EmitLabel(StringBegin);
> +
> + // Put the string table data fragment here, if we haven't already put it
> + // somewhere else. If somebody wants two string tables in their .s
> file, one
> + // will just be empty.
> + if (!InsertedStrTabFragment) {
> + OS.insert(getStringTableFragment());
> + InsertedStrTabFragment = true;
> + }
> +
> + OS.EmitValueToAlignment(4, 0);
> +
> + OS.EmitLabel(StringEnd);
> +}
> +
> +void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
> + MCContext &Ctx = OS.getContext();
> + MCSymbol *FileBegin = Ctx.createTempSymbol("filechecksums_begin"),
> + *FileEnd = Ctx.createTempSymbol("filechecksums_end");
> +
> + OS.EmitIntValue(unsigned(ModuleSubstreamKind::FileChecksums), 4);
> + OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4);
> + OS.EmitLabel(FileBegin);
> +
> + // Emit an array of FileChecksum entries. We index into this table
> using the
> + // user-provided file number. Each entry is currently 8 bytes, as we
> don't
> + // emit checksums.
> + for (StringRef Filename : Filenames) {
> + OS.EmitIntValue(getStringTableOffset(Filename), 4);
> + // Zero the next two fields and align back to 4 bytes. This indicates
> that
> + // no checksum is present.
> + OS.EmitIntValue(0, 4);
> + }
> +
> + OS.EmitLabel(FileEnd);
> +}
> +
> +void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
> + unsigned FuncId,
> + const MCSymbol *FuncBegin,
> + const MCSymbol *FuncEnd) {
> + MCContext &Ctx = OS.getContext();
> + MCSymbol *LineBegin = Ctx.createTempSymbol("linetable_begin"),
> + *LineEnd = Ctx.createTempSymbol("linetable_end");
> +
> + OS.EmitIntValue(unsigned(ModuleSubstreamKind::Lines), 4);
> + OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4);
> + OS.EmitLabel(LineBegin);
> + OS.EmitCOFFSecRel32(FuncBegin);
> + OS.EmitCOFFSectionIndex(FuncBegin);
> +
> + // Actual line info.
> + ArrayRef<MCCVLineEntry> Locs = getFunctionLineEntries(FuncId);
> + bool HaveColumns = any_of(Locs, [](const MCCVLineEntry &LineEntry) {
> + return LineEntry.getColumn() != 0;
> + });
> + OS.EmitIntValue(HaveColumns ? int(codeview::LineFlags::HaveColumns) :
> 0, 2);
> + OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4);
> +
> + for (auto I = Locs.begin(), E = Locs.end(); I != E;) {
> + // Emit a file segment for the run of locations that share a file id.
> + unsigned CurFileNum = I->getFileNum();
> + auto FileSegEnd =
> + std::find_if(I, E, [CurFileNum](const MCCVLineEntry &Loc) {
> + return Loc.getFileNum() != CurFileNum;
> + });
> + unsigned EntryCount = FileSegEnd - I;
> + OS.AddComment("Segment for file '" + Twine(Filenames[CurFileNum - 1])
> +
> + "' begins");
> + OS.EmitIntValue(8 * (CurFileNum - 1), 4);
> + OS.EmitIntValue(EntryCount, 4);
> + uint32_t SegmentSize = 12;
> + SegmentSize += 8 * EntryCount;
> + if (HaveColumns)
> + SegmentSize += 4 * EntryCount;
> + OS.EmitIntValue(SegmentSize, 4);
> +
> + for (auto J = I; J != FileSegEnd; ++J) {
> + OS.emitAbsoluteSymbolDiff(J->getLabel(), FuncBegin, 4);
> + unsigned LineData = J->getLine();
> + if (J->isStmt())
> + LineData |= codeview::LineInfo::StatementFlag;
> + OS.EmitIntValue(LineData, 4);
> + }
> + if (HaveColumns) {
> + for (auto J = I; J != FileSegEnd; ++J) {
> + OS.EmitIntValue(J->getColumn(), 2);
> + OS.EmitIntValue(0, 2);
> + }
> + }
> + I = FileSegEnd;
> + }
> + OS.EmitLabel(LineEnd);
> +}
> +
> +//
> +// This is called when an instruction is assembled into the specified
> section
> +// and if there is information from the last .cv_loc directive that has
> yet to have
> +// a line entry made for it is made.
> +//
> +void MCCVLineEntry::Make(MCObjectStreamer *MCOS) {
> + if (!MCOS->getContext().getCVLocSeen())
> + return;
> +
> + // Create a symbol at in the current section for use in the line entry.
> + MCSymbol *LineSym = MCOS->getContext().createTempSymbol();
> + // Set the value of the symbol to use for the MCCVLineEntry.
> + MCOS->EmitLabel(LineSym);
> +
> + // Get the current .loc info saved in the context.
> + const MCCVLoc &CVLoc = MCOS->getContext().getCurrentCVLoc();
> +
> + // Create a (local) line entry with the symbol and the current .loc
> info.
> + MCCVLineEntry LineEntry(LineSym, CVLoc);
> +
> + // clear CVLocSeen saying the current .loc info is now used.
> + MCOS->getContext().clearCVLocSeen();
> +
> + // Add the line entry to this section's entries.
> + MCOS->getContext().getCVContext().addLineEntry(LineEntry);
> +}
>
> Modified: llvm/trunk/lib/MC/MCContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCContext.cpp?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCContext.cpp (original)
> +++ llvm/trunk/lib/MC/MCContext.cpp Thu Jan 28 18:49:42 2016
> @@ -12,6 +12,7 @@
> #include "llvm/ADT/Twine.h"
> #include "llvm/MC/MCAssembler.h"
> #include "llvm/MC/MCAsmInfo.h"
> +#include "llvm/MC/MCCodeView.h"
> #include "llvm/MC/MCDwarf.h"
> #include "llvm/MC/MCLabel.h"
> #include "llvm/MC/MCObjectFileInfo.h"
> @@ -90,6 +91,8 @@ void MCContext::reset() {
> DwarfCompileUnitID = 0;
> CurrentDwarfLoc = MCDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0);
>
> + CVContext.reset();
> +
> MachOUniquingMap.clear();
> ELFUniquingMap.clear();
> COFFUniquingMap.clear();
> @@ -474,6 +477,20 @@ void MCContext::finalizeDwarfSections(MC
> [&](MCSection *Sec) { return !MCOS.mayHaveInstructions(*Sec); });
> }
>
> +CodeViewContext &MCContext::getCVContext() {
> + if (!CVContext.get())
> + CVContext.reset(new CodeViewContext);
> + return *CVContext.get();
> +}
> +
> +unsigned MCContext::getCVFile(StringRef FileName, unsigned FileNumber) {
> + return getCVContext().addFile(FileNumber, FileName) ? FileNumber : 0;
> +}
> +
> +bool MCContext::isValidCVFileNumber(unsigned FileNumber) {
> + return getCVContext().isValidFileNumber(FileNumber);
> +}
> +
>
> //===----------------------------------------------------------------------===//
> // Error Reporting
>
> //===----------------------------------------------------------------------===//
>
> Modified: llvm/trunk/lib/MC/MCObjectStreamer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectStreamer.cpp?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCObjectStreamer.cpp (original)
> +++ llvm/trunk/lib/MC/MCObjectStreamer.cpp Thu Jan 28 18:49:42 2016
> @@ -125,6 +125,7 @@ void MCObjectStreamer::EmitValueImpl(con
> MCDataFragment *DF = getOrCreateDataFragment();
> flushPendingLabels(DF, DF->getContents().size());
>
> + MCCVLineEntry::Make(this);
> MCDwarfLineEntry::Make(this, getCurrentSection().first);
>
> // Avoid fixups when possible.
> @@ -232,6 +233,7 @@ void MCObjectStreamer::EmitInstruction(c
>
> // Now that a machine instruction has been assembled into this section,
> make
> // a line entry for any .loc directive that has been seen.
> + MCCVLineEntry::Make(this);
> MCDwarfLineEntry::Make(this, getCurrentSection().first);
>
> // If this instruction doesn't need relaxation, just emit it as data.
> @@ -362,7 +364,36 @@ void MCObjectStreamer::EmitDwarfAdvanceF
> insert(new MCDwarfCallFrameFragment(*AddrDelta));
> }
>
> +void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned
> FileNo,
> + unsigned Line, unsigned Column,
> + bool PrologueEnd, bool IsStmt,
> + StringRef FileName) {
> + // In case we see two .cv_loc directives in a row, make sure the
> + // first one gets a line entry.
> + MCCVLineEntry::Make(this);
> +
> + this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
> + PrologueEnd, IsStmt, FileName);
> +}
> +
> +void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId,
> + const MCSymbol *Begin,
> + const MCSymbol *End) {
> + getContext().getCVContext().emitLineTableForFunction(*this, FunctionId,
> Begin,
> + End);
> + this->MCStreamer::EmitCVLinetableDirective(FunctionId, Begin, End);
> +}
> +
> +void MCObjectStreamer::EmitCVStringTableDirective() {
> + getContext().getCVContext().emitStringTable(*this);
> +}
> +void MCObjectStreamer::EmitCVFileChecksumsDirective() {
> + getContext().getCVContext().emitFileChecksums(*this);
> +}
> +
> +
> void MCObjectStreamer::EmitBytes(StringRef Data) {
> + MCCVLineEntry::Make(this);
> MCDwarfLineEntry::Make(this, getCurrentSection().first);
> MCDataFragment *DF = getOrCreateDataFragment();
> flushPendingLabels(DF, DF->getContents().size());
>
> Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original)
> +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Thu Jan 28 18:49:42 2016
> @@ -357,6 +357,8 @@ private:
> DK_IFNB, DK_IFC, DK_IFEQS, DK_IFNC, DK_IFNES, DK_IFDEF, DK_IFNDEF,
> DK_IFNOTDEF, DK_ELSEIF, DK_ELSE, DK_ENDIF,
> DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS,
> + DK_CV_FILE, DK_CV_LOC, DK_CV_LINETABLE, DK_CV_STRINGTABLE,
> + DK_CV_FILECHECKSUMS,
> DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA,
> DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET,
> DK_CFI_DEF_CFA_REGISTER,
> DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA,
> @@ -394,6 +396,13 @@ private:
> bool parseDirectiveLoc();
> bool parseDirectiveStabs();
>
> + // ".cv_file", ".cv_loc", ".cv_linetable"
> + bool parseDirectiveCVFile();
> + bool parseDirectiveCVLoc();
> + bool parseDirectiveCVLinetable();
> + bool parseDirectiveCVStringTable();
> + bool parseDirectiveCVFileChecksums();
> +
> // .cfi directives
> bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
> bool parseDirectiveCFIWindowSave();
> @@ -1638,6 +1647,16 @@ bool AsmParser::parseStatement(ParseStat
> return parseDirectiveLoc();
> case DK_STABS:
> return parseDirectiveStabs();
> + case DK_CV_FILE:
> + return parseDirectiveCVFile();
> + case DK_CV_LOC:
> + return parseDirectiveCVLoc();
> + case DK_CV_LINETABLE:
> + return parseDirectiveCVLinetable();
> + case DK_CV_STRINGTABLE:
> + return parseDirectiveCVStringTable();
> + case DK_CV_FILECHECKSUMS:
> + return parseDirectiveCVFileChecksums();
> case DK_CFI_SECTIONS:
> return parseDirectiveCFISections();
> case DK_CFI_STARTPROC:
> @@ -3070,6 +3089,156 @@ bool AsmParser::parseDirectiveStabs() {
> return TokError("unsupported directive '.stabs'");
> }
>
> +/// parseDirectiveCVFile
> +/// ::= .cv_file number filename
> +bool AsmParser::parseDirectiveCVFile() {
> + SMLoc FileNumberLoc = getLexer().getLoc();
> + if (getLexer().isNot(AsmToken::Integer))
> + return TokError("expected file number in '.cv_file' directive");
> +
> + int64_t FileNumber = getTok().getIntVal();
> + Lex();
> +
> + if (FileNumber < 1)
> + return TokError("file number less than one");
> +
> + if (getLexer().isNot(AsmToken::String))
> + return TokError("unexpected token in '.cv_file' directive");
> +
> + // Usually the directory and filename together, otherwise just the
> directory.
> + // Allow the strings to have escaped octal character sequence.
> + std::string Filename;
> + if (parseEscapedString(Filename))
> + return true;
> + Lex();
> +
> + if (getLexer().isNot(AsmToken::EndOfStatement))
> + return TokError("unexpected token in '.cv_file' directive");
> +
> + if (getStreamer().EmitCVFileDirective(FileNumber, Filename) == 0)
> + Error(FileNumberLoc, "file number already allocated");
> +
> + return false;
> +}
> +
> +/// parseDirectiveCVLoc
> +/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos]
> [prologue_end]
> +/// [is_stmt VALUE]
> +/// The first number is a file number, must have been previously assigned
> with
> +/// a .file directive, the second number is the line number and
> optionally the
> +/// third number is a column position (zero if not specified). The
> remaining
> +/// optional items are .loc sub-directives.
> +bool AsmParser::parseDirectiveCVLoc() {
> + if (getLexer().isNot(AsmToken::Integer))
> + return TokError("unexpected token in '.cv_loc' directive");
> +
> + int64_t FunctionId = getTok().getIntVal();
> + if (FunctionId < 0)
> + return TokError("function id less than zero in '.cv_loc' directive");
> + Lex();
> +
> + int64_t FileNumber = getTok().getIntVal();
> + if (FileNumber < 1)
> + return TokError("file number less than one in '.cv_loc' directive");
> + if (!getContext().isValidCVFileNumber(FileNumber))
> + return TokError("unassigned file number in '.cv_loc' directive");
> + Lex();
> +
> + int64_t LineNumber = 0;
> + if (getLexer().is(AsmToken::Integer)) {
> + LineNumber = getTok().getIntVal();
> + if (LineNumber < 0)
> + return TokError("line number less than zero in '.cv_loc'
> directive");
> + Lex();
> + }
> +
> + int64_t ColumnPos = 0;
> + if (getLexer().is(AsmToken::Integer)) {
> + ColumnPos = getTok().getIntVal();
> + if (ColumnPos < 0)
> + return TokError("column position less than zero in '.cv_loc'
> directive");
> + Lex();
> + }
> +
> + bool PrologueEnd = false;
> + uint64_t IsStmt = 0;
> + while (getLexer().isNot(AsmToken::EndOfStatement)) {
> + StringRef Name;
> + SMLoc Loc = getTok().getLoc();
> + if (parseIdentifier(Name))
> + return TokError("unexpected token in '.cv_loc' directive");
> +
> + if (Name == "prologue_end")
> + PrologueEnd = true;
> + else if (Name == "is_stmt") {
> + Loc = getTok().getLoc();
> + const MCExpr *Value;
> + if (parseExpression(Value))
> + return true;
> + // The expression must be the constant 0 or 1.
> + IsStmt = ~0ULL;
> + if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
> + IsStmt = MCE->getValue();
> +
> + if (IsStmt > 1)
> + return Error(Loc, "is_stmt value not 0 or 1");
> + } else {
> + return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
> + }
> + }
> +
> + getStreamer().EmitCVLocDirective(FunctionId, FileNumber, LineNumber,
> + ColumnPos, PrologueEnd, IsStmt,
> StringRef());
> + return false;
> +}
> +
> +/// parseDirectiveCVLinetable
> +/// ::= .cv_linetable FunctionId, FnStart, FnEnd
> +bool AsmParser::parseDirectiveCVLinetable() {
> + int64_t FunctionId = getTok().getIntVal();
> + if (FunctionId < 0)
> + return TokError("function id less than zero in '.cv_linetable'
> directive");
> + Lex();
> +
> + if (Lexer.isNot(AsmToken::Comma))
> + return TokError("unexpected token in '.cv_linetable' directive");
> + Lex();
> +
> + SMLoc Loc = getLexer().getLoc();
> + StringRef FnStartName;
> + if (parseIdentifier(FnStartName))
> + return Error(Loc, "expected identifier in directive");
> +
> + if (Lexer.isNot(AsmToken::Comma))
> + return TokError("unexpected token in '.cv_linetable' directive");
> + Lex();
> +
> + Loc = getLexer().getLoc();
> + StringRef FnEndName;
> + if (parseIdentifier(FnEndName))
> + return Error(Loc, "expected identifier in directive");
> +
> + MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
> + MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
> +
> + getStreamer().EmitCVLinetableDirective(FunctionId, FnStartSym,
> FnEndSym);
> + return false;
> +}
> +
> +/// parseDirectiveCVStringTable
> +/// ::= .cv_stringtable
> +bool AsmParser::parseDirectiveCVStringTable() {
> + getStreamer().EmitCVStringTableDirective();
> + return false;
> +}
> +
> +/// parseDirectiveCVFileChecksums
> +/// ::= .cv_filechecksums
> +bool AsmParser::parseDirectiveCVFileChecksums() {
> + getStreamer().EmitCVFileChecksumsDirective();
> + return false;
> +}
> +
> /// parseDirectiveCFISections
> /// ::= .cfi_sections section [, section]
> bool AsmParser::parseDirectiveCFISections() {
> @@ -4381,6 +4550,11 @@ void AsmParser::initializeDirectiveKindM
> DirectiveKindMap[".line"] = DK_LINE;
> DirectiveKindMap[".loc"] = DK_LOC;
> DirectiveKindMap[".stabs"] = DK_STABS;
> + DirectiveKindMap[".cv_file"] = DK_CV_FILE;
> + DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
> + DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
> + DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
> + DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
> DirectiveKindMap[".sleb128"] = DK_SLEB128;
> DirectiveKindMap[".uleb128"] = DK_ULEB128;
> DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
>
> Modified: llvm/trunk/lib/MC/MCStreamer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCStreamer.cpp (original)
> +++ llvm/trunk/lib/MC/MCStreamer.cpp Thu Jan 28 18:49:42 2016
> @@ -180,6 +180,22 @@ void MCStreamer::EnsureValidDwarfFrame()
> report_fatal_error("No open frame");
> }
>
> +unsigned MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef
> Filename) {
> + return getContext().getCVFile(Filename, FileNo);
> +}
> +
> +void MCStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
> + unsigned Line, unsigned Column,
> + bool PrologueEnd, bool IsStmt,
> + StringRef FileName) {
> + getContext().setCurrentCVLoc(FunctionId, FileNo, Line, Column,
> PrologueEnd,
> + IsStmt);
> +}
> +
> +void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId,
> + const MCSymbol *Begin,
> + const MCSymbol *End) {}
> +
> void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
> MCSymbol *EHSymbol) {
> }
>
> Modified: llvm/trunk/lib/MC/StringTableBuilder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/StringTableBuilder.cpp?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/StringTableBuilder.cpp (original)
> +++ llvm/trunk/lib/MC/StringTableBuilder.cpp Thu Jan 28 18:49:42 2016
> @@ -16,7 +16,22 @@
>
> using namespace llvm;
>
> -StringTableBuilder::StringTableBuilder(Kind K) : K(K) {}
> +StringTableBuilder::StringTableBuilder(Kind K) : K(K) {
> + // Account for leading bytes in table so that offsets returned from add
> are
> + // correct.
> + switch (K) {
> + case RAW:
> + Size = 0;
> + break;
> + case MachO:
> + case ELF:
> + Size = 1;
> + break;
> + case WinCOFF:
> + Size = 4;
> + break;
> + }
> +}
>
> typedef std::pair<StringRef, size_t> StringPair;
>
> @@ -62,13 +77,32 @@ tailcall:
> }
>
> void StringTableBuilder::finalize() {
> - std::vector<std::pair<StringRef, size_t> *> Strings;
> + finalizeStringTable(/*Optimize=*/true);
> +}
> +
> +void StringTableBuilder::finalizeInOrder() {
> + finalizeStringTable(/*Optimize=*/false);
> +}
> +
> +void StringTableBuilder::finalizeStringTable(bool Optimize) {
> + typedef std::pair<StringRef, size_t> StringOffsetPair;
> + std::vector<StringOffsetPair *> Strings;
> Strings.reserve(StringIndexMap.size());
> - for (std::pair<StringRef, size_t> &P : StringIndexMap)
> + for (StringOffsetPair &P : StringIndexMap)
> Strings.push_back(&P);
>
> - if (!Strings.empty())
> - multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0);
> + if (!Strings.empty()) {
> + // If we're optimizing, sort by name. If not, sort by previously
> assigned
> + // offset.
> + if (Optimize) {
> + multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0);
> + } else {
> + std::sort(Strings.begin(), Strings.end(),
> + [](const StringOffsetPair *LHS, const StringOffsetPair
> *RHS) {
> + return LHS->second < RHS->second;
> + });
> + }
> + }
>
> switch (K) {
> case RAW:
> @@ -85,17 +119,22 @@ void StringTableBuilder::finalize() {
> }
>
> StringRef Previous;
> - for (std::pair<StringRef, size_t> *P : Strings) {
> + for (StringOffsetPair *P : Strings) {
> StringRef S = P->first;
> if (K == WinCOFF)
> assert(S.size() > COFF::NameSize && "Short string in COFF string
> table!");
>
> - if (Previous.endswith(S)) {
> + if (Optimize && Previous.endswith(S)) {
> P->second = StringTable.size() - S.size() - (K != RAW);
> continue;
> }
>
> - P->second = StringTable.size();
> + if (Optimize)
> + P->second = StringTable.size();
> + else
> + assert(P->second == StringTable.size() &&
> + "different strtab offset after finalization");
> +
> StringTable += S;
> if (K != RAW)
> StringTable += '\x00';
>
> Modified: llvm/trunk/test/DebugInfo/COFF/asm.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/asm.ll?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/COFF/asm.ll (original)
> +++ llvm/trunk/test/DebugInfo/COFF/asm.ll Thu Jan 28 18:49:42 2016
> @@ -13,11 +13,11 @@
> ; 6 }
>
> ; X86-LABEL: _f:
> -; X86: # BB
> -; X86-NEXT: [[ASM_LINE:^L.*]]:{{$}}
> -; X86: [[CALL_LINE:^L.*]]:{{$}}
> +; X86: .cv_file 1 "D:\\asm.c"
> +; X86: .cv_loc 0 1 4 0 is_stmt 0
> +; X86: .cv_loc 0 1 5 0
> ; X86: calll _g
> -; X86-NEXT: [[RETURN_STMT:.*]]:
> +; X86: .cv_loc 0 1 6 0
> ; X86: ret
> ; X86-NEXT: [[END_OF_F:^L.*]]:
> ;
> @@ -45,48 +45,15 @@
> ; Padding
> ; X86-NEXT: .zero 3
> ; Line table
> -; X86-NEXT: .long 242
> -; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X86-NEXT: [[F2_START]]:
> -; X86-NEXT: .secrel32 _f
> -; X86-NEXT: .secidx _f
> -; X86-NEXT: .short 1
> -; X86-NEXT: .long [[END_OF_F]]-_f
> -; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X86-NEXT: .long 0
> -; X86-NEXT: .long 3
> -; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X86-NEXT: .long [[ASM_LINE]]-_f
> -; X86-NEXT: .long -2147483644
> -; X86-NEXT: .long [[CALL_LINE]]-_f
> -; X86-NEXT: .long -2147483643
> -; X86-NEXT: .long [[RETURN_STMT]]-_f
> -; X86-NEXT: .long -2147483642
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: [[FILE_SEGMENT_END]]:
> -; X86-NEXT: [[F2_END]]:
> +; X86-NEXT: .cv_linetable 0, _f, [[END_OF_F]]
> ; File index to string table offset subsection
> -; X86-NEXT: .long 244
> -; X86-NEXT: .long 8
> -; X86-NEXT: .long 1
> -; X86-NEXT: .long 0
> +; X86-NEXT: .cv_filechecksums
> ; String table
> -; X86-NEXT: .long 243
> -; X86-NEXT: .long 10
> -; X86-NEXT: .byte 0
> -; X86-NEXT: .ascii "D:\\asm.c"
> -; X86-NEXT: .byte 0
> -; Padding
> -; X86-NEXT: .zero 2
> +; X86-NEXT: .cv_stringtable
>
> ; OBJ32: Section {
> ; OBJ32: Name: .debug$S (2E 64 65 62 75 67 24 53)
> -; OBJ32: Characteristics [ (0x42100040)
> +; OBJ32: Characteristics [ (0x42300040)
> ; OBJ32: ]
> ; OBJ32: Relocations [
> ; OBJ32-NEXT: 0x2C IMAGE_REL_I386_SECREL _f
> @@ -107,7 +74,7 @@
> ; OBJ32-NEXT: ]
> ; OBJ32: FunctionLineTable [
> ; OBJ32-NEXT: Name: _f
> -; OBJ32-NEXT: Flags: 0x1
> +; OBJ32-NEXT: Flags: 0x0
> ; OBJ32-NEXT: CodeSize: 0x6
> ; OBJ32-NEXT: FilenameSegment [
> ; OBJ32-NEXT: Filename: D:\asm.c
> @@ -118,34 +85,27 @@
> ; OBJ32-NEXT: LineNumberStart: 4
> ; OBJ32-NEXT: LineNumberEndDelta: 0
> ; OBJ32-NEXT: IsStatement: Yes
> -; OBJ32-NEXT: ColStart: 0
> -; OBJ32-NEXT: ColEnd: 0
> ; OBJ32-NEXT: ]
> ; OBJ32-NEXT: +0x0 [
> ; OBJ32-NEXT: LineNumberStart: 5
> ; OBJ32-NEXT: LineNumberEndDelta: 0
> ; OBJ32-NEXT: IsStatement: Yes
> -; OBJ32-NEXT: ColStart: 0
> -; OBJ32-NEXT: ColEnd: 0
> ; OBJ32-NEXT: ]
> ; OBJ32-NEXT: +0x5 [
> ; OBJ32-NEXT: LineNumberStart: 6
> ; OBJ32-NEXT: LineNumberEndDelta: 0
> ; OBJ32-NEXT: IsStatement: Yes
> -; OBJ32-NEXT: ColStart: 0
> -; OBJ32-NEXT: ColEnd: 0
> ; OBJ32-NEXT: ]
> ; OBJ32-NEXT: ]
>
> ; X64-LABEL: f:
> -; X64-NEXT: .L{{.*}}:{{$}}
> -; X64-NEXT: [[START:.*]]:{{$}}
> -; X64: # BB
> +; X64: .cv_file 1 "D:\\asm.c"
> +; X64: .cv_loc 0 1 3 0 is_stmt 0
> ; X64: subq $40, %rsp
> -; X64-NEXT: [[ASM_LINE:.*]]:{{$}}
> -; X64: [[CALL_LINE:.*]]:{{$}}
> +; X64: .cv_loc 0 1 4 0
> +; X64: .cv_loc 0 1 5 0
> ; X64: callq g
> -; X64-NEXT: [[EPILOG_AND_RET:.*]]:
> +; X64: .cv_loc 0 1 6 0
> ; X64: addq $40, %rsp
> ; X64-NEXT: ret
> ; X64-NEXT: [[END_OF_F:.*]]:
> @@ -174,52 +134,15 @@
> ; Padding
> ; X64-NEXT: .zero 3
> ; Line table
> -; X64-NEXT: .long 242
> -; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X64-NEXT: [[F2_START]]:
> -; X64-NEXT: .secrel32 f
> -; X64-NEXT: .secidx f
> -; X64-NEXT: .short 1
> -; X64-NEXT: .long [[END_OF_F]]-f
> -; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X64-NEXT: .long 0
> -; X64-NEXT: .long 4
> -; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X64-NEXT: .long [[START]]-f
> -; X64-NEXT: .long -2147483645
> -; X64-NEXT: .long [[ASM_LINE]]-f
> -; X64-NEXT: .long -2147483644
> -; X64-NEXT: .long [[CALL_LINE]]-f
> -; X64-NEXT: .long -2147483643
> -; X64-NEXT: .long [[EPILOG_AND_RET]]-f
> -; X64-NEXT: .long -2147483642
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: [[FILE_SEGMENT_END]]:
> -; X64-NEXT: [[F2_END]]:
> +; X64-NEXT: .cv_linetable 0, f, [[END_OF_F]]
> ; File index to string table offset subsection
> -; X64-NEXT: .long 244
> -; X64-NEXT: .long 8
> -; X64-NEXT: .long 1
> -; X64-NEXT: .long 0
> +; X64-NEXT: .cv_filechecksums
> ; String table
> -; X64-NEXT: .long 243
> -; X64-NEXT: .long 10
> -; X64-NEXT: .byte 0
> -; X64-NEXT: .ascii "D:\\asm.c"
> -; X64-NEXT: .byte 0
> -; Padding
> -; X64-NEXT: .zero 2
> +; X64-NEXT: .cv_stringtable
>
> ; OBJ64: Section {
> ; OBJ64: Name: .debug$S (2E 64 65 62 75 67 24 53)
> -; OBJ64: Characteristics [ (0x42100040)
> +; OBJ64: Characteristics [ (0x42300040)
> ; OBJ64: ]
> ; OBJ64: Relocations [
> ; OBJ64-NEXT: 0x2C IMAGE_REL_AMD64_SECREL f
> @@ -239,7 +162,7 @@
> ; OBJ64-NEXT: ]
> ; OBJ64: FunctionLineTable [
> ; OBJ64-NEXT: Name: f
> -; OBJ64-NEXT: Flags: 0x1
> +; OBJ64-NEXT: Flags: 0x0
> ; OBJ64-NEXT: CodeSize: 0xE
> ; OBJ64-NEXT: FilenameSegment [
> ; OBJ64-NEXT: Filename: D:\asm.c
> @@ -249,29 +172,21 @@
> ; OBJ64-NEXT: LineNumberStart: 3
> ; OBJ64-NEXT: LineNumberEndDelta: 0
> ; OBJ64-NEXT: IsStatement: Yes
> -; OBJ64-NEXT: ColStart: 0
> -; OBJ64-NEXT: ColEnd: 0
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: +0x4 [
> ; OBJ64-NEXT: LineNumberStart: 4
> ; OBJ64-NEXT: LineNumberEndDelta: 0
> ; OBJ64-NEXT: IsStatement: Yes
> -; OBJ64-NEXT: ColStart: 0
> -; OBJ64-NEXT: ColEnd: 0
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: +0x4 [
> ; OBJ64-NEXT: LineNumberStart: 5
> ; OBJ64-NEXT: LineNumberEndDelta: 0
> ; OBJ64-NEXT: IsStatement: Yes
> -; OBJ64-NEXT: ColStart: 0
> -; OBJ64-NEXT: ColEnd: 0
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: +0x9 [
> ; OBJ64-NEXT: LineNumberStart: 6
> ; OBJ64-NEXT: LineNumberEndDelta: 0
> ; OBJ64-NEXT: IsStatement: Yes
> -; OBJ64-NEXT: ColStart: 0
> -; OBJ64-NEXT: ColEnd: 0
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: ]
>
> Modified: llvm/trunk/test/DebugInfo/COFF/multifile.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/multifile.ll?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/COFF/multifile.ll (original)
> +++ llvm/trunk/test/DebugInfo/COFF/multifile.ll Thu Jan 28 18:49:42 2016
> @@ -18,13 +18,15 @@
>
> ; X86-LABEL: _f:
> ; X86: # BB
> -; X86-NEXT: [[CALL_LINE_1:.*]]:{{$}}
> +; X86: .cv_file 1 "D:\\one.c"
> +; X86: .cv_loc 0 1 1 0 is_stmt 0 # one.c:1:0
> ; X86: calll _g
> -; X86-NEXT: [[CALL_LINE_2:.*]]:{{$}}
> +; X86: .cv_file 2 "D:\\two.c"
> +; X86: .cv_loc 0 2 2 0 # two.c:2:0
> ; X86: calll _g
> -; X86-NEXT: [[CALL_LINE_3:.*]]:{{$}}
> +; X86: .cv_loc 0 1 7 0 # one.c:7:0
> ; X86: calll _g
> -; X86-NEXT: [[RETURN_STMT:.*]]:
> +; X86: .cv_loc 0 1 8 0 # one.c:8:0
> ; X86: ret
> ; X86-NEXT: [[END_OF_F:.*]]:
> ;
> @@ -52,68 +54,15 @@
> ; Padding
> ; X86-NEXT: .zero 3
> ; Line table
> -; X86-NEXT: .long 242
> -; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X86-NEXT: [[F2_START]]:
> -; X86-NEXT: .secrel32 _f
> -; X86-NEXT: .secidx _f
> -; X86-NEXT: .short 1
> -; X86-NEXT: .long [[END_OF_F]]-_f
> -; Segment for file 'D:\\one.c' begins
> -; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X86-NEXT: .long 0
> -; X86-NEXT: .long 1
> -; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X86-NEXT: .long [[CALL_LINE_1]]-_f
> -; X86-NEXT: .long -2147483647
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: [[FILE_SEGMENT_END]]:
> -; Segment for file 'D:\\two.c' begins
> -; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X86-NEXT: .long 8
> -; X86-NEXT: .long 1
> -; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X86-NEXT: .long [[CALL_LINE_2]]-_f
> -; X86-NEXT: .long -2147483646
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: [[FILE_SEGMENT_END]]:
> -; A new segment for file 'D:\\one.c' begins
> -; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X86-NEXT: .long 0
> -; X86-NEXT: .long 2
> -; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X86-NEXT: .long [[CALL_LINE_3]]-_f
> -; X86-NEXT: .long -2147483641
> -; X86-NEXT: .long [[RETURN_STMT]]-_f
> -; X86-NEXT: .long -2147483640
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: [[FILE_SEGMENT_END]]:
> -; X86-NEXT: [[F2_END]]:
> +; X86-NEXT: .cv_linetable 0, _f, [[END_OF_F]]
> ; File index to string table offset subsection
> -; X86-NEXT: .long 244
> -; X86-NEXT: .long 16
> -; X86-NEXT: .long 1
> -; X86-NEXT: .long 0
> -; X86-NEXT: .long 10
> -; X86-NEXT: .long 0
> +; X86-NEXT: .cv_filechecksums
> ; String table
> -; X86-NEXT: .long 243
> -; X86-NEXT: .long 19
> -; X86-NEXT: .byte 0
> -; X86-NEXT: .ascii "D:\\one.c"
> -; X86-NEXT: .byte 0
> -; X86-NEXT: .ascii "D:\\two.c"
> -; X86-NEXT: .byte 0
> -; X86-NEXT: .zero 1
> +; X86-NEXT: .cv_stringtable
>
> ; OBJ32: Section {
> ; OBJ32: Name: .debug$S (2E 64 65 62 75 67 24 53)
> -; OBJ32: Characteristics [ (0x42100040)
> +; OBJ32: Characteristics [ (0x42300040)
> ; OBJ32: ]
> ; OBJ32: Relocations [
> ; OBJ32-NEXT: 0x2C IMAGE_REL_I386_SECREL _f
> @@ -133,7 +82,7 @@
> ; OBJ32-NEXT: ]
> ; OBJ32: FunctionLineTable [
> ; OBJ32-NEXT: Name: _f
> -; OBJ32-NEXT: Flags: 0x1
> +; OBJ32-NEXT: Flags: 0x0
> ; OBJ32-NEXT: CodeSize: 0x10
> ; OBJ32-NEXT: FilenameSegment [
> ; OBJ32-NEXT: Filename: D:\one.c
> @@ -141,8 +90,6 @@
> ; OBJ32-NEXT: LineNumberStart: 1
> ; OBJ32-NEXT: LineNumberEndDelta: 0
> ; OBJ32-NEXT: IsStatement: Yes
> -; OBJ32-NEXT: ColStart: 0
> -; OBJ32-NEXT: ColEnd: 0
> ; OBJ32-NEXT: ]
> ; OBJ32-NEXT: ]
> ; OBJ32-NEXT: FilenameSegment [
> @@ -151,8 +98,6 @@
> ; OBJ32-NEXT: LineNumberStart: 2
> ; OBJ32-NEXT: LineNumberEndDelta: 0
> ; OBJ32-NEXT: IsStatement: Yes
> -; OBJ32-NEXT: ColStart: 0
> -; OBJ32-NEXT: ColEnd: 0
> ; OBJ32-NEXT: ]
> ; OBJ32-NEXT: ]
> ; OBJ32-NEXT: FilenameSegment [
> @@ -161,31 +106,30 @@
> ; OBJ32-NEXT: LineNumberStart: 7
> ; OBJ32-NEXT: LineNumberEndDelta: 0
> ; OBJ32-NEXT: IsStatement: Yes
> -; OBJ32-NEXT: ColStart: 0
> -; OBJ32-NEXT: ColEnd: 0
> ; OBJ32-NEXT: ]
> ; OBJ32-NEXT: +0xF [
> ; OBJ32-NEXT: LineNumberStart: 8
> ; OBJ32-NEXT: LineNumberEndDelta: 0
> ; OBJ32-NEXT: IsStatement: Yes
> -; OBJ32-NEXT: ColStart: 0
> -; OBJ32-NEXT: ColEnd: 0
> ; OBJ32-NEXT: ]
> ; OBJ32-NEXT: ]
> ; OBJ32-NEXT: ]
>
> ; X64-LABEL: f:
> ; X64-NEXT: .L{{.*}}:{{$}}
> -; X64-NEXT: [[START:.*]]:{{$}}
> +; X64: .cv_file 1 "D:\\input.c"
> +; X64: .cv_loc 0 1 3 0 is_stmt 0 # input.c:3:0
> ; X64: # BB
> ; X64: subq $40, %rsp
> -; X64-NEXT: [[CALL_LINE_1:.*]]:{{$}}
> +; X64: .cv_file 2 "D:\\one.c"
> +; X64: .cv_loc 0 2 1 0 # one.c:1:0
> ; X64: callq g
> -; X64-NEXT: [[CALL_LINE_2:.*]]:{{$}}
> +; X64: .cv_file 3 "D:\\two.c"
> +; X64: .cv_loc 0 3 2 0 # two.c:2:0
> ; X64: callq g
> -; X64-NEXT: [[CALL_LINE_3:.*]]:{{$}}
> +; X64: .cv_loc 0 2 7 0 # one.c:7:0
> ; X64: callq g
> -; X64-NEXT: [[EPILOG_AND_RET:.*]]:
> +; X64: .cv_loc 0 2 8 0 # one.c:8:0
> ; X64: addq $40, %rsp
> ; X64-NEXT: ret
> ; X64-NEXT: [[END_OF_F:.*]]:
> @@ -213,83 +157,13 @@
> ; X64-NEXT: [[F1_END]]:
> ; Padding
> ; X64-NEXT: .zero 3
> -; Line table
> -; X64-NEXT: .long 242
> -; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X64-NEXT: [[F2_START]]:
> -; X64-NEXT: .secrel32 f
> -; X64-NEXT: .secidx f
> -; X64-NEXT: .short 1
> -; X64-NEXT: .long [[END_OF_F]]-f
> -; Segment for file 'D:\\input.c' begins
> -; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X64-NEXT: .long 0
> -; X64-NEXT: .long 1
> -; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X64-NEXT: .long [[START]]-f
> -; X64-NEXT: .long -2147483645
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: [[FILE_SEGMENT_END]]:
> -; Segment for file 'D:\\one.c' begins
> -; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X64-NEXT: .long 8
> -; X64-NEXT: .long 1
> -; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X64-NEXT: .long [[CALL_LINE_1]]-f
> -; X64-NEXT: .long -2147483647
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: [[FILE_SEGMENT_END]]:
> -; Segment for file 'D:\\two.c' begins
> -; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X64-NEXT: .long 16
> -; X64-NEXT: .long 1
> -; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X64-NEXT: .long [[CALL_LINE_2]]-f
> -; X64-NEXT: .long -2147483646
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: [[FILE_SEGMENT_END]]:
> -; A new segment for file 'D:\\one.c' begins
> -; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X64-NEXT: .long 8
> -; X64-NEXT: .long 2
> -; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X64-NEXT: .long [[CALL_LINE_3]]-f
> -; X64-NEXT: .long -2147483641
> -; X64-NEXT: .long [[EPILOG_AND_RET]]-f
> -; X64-NEXT: .long -2147483640
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: [[FILE_SEGMENT_END]]:
> -; X64-NEXT: [[F2_END]]:
> -; File index to string table offset subsection
> -; X64-NEXT: .long 244
> -; X64-NEXT: .long 24
> -; X64-NEXT: .long 1
> -; X64-NEXT: .long 0
> -; X64-NEXT: .long 12
> -; X64-NEXT: .long 0
> -; X64-NEXT: .long 21
> -; X64-NEXT: .long 0
> -; String table
> -; X64-NEXT: .long 243
> -; X64-NEXT: .long 30
> -; X64-NEXT: .byte 0
> -; X64-NEXT: .ascii "D:\\input.c"
> -; X64-NEXT: .byte 0
> -; X64-NEXT: .ascii "D:\\one.c"
> -; X64-NEXT: .byte 0
> -; X64-NEXT: .ascii "D:\\two.c"
> -; X64-NEXT: .byte 0
> -; X64-NEXT: .zero 2
> +; X64: .cv_linetable 0, f, [[END_OF_F]]
> +; X64: .cv_filechecksums
> +; X64: .cv_stringtable
>
> ; OBJ64: Section {
> ; OBJ64: Name: .debug$S (2E 64 65 62 75 67 24 53)
> -; OBJ64: Characteristics [ (0x42100040)
> +; OBJ64: Characteristics [ (0x42300040)
> ; OBJ64: ]
> ; OBJ64: Relocations [
> ; OBJ64-NEXT: 0x2C IMAGE_REL_AMD64_SECREL f
> @@ -309,7 +183,7 @@
> ; OBJ64-NEXT: ]
> ; OBJ64: FunctionLineTable [
> ; OBJ64-NEXT: Name: f
> -; OBJ64-NEXT: Flags: 0x1
> +; OBJ64-NEXT: Flags: 0x0
> ; OBJ64-NEXT: CodeSize: 0x18
> ; OBJ64-NEXT: FilenameSegment [
> ; OBJ64-NEXT: Filename: D:\input.c
> @@ -317,8 +191,6 @@
> ; OBJ64-NEXT: LineNumberStart: 3
> ; OBJ64-NEXT: LineNumberEndDelta: 0
> ; OBJ64-NEXT: IsStatement: Yes
> -; OBJ64-NEXT: ColStart: 0
> -; OBJ64-NEXT: ColEnd: 0
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: FilenameSegment [
> @@ -327,8 +199,6 @@
> ; OBJ64-NEXT: LineNumberStart: 1
> ; OBJ64-NEXT: LineNumberEndDelta: 0
> ; OBJ64-NEXT: IsStatement: Yes
> -; OBJ64-NEXT: ColStart: 0
> -; OBJ64-NEXT: ColEnd: 0
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: FilenameSegment [
> @@ -337,8 +207,6 @@
> ; OBJ64-NEXT: LineNumberStart: 2
> ; OBJ64-NEXT: LineNumberEndDelta: 0
> ; OBJ64-NEXT: IsStatement: Yes
> -; OBJ64-NEXT: ColStart: 0
> -; OBJ64-NEXT: ColEnd: 0
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: FilenameSegment [
> @@ -347,15 +215,11 @@
> ; OBJ64-NEXT: LineNumberStart: 7
> ; OBJ64-NEXT: LineNumberEndDelta: 0
> ; OBJ64-NEXT: IsStatement: Yes
> -; OBJ64-NEXT: ColStart: 0
> -; OBJ64-NEXT: ColEnd: 0
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: +0x13 [
> ; OBJ64-NEXT: LineNumberStart: 8
> ; OBJ64-NEXT: LineNumberEndDelta: 0
> ; OBJ64-NEXT: IsStatement: Yes
> -; OBJ64-NEXT: ColStart: 0
> -; OBJ64-NEXT: ColEnd: 0
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: ]
>
> Modified: llvm/trunk/test/DebugInfo/COFF/multifunction.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/multifunction.ll?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/COFF/multifunction.ll (original)
> +++ llvm/trunk/test/DebugInfo/COFF/multifunction.ll Thu Jan 28 18:49:42
> 2016
> @@ -24,29 +24,30 @@
>
> ; X86-LABEL: _x:
> ; X86: # BB
> -; X86-NEXT: [[X_CALL:.*]]:{{$}}
> +; X86: .cv_file 1 "D:\\source.c"
> +; X86: .cv_loc 0 1 4 42 is_stmt 0 # source.c:4:42
> ; X86: calll _z
> -; X86-NEXT: [[X_RETURN:.*]]:
> +; X86: .cv_loc 0 1 5 43 # source.c:5:43
> ; X86: ret
> ; X86-NEXT: [[END_OF_X:.*]]:
> ;
> ; X86-LABEL: _y:
> ; X86: # BB
> -; X86-NEXT: [[Y_CALL:.*]]:{{$}}
> +; X86: .cv_loc 1 1 8 52 # source.c:8:52
> ; X86: calll _z
> -; X86-NEXT: [[Y_RETURN:.*]]:
> +; X86: .cv_loc 1 1 9 53 # source.c:9:53
> ; X86: ret
> ; X86-NEXT: [[END_OF_Y:.*]]:
> ;
> ; X86-LABEL: _f:
> ; X86: # BB
> -; X86-NEXT: [[F_CALLS_X:.*]]:{{$}}
> +; X86: .cv_loc 2 1 12 62 # source.c:12:62
> ; X86: calll _x
> -; X86-NEXT: [[F_CALLS_Y:.*]]:
> +; X86: .cv_loc 2 1 13 63 # source.c:13:63
> ; X86: calll _y
> -; X86-NEXT: [[F_CALLS_Z:.*]]:
> +; X86: .cv_loc 2 1 14 72 # source.c:14:72
> ; X86: calll _z
> -; X86-NEXT: [[F_RETURN:.*]]:
> +; X86: .cv_loc 2 1 15 73 # source.c:15:73
> ; X86: ret
> ; X86-NEXT: [[END_OF_F:.*]]:
> ;
> @@ -74,27 +75,7 @@
> ; Padding
> ; X86-NEXT: .zero 3
> ; Line table subsection for x
> -; X86-NEXT: .long 242
> -; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X86-NEXT: [[F2_START]]:
> -; X86-NEXT: .secrel32 _x
> -; X86-NEXT: .secidx _x
> -; X86-NEXT: .short 1
> -; X86-NEXT: .long [[END_OF_X]]-_x
> -; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X86-NEXT: .long 0
> -; X86-NEXT: .long 2
> -; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X86-NEXT: .long [[X_CALL]]-_x
> -; X86-NEXT: .long -2147483644
> -; X86-NEXT: .long [[X_RETURN]]-_x
> -; X86-NEXT: .long -2147483643
> -; X86-NEXT: .short 42
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 43
> -; X86-NEXT: .short 0
> -; X86-NEXT: [[FILE_SEGMENT_END]]:
> -; X86-NEXT: [[F2_END]]:
> +; X86: .cv_linetable 0, _x, [[END_OF_X]]
> ; Symbol subsection for y
> ; X86-NEXT: .long 241
> ; X86-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
> @@ -117,27 +98,7 @@
> ; Padding
> ; X86-NEXT: .zero 3
> ; Line table subsection for y
> -; X86-NEXT: .long 242
> -; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X86-NEXT: [[F2_START]]:
> -; X86-NEXT: .secrel32 _y
> -; X86-NEXT: .secidx _y
> -; X86-NEXT: .short 1
> -; X86-NEXT: .long [[END_OF_Y]]-_y
> -; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X86-NEXT: .long 0
> -; X86-NEXT: .long 2
> -; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X86-NEXT: .long [[Y_CALL]]-_y
> -; X86-NEXT: .long -2147483640
> -; X86-NEXT: .long [[Y_RETURN]]-_y
> -; X86-NEXT: .long -2147483639
> -; X86-NEXT: .short 52
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 53
> -; X86-NEXT: .short 0
> -; X86-NEXT: [[FILE_SEGMENT_END]]:
> -; X86-NEXT: [[F2_END]]:
> +; X86: .cv_linetable 1, _y, [[END_OF_Y]]
> ; Symbol subsection for f
> ; X86-NEXT: .long 241
> ; X86-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
> @@ -160,51 +121,13 @@
> ; Padding
> ; X86-NEXT: .zero 3
> ; Line table subsection for f
> -; X86-NEXT: .long 242
> -; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X86-NEXT: [[F2_START]]:
> -; X86-NEXT: .secrel32 _f
> -; X86-NEXT: .secidx _f
> -; X86-NEXT: .short 1
> -; X86-NEXT: .long [[END_OF_F]]-_f
> -; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X86-NEXT: .long 0
> -; X86-NEXT: .long 4
> -; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X86-NEXT: .long [[F_CALLS_X]]-_f
> -; X86-NEXT: .long -2147483636
> -; X86-NEXT: .long [[F_CALLS_Y]]-_f
> -; X86-NEXT: .long -2147483635
> -; X86-NEXT: .long [[F_CALLS_Z]]-_f
> -; X86-NEXT: .long -2147483634
> -; X86-NEXT: .long [[F_RETURN]]-_f
> -; X86-NEXT: .long -2147483633
> -; X86-NEXT: .short 62
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 63
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 72
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 73
> -; X86-NEXT: .short 0
> -; X86-NEXT: [[FILE_SEGMENT_END]]:
> -; X86-NEXT: [[F2_END]]:
> -; File index to string table offset subsection
> -; X86-NEXT: .long 244
> -; X86-NEXT: .long 8
> -; X86-NEXT: .long 1
> -; X86-NEXT: .long 0
> -; String table
> -; X86-NEXT: .long 243
> -; X86-NEXT: .long 13
> -; X86-NEXT: .byte 0
> -; X86-NEXT: .ascii "D:\\source.c"
> -; X86-NEXT: .byte 0
> -; X86-NEXT: .zero 3
> +; X86: .cv_linetable 2, _f, [[END_OF_F]]
> +; X86: .cv_filechecksums
> +; X86: .cv_stringtable
>
> ; OBJ32: Section {
> ; OBJ32: Name: .debug$S (2E 64 65 62 75 67 24 53)
> -; OBJ32: Characteristics [ (0x42100040)
> +; OBJ32: Characteristics [ (0x42300040)
> ; OBJ32: ]
> ; OBJ32: Relocations [
> ; OBJ32-NEXT: 0x2C IMAGE_REL_I386_SECREL _x
> @@ -343,40 +266,41 @@
>
> ; X64-LABEL: x:
> ; X64-NEXT: .L{{.*}}:
> -; X64-NEXT: [[X_START:.*]]:{{$}}
> +; X64: .cv_file 1 "D:\\source.c"
> +; X64: .cv_loc 0 1 3 0 is_stmt 0 # source.c:3:0
> ; X64: # BB
> ; X64: subq $40, %rsp
> -; X64-NEXT: [[X_CALL_LINE:.*]]:{{$}}
> +; X64: .cv_loc 0 1 4 42 # source.c:4:42
> ; X64-NEXT: callq z
> -; X64-NEXT: [[X_EPILOG_AND_RET:.*]]:
> +; X64: .cv_loc 0 1 5 43 # source.c:5:43
> ; X64: addq $40, %rsp
> ; X64-NEXT: ret
> ; X64-NEXT: [[END_OF_X:.*]]:
> ;
> ; X64-LABEL: y:
> ; X64-NEXT: .L{{.*}}:
> -; X64-NEXT: [[Y_START:.*]]:{{$}}
> +; X64: .cv_loc 1 1 7 0 # source.c:7:0
> ; X64: # BB
> ; X64: subq $40, %rsp
> -; X64-NEXT: [[Y_CALL_LINE:.*]]:{{$}}
> +; X64: .cv_loc 1 1 8 52 # source.c:8:52
> ; X64-NEXT: callq z
> -; X64-NEXT: [[Y_EPILOG_AND_RET:.*]]:
> +; X64: .cv_loc 1 1 9 53 # source.c:9:53
> ; X64: addq $40, %rsp
> ; X64-NEXT: ret
> ; X64-NEXT: [[END_OF_Y:.*]]:
> ;
> ; X64-LABEL: f:
> ; X64-NEXT: .L{{.*}}:
> -; X64-NEXT: [[F_START:.*]]:{{$}}
> +; X64: .cv_loc 2 1 11 0 # source.c:11:0
> ; X64: # BB
> ; X64: subq $40, %rsp
> -; X64-NEXT: [[F_CALLS_X:.*]]:{{$}}
> +; X64: .cv_loc 2 1 12 62 # source.c:12:62
> ; X64-NEXT: callq x
> -; X64-NEXT: [[F_CALLS_Y:.*]]:
> +; X64: .cv_loc 2 1 13 63 # source.c:13:63
> ; X64: callq y
> -; X64-NEXT: [[F_CALLS_Z:.*]]:
> +; X64: .cv_loc 2 1 14 72 # source.c:14:72
> ; X64: callq z
> -; X64-NEXT: [[F_EPILOG_AND_RET:.*]]:
> +; X64: .cv_loc 2 1 15 73 # source.c:15:73
> ; X64: addq $40, %rsp
> ; X64-NEXT: ret
> ; X64-NEXT: [[END_OF_F:.*]]:
> @@ -405,31 +329,7 @@
> ; Padding
> ; X64-NEXT: .zero 3
> ; Line table subsection for x
> -; X64-NEXT: .long 242
> -; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X64-NEXT: [[F2_START]]:
> -; X64-NEXT: .secrel32 x
> -; X64-NEXT: .secidx x
> -; X64-NEXT: .short 1
> -; X64-NEXT: .long [[END_OF_X]]-x
> -; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X64-NEXT: .long 0
> -; X64-NEXT: .long 3
> -; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X64-NEXT: .long [[X_START]]-x
> -; X64-NEXT: .long -2147483645
> -; X64-NEXT: .long [[X_CALL_LINE]]-x
> -; X64-NEXT: .long -2147483644
> -; X64-NEXT: .long [[X_EPILOG_AND_RET]]-x
> -; X64-NEXT: .long -2147483643
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 42
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 43
> -; X64-NEXT: .short 0
> -; X64-NEXT: [[FILE_SEGMENT_END]]:
> -; X64-NEXT: [[F2_END]]:
> +; X64: .cv_linetable 0, x, [[END_OF_X]]
> ; Symbol subsection for y
> ; X64-NEXT: .long 241
> ; X64-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
> @@ -452,31 +352,7 @@
> ; Padding
> ; X64-NEXT: .zero 3
> ; Line table subsection for y
> -; X64-NEXT: .long 242
> -; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X64-NEXT: [[F2_START]]:
> -; X64-NEXT: .secrel32 y
> -; X64-NEXT: .secidx y
> -; X64-NEXT: .short 1
> -; X64-NEXT: .long [[END_OF_Y]]-y
> -; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X64-NEXT: .long 0
> -; X64-NEXT: .long 3
> -; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X64-NEXT: .long [[Y_START]]-y
> -; X64-NEXT: .long -2147483641
> -; X64-NEXT: .long [[Y_CALL_LINE]]-y
> -; X64-NEXT: .long -2147483640
> -; X64-NEXT: .long [[Y_EPILOG_AND_RET]]-y
> -; X64-NEXT: .long -2147483639
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 52
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 53
> -; X64-NEXT: .short 0
> -; X64-NEXT: [[FILE_SEGMENT_END]]:
> -; X64-NEXT: [[F2_END]]:
> +; X64: .cv_linetable 1, y, [[END_OF_Y]]
> ; Symbol subsection for f
> ; X64-NEXT: .long 241
> ; X64-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
> @@ -499,55 +375,15 @@
> ; Padding
> ; X64-NEXT: .zero 3
> ; Line table subsection for f
> -; X64-NEXT: .long 242
> -; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X64-NEXT: [[F2_START]]:
> -; X64-NEXT: .secrel32 f
> -; X64-NEXT: .secidx f
> -; X64-NEXT: .short 1
> -; X64-NEXT: .long [[END_OF_F]]-f
> -; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X64-NEXT: .long 0
> -; X64-NEXT: .long 5
> -; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X64-NEXT: .long [[F_START]]-f
> -; X64-NEXT: .long -2147483637
> -; X64-NEXT: .long [[F_CALLS_X]]-f
> -; X64-NEXT: .long -2147483636
> -; X64-NEXT: .long [[F_CALLS_Y]]-f
> -; X64-NEXT: .long -2147483635
> -; X64-NEXT: .long [[F_CALLS_Z]]-f
> -; X64-NEXT: .long -2147483634
> -; X64-NEXT: .long [[F_EPILOG_AND_RET]]-f
> -; X64-NEXT: .long -2147483633
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 62
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 63
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 72
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 73
> -; X64-NEXT: .short 0
> -; X64-NEXT: [[FILE_SEGMENT_END]]:
> -; X64-NEXT: [[F2_END]]:
> +; X64: .cv_linetable 2, f, [[END_OF_F]]
> ; File index to string table offset subsection
> -; X64-NEXT: .long 244
> -; X64-NEXT: .long 8
> -; X64-NEXT: .long 1
> -; X64-NEXT: .long 0
> +; X64: .cv_filechecksums
> ; String table
> -; X64-NEXT: .long 243
> -; X64-NEXT: .long 13
> -; X64-NEXT: .byte 0
> -; X64-NEXT: .ascii "D:\\source.c"
> -; X64-NEXT: .byte 0
> -; X64-NEXT: .zero 3
> +; X64: .cv_stringtable
>
> ; OBJ64: Section {
> ; OBJ64: Name: .debug$S (2E 64 65 62 75 67 24 53)
> -; OBJ64: Characteristics [ (0x42100040)
> +; OBJ64: Characteristics [ (0x42300040)
> ; OBJ64: ]
> ; OBJ64: Relocations [
> ; OBJ64-NEXT: 0x2C IMAGE_REL_AMD64_SECREL x
>
> Modified: llvm/trunk/test/DebugInfo/COFF/simple.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/simple.ll?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/COFF/simple.ll (original)
> +++ llvm/trunk/test/DebugInfo/COFF/simple.ll Thu Jan 28 18:49:42 2016
> @@ -13,9 +13,10 @@
>
> ; X86-LABEL: _f:
> ; X86: # BB
> -; X86-NEXT: [[CALL_LINE:^L.*]]:{{$}}
> +; X86: .cv_file 1 "D:\\test.c"
> +; X86: .cv_loc 0 1 4 2 is_stmt 0 # test.c:4:2
> ; X86: calll _g
> -; X86-NEXT: [[RETURN_STMT:.*]]:
> +; X86: .cv_loc 0 1 5 0 # test.c:5:0
> ; X86: ret
> ; X86-NEXT: [[END_OF_F:.*]]:
> ;
> @@ -43,44 +44,15 @@
> ; Padding
> ; X86-NEXT: .zero 3
> ; Line table
> -; X86-NEXT: .long 242
> -; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X86-NEXT: [[F2_START]]:
> -; X86-NEXT: .secrel32 _f
> -; X86-NEXT: .secidx _f
> -; X86-NEXT: .short 1
> -; X86-NEXT: .long [[END_OF_F]]-_f
> -; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X86-NEXT: .long 0
> -; X86-NEXT: .long 2
> -; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X86-NEXT: .long [[CALL_LINE]]-_f
> -; X86-NEXT: .long -2147483644
> -; X86-NEXT: .long [[RETURN_STMT]]-_f
> -; X86-NEXT: .long -2147483643
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: .short 0
> -; X86-NEXT: [[FILE_SEGMENT_END]]:
> -; X86-NEXT: [[F2_END]]:
> +; X86-NEXT: .cv_linetable 0, _f, [[END_OF_F]]
> ; File index to string table offset subsection
> -; X86-NEXT: .long 244
> -; X86-NEXT: .long 8
> -; X86-NEXT: .long 1
> -; X86-NEXT: .long 0
> +; X86-NEXT: .cv_filechecksums
> ; String table
> -; X86-NEXT: .long 243
> -; X86-NEXT: .long 11
> -; X86-NEXT: .byte 0
> -; X86-NEXT: .ascii "D:\\test.c"
> -; X86-NEXT: .byte 0
> -; Padding
> -; X86-NEXT: .zero 1
> +; X86-NEXT: .cv_stringtable
>
> ; OBJ32: Section {
> ; OBJ32: Name: .debug$S (2E 64 65 62 75 67 24 53)
> -; OBJ32: Characteristics [ (0x42100040)
> +; OBJ32: Characteristics [ (0x42300040)
> ; OBJ32: ]
> ; OBJ32: Relocations [
> ; OBJ32-NEXT: 0x2C IMAGE_REL_I386_SECREL _f
> @@ -108,7 +80,7 @@
> ; OBJ32-NEXT: LineNumberStart: 4
> ; OBJ32-NEXT: LineNumberEndDelta: 0
> ; OBJ32-NEXT: IsStatement: Yes
> -; OBJ32-NEXT: ColStart: 0
> +; OBJ32-NEXT: ColStart: 2
> ; OBJ32-NEXT: ColEnd: 0
> ; OBJ32-NEXT: ]
> ; OBJ32-NEXT: +0x5 [
> @@ -123,12 +95,13 @@
>
> ; X64-LABEL: f:
> ; X64-NEXT: .L{{.*}}:{{$}}
> -; X64-NEXT: [[START:.*]]:{{$}}
> +; X64: .cv_file 1 "D:\\test.c"
> +; X64: .cv_loc 0 1 3 0 is_stmt 0 # test.c:3:0
> ; X64: # BB
> ; X64: subq $40, %rsp
> -; X64-NEXT: [[CALL_LINE:.*]]:{{$}}
> +; X64: .cv_loc 0 1 4 2 # test.c:4:2
> ; X64-NEXT: callq g
> -; X64-NEXT: [[EPILOG_AND_RET:.*]]:
> +; X64: .cv_loc 0 1 5 0 # test.c:5:0
> ; X64: addq $40, %rsp
> ; X64-NEXT: ret
> ; X64-NEXT: [[END_OF_F:.*]]:
> @@ -157,48 +130,15 @@
> ; Padding
> ; X64-NEXT: .zero 3
> ; Line table
> -; X64-NEXT: .long 242
> -; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
> -; X64-NEXT: [[F2_START]]:
> -; X64-NEXT: .secrel32 f
> -; X64-NEXT: .secidx f
> -; X64-NEXT: .short 1
> -; X64-NEXT: .long [[END_OF_F]]-f
> -; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
> -; X64-NEXT: .long 0
> -; X64-NEXT: .long 3
> -; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
> -; X64-NEXT: .long [[START]]-f
> -; X64-NEXT: .long -2147483645
> -; X64-NEXT: .long [[CALL_LINE]]-f
> -; X64-NEXT: .long -2147483644
> -; X64-NEXT: .long [[EPILOG_AND_RET]]-f
> -; X64-NEXT: .long -2147483643
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: .short 0
> -; X64-NEXT: [[FILE_SEGMENT_END]]:
> -; X64-NEXT: [[F2_END]]:
> +; X64-NEXT: .cv_linetable 0, f, [[END_OF_F]]
> ; File index to string table offset subsection
> -; X64-NEXT: .long 244
> -; X64-NEXT: .long 8
> -; X64-NEXT: .long 1
> -; X64-NEXT: .long 0
> +; X64-NEXT: .cv_filechecksums
> ; String table
> -; X64-NEXT: .long 243
> -; X64-NEXT: .long 11
> -; X64-NEXT: .byte 0
> -; X64-NEXT: .ascii "D:\\test.c"
> -; X64-NEXT: .byte 0
> -; Padding
> -; X64-NEXT: .zero 1
> +; X64-NEXT: .cv_stringtable
>
> ; OBJ64: Section {
> ; OBJ64: Name: .debug$S (2E 64 65 62 75 67 24 53)
> -; OBJ64: Characteristics [ (0x42100040)
> +; OBJ64: Characteristics [ (0x42300040)
> ; OBJ64: ]
> ; OBJ64: Relocations [
> ; OBJ64-NEXT: 0x2C IMAGE_REL_AMD64_SECREL f
> @@ -233,7 +173,7 @@
> ; OBJ64-NEXT: LineNumberStart: 4
> ; OBJ64-NEXT: LineNumberEndDelta: 0
> ; OBJ64-NEXT: IsStatement: Yes
> -; OBJ64-NEXT: ColStart: 0
> +; OBJ64-NEXT: ColStart: 2
> ; OBJ64-NEXT: ColEnd: 0
> ; OBJ64-NEXT: ]
> ; OBJ64-NEXT: +0x9 [
> @@ -274,5 +214,5 @@ attributes #1 = { "less-precise-fpmad"="
> !9 = !{i32 2, !"CodeView", i32 1}
> !10 = !{i32 1, !"Debug Info Version", i32 3}
> !11 = !{!"clang version 3.5 "}
> -!12 = !DILocation(line: 4, scope: !4)
> +!12 = !DILocation(line: 4, column: 2, scope: !4)
> !13 = !DILocation(line: 5, scope: !4)
>
> Modified:
> llvm/trunk/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll
> (original)
> +++ llvm/trunk/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll Thu
> Jan 28 18:49:42 2016
> @@ -15,10 +15,10 @@
> ; The bar function happens to have no lexical scopes, yet it has one
> instruction
> ; with debug information available. This used to be PR19239.
>
> +; X86: .cv_file 1 "D:\\test.cpp"
> +
> ; X86-LABEL: {{^}}"?bar@@YAXHZZ":
> -; X86-NEXT: L{{.*}}:
> -; X86-NEXT: # BB
> -; X86-NEXT: [[JMP_LINE:^L.*]]:{{$}}
> +; X86: .cv_loc 1 1 4 0
> ; X86: jmp "?foo@@YAXXZ"
> ; X86-NEXT: [[END_OF_BAR:^L.*]]:{{$}}
> ; X86-NOT: ret
> @@ -26,13 +26,9 @@
> ; X86-LABEL: .section .debug$S,"dr"
> ; X86: .secrel32 "?bar@@YAXHZZ"
> ; X86-NEXT: .secidx "?bar@@YAXHZZ"
> -; X86: .long 0
> -; X86-NEXT: .long 1
> -; X86-NEXT: .long {{.*}}
> -; X86-NEXT: .long [[JMP_LINE]]-"?bar@@YAXHZZ"
> -; X86-NEXT: .long -2147483644
> -
> -; X86-LABEL: .long 244
> +; X86: .cv_linetable 1, "?bar@@YAXHZZ", [[END_OF_BAR]]
> +; X86: .cv_filechecksums
> +; X86: .cv_stringtable
>
> ; ModuleID = 'test.cpp'
> target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32"
>
> Added: llvm/trunk/test/MC/COFF/cv-loc.s
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-loc.s?rev=259130&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/MC/COFF/cv-loc.s (added)
> +++ llvm/trunk/test/MC/COFF/cv-loc.s Thu Jan 28 18:49:42 2016
> @@ -0,0 +1,85 @@
> +# RUN: llvm-mc < %s -triple=x86_64-pc-win32 -filetype=obj | llvm-readobj
> - -codeview | FileCheck %s
> +
> +.section .debug$S
> +.long 4
> +.cv_stringtable
> +
> +.cv_file 1 "a.c"
> +.cv_file 2 "t.inc"
> +
> +# Implements this C:
> +# void f(volatile int *x) {
> +# ++*x;
> +# #include "t.h" // contains two ++*x; statements
> +# ++*x;
> +# }
> +
> +.text
> +.def f;
> + .scl 2;
> + .type 32;
> + .endef
> + .text
> + .globl f
> + .align 16, 0x90
> +f:
> +.Lfunc_begin0:
> + .cv_loc 0 1 5 2
> + incl (%rdi)
> + # #include "t.h" start
> + .cv_loc 0 2 0 0
> + incl (%rdi)
> + .cv_loc 0 2 1 0
> + incl (%rdi)
> + # #include "t.h" end
> + .cv_loc 0 1 6 2
> + incl (%rdi)
> + retq
> +.Lfunc_end0:
> +
> +.section .debug$S
> +.cv_filechecksums
> +.cv_linetable 0, f, .Lfunc_end0
> +
> +# CHECK: FunctionLineTable [
> +# CHECK: LinkageName: f
> +# CHECK: Flags: 0x1
> +# CHECK: CodeSize: 0x9
> +# CHECK: FilenameSegment [
> +# CHECK: Filename: a.c (0x0)
> +# CHECK: +0x0 [
> +# CHECK: LineNumberStart: 5
> +# CHECK: LineNumberEndDelta: 0
> +# CHECK: IsStatement: Yes
> +# CHECK: ColStart: 2
> +# CHECK: ColEnd: 0
> +# CHECK: ]
> +# CHECK: ]
> +# CHECK: FilenameSegment [
> +# CHECK: Filename: t.inc (0x8)
> +# CHECK: +0x2 [
> +# CHECK: LineNumberStart: 0
> +# CHECK: LineNumberEndDelta: 0
> +# CHECK: IsStatement: Yes
> +# CHECK: ColStart: 0
> +# CHECK: ColEnd: 0
> +# CHECK: ]
> +# CHECK: +0x4 [
> +# CHECK: LineNumberStart: 1
> +# CHECK: LineNumberEndDelta: 0
> +# CHECK: IsStatement: Yes
> +# CHECK: ColStart: 0
> +# CHECK: ColEnd: 0
> +# CHECK: ]
> +# CHECK: ]
> +# CHECK: FilenameSegment [
> +# CHECK: Filename: a.c (0x0)
> +# CHECK: +0x6 [
> +# CHECK: LineNumberStart: 6
> +# CHECK: LineNumberEndDelta: 0
> +# CHECK: IsStatement: Yes
> +# CHECK: ColStart: 2
> +# CHECK: ColEnd: 0
> +# CHECK: ]
> +# CHECK: ]
> +# CHECK: ]
>
> Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
> +++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Thu Jan 28 18:49:42 2016
> @@ -1116,8 +1116,7 @@ void COFFDumper::printCodeViewSymbolSect
> uint32_t Offset = 6; // Skip relocations.
> uint16_t Flags = DE.getU16(&Offset);
> W.printHex("Flags", Flags);
> - bool HasColumnInformation =
> - Flags & COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS;
> + bool HasColumnInformation = Flags & codeview::LineFlags::HaveColumns;
> uint32_t FunctionSize = DE.getU32(&Offset);
> W.printHex("CodeSize", FunctionSize);
> while (DE.isValidOffset(Offset)) {
> @@ -1151,11 +1150,11 @@ void COFFDumper::printCodeViewSymbolSect
> char Buffer[32];
> format("+0x%X", PC).snprint(Buffer, 32);
> ListScope PCScope(W, Buffer);
> - uint32_t LineNumberStart = LineData & COFF::CVL_MaxLineNumber;
> + uint32_t LineNumberStart = LineData &
> codeview::LineInfo::StartLineMask;
> uint32_t LineNumberEndDelta =
> - (LineData >> COFF::CVL_LineNumberStartBits) &
> - COFF::CVL_LineNumberEndDeltaMask;
> - bool IsStatement = LineData & COFF::CVL_IsStatement;
> + (LineData & codeview::LineInfo::EndLineDeltaMask) >>
> + codeview::LineInfo::EndLineDeltaShift;
> + bool IsStatement = codeview::LineInfo::StatementFlag;
> W.printNumber("LineNumberStart", LineNumberStart);
> W.printNumber("LineNumberEndDelta", LineNumberEndDelta);
> W.printBoolean("IsStatement", IsStatement);
>
> Modified: llvm/trunk/unittests/MC/StringTableBuilderTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/MC/StringTableBuilderTest.cpp?rev=259130&r1=259129&r2=259130&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/MC/StringTableBuilderTest.cpp (original)
> +++ llvm/trunk/unittests/MC/StringTableBuilderTest.cpp Thu Jan 28 18:49:42
> 2016
> @@ -68,4 +68,27 @@ TEST(StringTableBuilderTest, BasicWinCOF
> EXPECT_EQ(23U, B.getOffset("river horse"));
> }
>
> +TEST(StringTableBuilderTest, ELFInOrder) {
> + StringTableBuilder B(StringTableBuilder::ELF);
> + EXPECT_EQ(1U, B.add("foo"));
> + EXPECT_EQ(5U, B.add("bar"));
> + EXPECT_EQ(9U, B.add("foobar"));
> +
> + B.finalizeInOrder();
> +
> + std::string Expected;
> + Expected += '\x00';
> + Expected += "foo";
> + Expected += '\x00';
> + Expected += "bar";
> + Expected += '\x00';
> + Expected += "foobar";
> + Expected += '\x00';
> +
> + EXPECT_EQ(Expected, B.data());
> + EXPECT_EQ(1U, B.getOffset("foo"));
> + EXPECT_EQ(5U, B.getOffset("bar"));
> + EXPECT_EQ(9U, B.getOffset("foobar"));
> +}
> +
> }
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160128/524cc22b/attachment-0001.html>
More information about the llvm-commits
mailing list