diff --git a/llvm/include/llvm/DebugInfo/CodeView/Line.h b/llvm/include/llvm/DebugInfo/CodeView/Line.h index 5defdf1b2def..0e7057fb5402 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/Line.h +++ b/llvm/include/llvm/DebugInfo/CodeView/Line.h @@ -21,26 +21,17 @@ using llvm::support::ulittle32_t; class LineInfo { public: - enum : uint32_t { - AlwaysStepIntoLineNumber = 0xfeefee, - NeverStepIntoLineNumber = 0xf00f00 - }; + static const uint32_t AlwaysStepIntoLineNumber = 0xfeefee; + static const uint32_t NeverStepIntoLineNumber = 0xf00f00; - enum : int { EndLineDeltaShift = 24 }; +private: + static const uint32_t StartLineMask = 0x00ffffff; + static const uint32_t EndLineDeltaMask = 0x7f000000; + static const int EndLineDeltaShift = 24; + static const uint32_t StatementFlag = 0x80000000u; - enum : uint32_t { - StartLineMask = 0x00ffffff, - EndLineDeltaMask = 0x7f000000, - StatementFlag = 0x80000000u - }; - - LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement) { - LineData = StartLine & StartLineMask; - uint32_t Delta = EndLine - StartLine; - LineData |= (Delta << EndLineDeltaShift) & EndLineDeltaShift; - if (IsStatement) - LineData |= StatementFlag; - } +public: + LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement); uint32_t getStartLine() const { return LineData & StartLineMask; } @@ -160,10 +151,6 @@ struct FileChecksum { // Checksum bytes follow. }; -enum LineFlags : uint32_t { - HaveColumns = 1, // CV_LINES_HAVE_COLUMNS -}; - } // namespace codeview } // namespace llvm diff --git a/llvm/include/llvm/MC/MCCodeView.h b/llvm/include/llvm/MC/MCCodeView.h deleted file mode 100644 index ed2f35a8f94c..000000000000 --- a/llvm/include/llvm/MC/MCCodeView.h +++ /dev/null @@ -1,162 +0,0 @@ -//===- 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 -#include - -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 getFilenames() { return Filenames; } - - /// \brief Add a line entry. - void addLineEntry(const MCCVLineEntry &LineEntry) { - MCCVLines[LineEntry.getFunctionId()].push_back(LineEntry); - } - - ArrayRef 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 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 Filenames; - - /// A collection of MCDwarfLineEntry for each section. - std::map> MCCVLines; -}; - -} // end namespace llvm -#endif diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index 608d15a27cf0..e5a9afd9968c 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -16,7 +16,6 @@ #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" @@ -43,7 +42,6 @@ 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. @@ -68,8 +66,6 @@ namespace llvm { /// The MCObjectFileInfo for this target. const MCObjectFileInfo *MOFI; - std::unique_ptr CVContext; - /// Allocator object used for creating machine code objects. /// /// We use a bump pointer allocator to avoid the need to track all allocated @@ -139,10 +135,6 @@ 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; @@ -245,8 +237,6 @@ namespace llvm { const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; } - CodeViewContext &getCVContext(); - void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; } void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; } @@ -515,35 +505,6 @@ 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; } diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index fe5575c50184..9fe2fda21353 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -59,6 +59,7 @@ public: void EmitFrames(MCAsmBackend *MAB); void EmitCFISections(bool EH, bool Debug) override; +protected: MCFragment *getCurrentFragment() const; void insert(MCFragment *F) { @@ -72,7 +73,6 @@ public: /// 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,13 +122,6 @@ 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, diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 1f4b24644ca8..04d143ffef66 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -640,27 +640,6 @@ 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. diff --git a/llvm/include/llvm/MC/StringTableBuilder.h b/llvm/include/llvm/MC/StringTableBuilder.h index bf3cea7f03f5..adde86b45583 100644 --- a/llvm/include/llvm/MC/StringTableBuilder.h +++ b/llvm/include/llvm/MC/StringTableBuilder.h @@ -27,8 +27,6 @@ private: size_t Size = 0; Kind K; - void finalizeStringTable(bool Optimize); - public: StringTableBuilder(Kind K); @@ -41,10 +39,6 @@ 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 { diff --git a/llvm/include/llvm/Support/COFF.h b/llvm/include/llvm/Support/COFF.h index 32bedbb2904b..bbd851ecfb54 100644 --- a/llvm/include/llvm/Support/COFF.h +++ b/llvm/include/llvm/Support/COFF.h @@ -656,7 +656,17 @@ 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, }; diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index b503f1dc31e4..f1716361a1dc 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -13,7 +13,6 @@ #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" @@ -75,18 +74,6 @@ StringRef CodeViewDebug::getFullFilepath(const DIFile *File) { 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. @@ -98,26 +85,15 @@ void CodeViewDebug::maybeRecordLocation(DebugLoc DL, return; // Skip this line if it is longer than the maximum we can record. - LineInfo LI(DL.getLine(), DL.getLine(), /*IsStatement=*/true); - if (LI.getStartLine() != DL.getLine() || LI.isAlwaysStepInto() || - LI.isNeverStepInto()) + if (DL.getLine() > COFF::CVL_MaxLineNumber) return; - ColumnInfo CI(DL.getCol(), /*EndColumn=*/0); - if (CI.getStartColumn() != DL.getCol()) - return; - - 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()); + + MCSymbol *MCL = Asm->MMI->getContext().createTempSymbol(); + Asm->OutStreamer->EmitLabel(MCL); + CurFn->Instrs.push_back(MCL); + LabelsAndLocs[MCL] = DL; } CodeViewDebug::CodeViewDebug(AsmPrinter *AP) @@ -152,17 +128,39 @@ void CodeViewDebug::endModule() { // of the payload followed by the payload itself. The subsections are 4-byte // aligned. - // Emit per-function debug information. - for (auto &P : FnDebugInfo) - emitDebugInfoForFunction(P.first, P.second); + // 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]); // This subsection holds a file index to offset in string table table. Asm->OutStreamer->AddComment("File index to string table offset subsection"); - Asm->OutStreamer->EmitCVFileChecksumsDirective(); + 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); + } // This subsection holds the string table. Asm->OutStreamer->AddComment("String table"); - Asm->OutStreamer->EmitCVStringTableDirective(); + 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); clear(); } @@ -179,13 +177,21 @@ static void EmitLabelDiff(MCStreamer &Streamer, Streamer.EmitValue(AddrDelta, Size); } -void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, - FunctionInfo &FI) { +static const DIFile *getFileFromLoc(DebugLoc DL) { + return DL.get()->getScope()->getFile(); +} + +void CodeViewDebug::emitDebugInfoForFunction(const Function *GV) { // 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(); @@ -232,8 +238,102 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, // Every subsection must be aligned to a 4-byte boundary. Asm->OutStreamer->EmitFill((-FuncName.size()) % 4, 0); - // We have an assembler directive that takes care of the whole line table. - Asm->OutStreamer->EmitCVLinetableDirective(FI.FuncId, Fn, FI.End); + // 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 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); } void CodeViewDebug::beginFunction(const MachineFunction *MF) { @@ -244,8 +344,8 @@ void CodeViewDebug::beginFunction(const MachineFunction *MF) { 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 @@ -284,9 +384,9 @@ void CodeViewDebug::endFunction(const MachineFunction *MF) { assert(FnDebugInfo.count(GV)); assert(CurFn == &FnDebugInfo[GV]); - // Don't emit anything if we don't have any line tables. - if (!CurFn->HaveLineInfo) { + if (CurFn->Instrs.empty()) { FnDebugInfo.erase(GV); + VisitedFunctions.pop_back(); } else { CurFn->End = Asm->getFunctionEnd(); } diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index 77b5ed39c1f8..4294b4fd6941 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -37,38 +37,72 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler { // to the end of the function. struct FunctionInfo { DebugLoc LastLoc; - MCSymbol *End = nullptr; - unsigned FuncId = 0; - unsigned LastFileId; - bool HaveLineInfo = false; + SmallVector Instrs; + MCSymbol *End; + FunctionInfo() : End(nullptr) {} }; FunctionInfo *CurFn; - unsigned NextFuncId = 0; + typedef DenseMap FnDebugInfoTy; + FnDebugInfoTy FnDebugInfo; + // Store the functions we've visited in a vector so we can maintain a stable + // order while emitting subsections. + SmallVector VisitedFunctions; - /// Remember some debug info about each function. Keep it in a stable order to - /// emit at the end of the TU. - MapVector FnDebugInfo; + DenseMap LabelsAndLocs; - /// Map from DIFile to .cv_file id. - DenseMap FileIdMap; + // 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 Filenames; + struct PerFileInfo { + size_t FilenameID, StartOffset; + }; + StringMap 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::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; typedef std::map 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); - FileIdMap.clear(); - FnDebugInfo.clear(); - FileToFilepathMap.clear(); + FileNameRegistry.clear(); + LabelsAndLocs.clear(); } - void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI); + void emitDebugInfoForFunction(const Function *GV); public: CodeViewDebug(AsmPrinter *Asm); diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt index a04f16c6ea7c..d1aac8104a31 100644 --- a/llvm/lib/MC/CMakeLists.txt +++ b/llvm/lib/MC/CMakeLists.txt @@ -10,7 +10,6 @@ add_llvm_library(LLVMMC MCAssembler.cpp MCCodeEmitter.cpp MCCodeGenInfo.cpp - MCCodeView.cpp MCContext.cpp MCDwarf.cpp MCELFObjectTargetWriter.cpp diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index d9382c5df9fb..2de36f8561cc 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -199,15 +199,6 @@ 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; @@ -963,69 +954,6 @@ MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) { 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"; diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp deleted file mode 100644 index 992edd0a8bc8..000000000000 --- a/llvm/lib/MC/MCCodeView.cpp +++ /dev/null @@ -1,222 +0,0 @@ -//===- 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 = ""; - - 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 &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 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); -} diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index c5243ef62c9c..b5ad518d0330 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -12,7 +12,6 @@ #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" @@ -91,8 +90,6 @@ void MCContext::reset() { DwarfCompileUnitID = 0; CurrentDwarfLoc = MCDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0); - CVContext.reset(); - MachOUniquingMap.clear(); ELFUniquingMap.clear(); COFFUniquingMap.clear(); @@ -477,20 +474,6 @@ void MCContext::finalizeDwarfSections(MCStreamer &MCOS) { [&](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 //===----------------------------------------------------------------------===// diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 71d578aca9d4..39755e5b0a8a 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -125,7 +125,6 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); - MCCVLineEntry::Make(this); MCDwarfLineEntry::Make(this, getCurrentSection().first); // Avoid fixups when possible. @@ -233,7 +232,6 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst, // 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. @@ -364,36 +362,7 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, 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()); diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 360de5db883d..b1814f8c8ff4 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -357,8 +357,6 @@ 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, @@ -396,13 +394,6 @@ 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(); @@ -1647,16 +1638,6 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, 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: @@ -3089,156 +3070,6 @@ 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(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() { @@ -4550,11 +4381,6 @@ void AsmParser::initializeDirectiveKindMap() { 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; diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index adae5d73ce54..836b40544642 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -180,22 +180,6 @@ 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) { } diff --git a/llvm/lib/MC/StringTableBuilder.cpp b/llvm/lib/MC/StringTableBuilder.cpp index f50e098e6e45..80e552287b3d 100644 --- a/llvm/lib/MC/StringTableBuilder.cpp +++ b/llvm/lib/MC/StringTableBuilder.cpp @@ -16,22 +16,7 @@ using namespace llvm; -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; - } -} +StringTableBuilder::StringTableBuilder(Kind K) : K(K) {} typedef std::pair StringPair; @@ -77,32 +62,13 @@ tailcall: } void StringTableBuilder::finalize() { - finalizeStringTable(/*Optimize=*/true); -} - -void StringTableBuilder::finalizeInOrder() { - finalizeStringTable(/*Optimize=*/false); -} - -void StringTableBuilder::finalizeStringTable(bool Optimize) { - typedef std::pair StringOffsetPair; - std::vector Strings; + std::vector *> Strings; Strings.reserve(StringIndexMap.size()); - for (StringOffsetPair &P : StringIndexMap) + for (std::pair &P : StringIndexMap) Strings.push_back(&P); - 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; - }); - } - } + if (!Strings.empty()) + multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0); switch (K) { case RAW: @@ -119,22 +85,17 @@ void StringTableBuilder::finalizeStringTable(bool Optimize) { } StringRef Previous; - for (StringOffsetPair *P : Strings) { + for (std::pair *P : Strings) { StringRef S = P->first; if (K == WinCOFF) assert(S.size() > COFF::NameSize && "Short string in COFF string table!"); - if (Optimize && Previous.endswith(S)) { + if (Previous.endswith(S)) { P->second = StringTable.size() - S.size() - (K != RAW); continue; } - if (Optimize) - P->second = StringTable.size(); - else - assert(P->second == StringTable.size() && - "different strtab offset after finalization"); - + P->second = StringTable.size(); StringTable += S; if (K != RAW) StringTable += '\x00'; diff --git a/llvm/test/DebugInfo/COFF/asm.ll b/llvm/test/DebugInfo/COFF/asm.ll index bb5937962381..e4daeda3394d 100644 --- a/llvm/test/DebugInfo/COFF/asm.ll +++ b/llvm/test/DebugInfo/COFF/asm.ll @@ -13,11 +13,11 @@ ; 6 } ; X86-LABEL: _f: -; 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: # BB +; X86-NEXT: [[ASM_LINE:^L.*]]:{{$}} +; X86: [[CALL_LINE:^L.*]]:{{$}} ; X86: calll _g -; X86: .cv_loc 0 1 6 0 +; X86-NEXT: [[RETURN_STMT:.*]]: ; X86: ret ; X86-NEXT: [[END_OF_F:^L.*]]: ; @@ -45,15 +45,48 @@ ; Padding ; X86-NEXT: .zero 3 ; Line table -; X86-NEXT: .cv_linetable 0, _f, [[END_OF_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 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]]: ; File index to string table offset subsection -; X86-NEXT: .cv_filechecksums +; X86-NEXT: .long 244 +; X86-NEXT: .long 8 +; X86-NEXT: .long 1 +; X86-NEXT: .long 0 ; String table -; X86-NEXT: .cv_stringtable +; 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 ; OBJ32: Section { ; OBJ32: Name: .debug$S (2E 64 65 62 75 67 24 53) -; OBJ32: Characteristics [ (0x42300040) +; OBJ32: Characteristics [ (0x42100040) ; OBJ32: ] ; OBJ32: Relocations [ ; OBJ32-NEXT: 0x2C IMAGE_REL_I386_SECREL _f @@ -74,7 +107,7 @@ ; OBJ32-NEXT: ] ; OBJ32: FunctionLineTable [ ; OBJ32-NEXT: Name: _f -; OBJ32-NEXT: Flags: 0x0 +; OBJ32-NEXT: Flags: 0x1 ; OBJ32-NEXT: CodeSize: 0x6 ; OBJ32-NEXT: FilenameSegment [ ; OBJ32-NEXT: Filename: D:\asm.c @@ -85,27 +118,34 @@ ; 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: .cv_file 1 "D:\\asm.c" -; X64: .cv_loc 0 1 3 0 is_stmt 0 +; X64-NEXT: .L{{.*}}:{{$}} +; X64-NEXT: [[START:.*]]:{{$}} +; X64: # BB ; X64: subq $40, %rsp -; X64: .cv_loc 0 1 4 0 -; X64: .cv_loc 0 1 5 0 +; X64-NEXT: [[ASM_LINE:.*]]:{{$}} +; X64: [[CALL_LINE:.*]]:{{$}} ; X64: callq g -; X64: .cv_loc 0 1 6 0 +; X64-NEXT: [[EPILOG_AND_RET:.*]]: ; X64: addq $40, %rsp ; X64-NEXT: ret ; X64-NEXT: [[END_OF_F:.*]]: @@ -134,15 +174,52 @@ ; Padding ; X64-NEXT: .zero 3 ; Line table -; X64-NEXT: .cv_linetable 0, f, [[END_OF_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 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]]: ; File index to string table offset subsection -; X64-NEXT: .cv_filechecksums +; X64-NEXT: .long 244 +; X64-NEXT: .long 8 +; X64-NEXT: .long 1 +; X64-NEXT: .long 0 ; String table -; X64-NEXT: .cv_stringtable +; 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 ; OBJ64: Section { ; OBJ64: Name: .debug$S (2E 64 65 62 75 67 24 53) -; OBJ64: Characteristics [ (0x42300040) +; OBJ64: Characteristics [ (0x42100040) ; OBJ64: ] ; OBJ64: Relocations [ ; OBJ64-NEXT: 0x2C IMAGE_REL_AMD64_SECREL f @@ -162,7 +239,7 @@ ; OBJ64-NEXT: ] ; OBJ64: FunctionLineTable [ ; OBJ64-NEXT: Name: f -; OBJ64-NEXT: Flags: 0x0 +; OBJ64-NEXT: Flags: 0x1 ; OBJ64-NEXT: CodeSize: 0xE ; OBJ64-NEXT: FilenameSegment [ ; OBJ64-NEXT: Filename: D:\asm.c @@ -172,21 +249,29 @@ ; 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: ] diff --git a/llvm/test/DebugInfo/COFF/multifile.ll b/llvm/test/DebugInfo/COFF/multifile.ll index 4de49881454a..6c52259aec71 100644 --- a/llvm/test/DebugInfo/COFF/multifile.ll +++ b/llvm/test/DebugInfo/COFF/multifile.ll @@ -18,15 +18,13 @@ ; X86-LABEL: _f: ; X86: # BB -; X86: .cv_file 1 "D:\\one.c" -; X86: .cv_loc 0 1 1 0 is_stmt 0 # one.c:1:0 +; X86-NEXT: [[CALL_LINE_1:.*]]:{{$}} ; X86: calll _g -; X86: .cv_file 2 "D:\\two.c" -; X86: .cv_loc 0 2 2 0 # two.c:2:0 +; X86-NEXT: [[CALL_LINE_2:.*]]:{{$}} ; X86: calll _g -; X86: .cv_loc 0 1 7 0 # one.c:7:0 +; X86-NEXT: [[CALL_LINE_3:.*]]:{{$}} ; X86: calll _g -; X86: .cv_loc 0 1 8 0 # one.c:8:0 +; X86-NEXT: [[RETURN_STMT:.*]]: ; X86: ret ; X86-NEXT: [[END_OF_F:.*]]: ; @@ -54,15 +52,68 @@ ; Padding ; X86-NEXT: .zero 3 ; Line table -; X86-NEXT: .cv_linetable 0, _f, [[END_OF_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 +; 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]]: ; File index to string table offset subsection -; X86-NEXT: .cv_filechecksums +; X86-NEXT: .long 244 +; X86-NEXT: .long 16 +; X86-NEXT: .long 1 +; X86-NEXT: .long 0 +; X86-NEXT: .long 10 +; X86-NEXT: .long 0 ; String table -; X86-NEXT: .cv_stringtable +; 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 ; OBJ32: Section { ; OBJ32: Name: .debug$S (2E 64 65 62 75 67 24 53) -; OBJ32: Characteristics [ (0x42300040) +; OBJ32: Characteristics [ (0x42100040) ; OBJ32: ] ; OBJ32: Relocations [ ; OBJ32-NEXT: 0x2C IMAGE_REL_I386_SECREL _f @@ -82,7 +133,7 @@ ; OBJ32-NEXT: ] ; OBJ32: FunctionLineTable [ ; OBJ32-NEXT: Name: _f -; OBJ32-NEXT: Flags: 0x0 +; OBJ32-NEXT: Flags: 0x1 ; OBJ32-NEXT: CodeSize: 0x10 ; OBJ32-NEXT: FilenameSegment [ ; OBJ32-NEXT: Filename: D:\one.c @@ -90,6 +141,8 @@ ; 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 [ @@ -98,6 +151,8 @@ ; 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 [ @@ -106,30 +161,31 @@ ; 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: .cv_file 1 "D:\\input.c" -; X64: .cv_loc 0 1 3 0 is_stmt 0 # input.c:3:0 +; X64-NEXT: [[START:.*]]:{{$}} ; X64: # BB ; X64: subq $40, %rsp -; X64: .cv_file 2 "D:\\one.c" -; X64: .cv_loc 0 2 1 0 # one.c:1:0 +; X64-NEXT: [[CALL_LINE_1:.*]]:{{$}} ; X64: callq g -; X64: .cv_file 3 "D:\\two.c" -; X64: .cv_loc 0 3 2 0 # two.c:2:0 +; X64-NEXT: [[CALL_LINE_2:.*]]:{{$}} ; X64: callq g -; X64: .cv_loc 0 2 7 0 # one.c:7:0 +; X64-NEXT: [[CALL_LINE_3:.*]]:{{$}} ; X64: callq g -; X64: .cv_loc 0 2 8 0 # one.c:8:0 +; X64-NEXT: [[EPILOG_AND_RET:.*]]: ; X64: addq $40, %rsp ; X64-NEXT: ret ; X64-NEXT: [[END_OF_F:.*]]: @@ -157,13 +213,83 @@ ; X64-NEXT: [[F1_END]]: ; Padding ; X64-NEXT: .zero 3 -; X64: .cv_linetable 0, f, [[END_OF_F]] -; X64: .cv_filechecksums -; X64: .cv_stringtable +; 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 ; OBJ64: Section { ; OBJ64: Name: .debug$S (2E 64 65 62 75 67 24 53) -; OBJ64: Characteristics [ (0x42300040) +; OBJ64: Characteristics [ (0x42100040) ; OBJ64: ] ; OBJ64: Relocations [ ; OBJ64-NEXT: 0x2C IMAGE_REL_AMD64_SECREL f @@ -183,7 +309,7 @@ ; OBJ64-NEXT: ] ; OBJ64: FunctionLineTable [ ; OBJ64-NEXT: Name: f -; OBJ64-NEXT: Flags: 0x0 +; OBJ64-NEXT: Flags: 0x1 ; OBJ64-NEXT: CodeSize: 0x18 ; OBJ64-NEXT: FilenameSegment [ ; OBJ64-NEXT: Filename: D:\input.c @@ -191,6 +317,8 @@ ; 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 [ @@ -199,6 +327,8 @@ ; 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 [ @@ -207,6 +337,8 @@ ; 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 [ @@ -215,11 +347,15 @@ ; 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: ] diff --git a/llvm/test/DebugInfo/COFF/multifunction.ll b/llvm/test/DebugInfo/COFF/multifunction.ll index 83ce9c77fe31..ff8b924bed3c 100644 --- a/llvm/test/DebugInfo/COFF/multifunction.ll +++ b/llvm/test/DebugInfo/COFF/multifunction.ll @@ -24,30 +24,29 @@ ; X86-LABEL: _x: ; X86: # BB -; X86: .cv_file 1 "D:\\source.c" -; X86: .cv_loc 0 1 4 42 is_stmt 0 # source.c:4:42 +; X86-NEXT: [[X_CALL:.*]]:{{$}} ; X86: calll _z -; X86: .cv_loc 0 1 5 43 # source.c:5:43 +; X86-NEXT: [[X_RETURN:.*]]: ; X86: ret ; X86-NEXT: [[END_OF_X:.*]]: ; ; X86-LABEL: _y: ; X86: # BB -; X86: .cv_loc 1 1 8 52 # source.c:8:52 +; X86-NEXT: [[Y_CALL:.*]]:{{$}} ; X86: calll _z -; X86: .cv_loc 1 1 9 53 # source.c:9:53 +; X86-NEXT: [[Y_RETURN:.*]]: ; X86: ret ; X86-NEXT: [[END_OF_Y:.*]]: ; ; X86-LABEL: _f: ; X86: # BB -; X86: .cv_loc 2 1 12 62 # source.c:12:62 +; X86-NEXT: [[F_CALLS_X:.*]]:{{$}} ; X86: calll _x -; X86: .cv_loc 2 1 13 63 # source.c:13:63 +; X86-NEXT: [[F_CALLS_Y:.*]]: ; X86: calll _y -; X86: .cv_loc 2 1 14 72 # source.c:14:72 +; X86-NEXT: [[F_CALLS_Z:.*]]: ; X86: calll _z -; X86: .cv_loc 2 1 15 73 # source.c:15:73 +; X86-NEXT: [[F_RETURN:.*]]: ; X86: ret ; X86-NEXT: [[END_OF_F:.*]]: ; @@ -75,7 +74,27 @@ ; Padding ; X86-NEXT: .zero 3 ; Line table subsection for x -; X86: .cv_linetable 0, _x, [[END_OF_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]]: ; Symbol subsection for y ; X86-NEXT: .long 241 ; X86-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]] @@ -98,7 +117,27 @@ ; Padding ; X86-NEXT: .zero 3 ; Line table subsection for y -; X86: .cv_linetable 1, _y, [[END_OF_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]]: ; Symbol subsection for f ; X86-NEXT: .long 241 ; X86-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]] @@ -121,13 +160,51 @@ ; Padding ; X86-NEXT: .zero 3 ; Line table subsection for f -; X86: .cv_linetable 2, _f, [[END_OF_F]] -; X86: .cv_filechecksums -; X86: .cv_stringtable +; 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 ; OBJ32: Section { ; OBJ32: Name: .debug$S (2E 64 65 62 75 67 24 53) -; OBJ32: Characteristics [ (0x42300040) +; OBJ32: Characteristics [ (0x42100040) ; OBJ32: ] ; OBJ32: Relocations [ ; OBJ32-NEXT: 0x2C IMAGE_REL_I386_SECREL _x @@ -266,41 +343,40 @@ ; X64-LABEL: x: ; X64-NEXT: .L{{.*}}: -; X64: .cv_file 1 "D:\\source.c" -; X64: .cv_loc 0 1 3 0 is_stmt 0 # source.c:3:0 +; X64-NEXT: [[X_START:.*]]:{{$}} ; X64: # BB ; X64: subq $40, %rsp -; X64: .cv_loc 0 1 4 42 # source.c:4:42 +; X64-NEXT: [[X_CALL_LINE:.*]]:{{$}} ; X64-NEXT: callq z -; X64: .cv_loc 0 1 5 43 # source.c:5:43 +; X64-NEXT: [[X_EPILOG_AND_RET:.*]]: ; X64: addq $40, %rsp ; X64-NEXT: ret ; X64-NEXT: [[END_OF_X:.*]]: ; ; X64-LABEL: y: ; X64-NEXT: .L{{.*}}: -; X64: .cv_loc 1 1 7 0 # source.c:7:0 +; X64-NEXT: [[Y_START:.*]]:{{$}} ; X64: # BB ; X64: subq $40, %rsp -; X64: .cv_loc 1 1 8 52 # source.c:8:52 +; X64-NEXT: [[Y_CALL_LINE:.*]]:{{$}} ; X64-NEXT: callq z -; X64: .cv_loc 1 1 9 53 # source.c:9:53 +; X64-NEXT: [[Y_EPILOG_AND_RET:.*]]: ; X64: addq $40, %rsp ; X64-NEXT: ret ; X64-NEXT: [[END_OF_Y:.*]]: ; ; X64-LABEL: f: ; X64-NEXT: .L{{.*}}: -; X64: .cv_loc 2 1 11 0 # source.c:11:0 +; X64-NEXT: [[F_START:.*]]:{{$}} ; X64: # BB ; X64: subq $40, %rsp -; X64: .cv_loc 2 1 12 62 # source.c:12:62 +; X64-NEXT: [[F_CALLS_X:.*]]:{{$}} ; X64-NEXT: callq x -; X64: .cv_loc 2 1 13 63 # source.c:13:63 +; X64-NEXT: [[F_CALLS_Y:.*]]: ; X64: callq y -; X64: .cv_loc 2 1 14 72 # source.c:14:72 +; X64-NEXT: [[F_CALLS_Z:.*]]: ; X64: callq z -; X64: .cv_loc 2 1 15 73 # source.c:15:73 +; X64-NEXT: [[F_EPILOG_AND_RET:.*]]: ; X64: addq $40, %rsp ; X64-NEXT: ret ; X64-NEXT: [[END_OF_F:.*]]: @@ -329,7 +405,31 @@ ; Padding ; X64-NEXT: .zero 3 ; Line table subsection for x -; X64: .cv_linetable 0, x, [[END_OF_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]]: ; Symbol subsection for y ; X64-NEXT: .long 241 ; X64-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]] @@ -352,7 +452,31 @@ ; Padding ; X64-NEXT: .zero 3 ; Line table subsection for y -; X64: .cv_linetable 1, y, [[END_OF_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]]: ; Symbol subsection for f ; X64-NEXT: .long 241 ; X64-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]] @@ -375,15 +499,55 @@ ; Padding ; X64-NEXT: .zero 3 ; Line table subsection for f -; X64: .cv_linetable 2, f, [[END_OF_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]]: ; File index to string table offset subsection -; X64: .cv_filechecksums +; X64-NEXT: .long 244 +; X64-NEXT: .long 8 +; X64-NEXT: .long 1 +; X64-NEXT: .long 0 ; String table -; X64: .cv_stringtable +; 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 ; OBJ64: Section { ; OBJ64: Name: .debug$S (2E 64 65 62 75 67 24 53) -; OBJ64: Characteristics [ (0x42300040) +; OBJ64: Characteristics [ (0x42100040) ; OBJ64: ] ; OBJ64: Relocations [ ; OBJ64-NEXT: 0x2C IMAGE_REL_AMD64_SECREL x diff --git a/llvm/test/DebugInfo/COFF/simple.ll b/llvm/test/DebugInfo/COFF/simple.ll index 7d31cca19e79..ee154359cf84 100644 --- a/llvm/test/DebugInfo/COFF/simple.ll +++ b/llvm/test/DebugInfo/COFF/simple.ll @@ -13,10 +13,9 @@ ; X86-LABEL: _f: ; X86: # BB -; X86: .cv_file 1 "D:\\test.c" -; X86: .cv_loc 0 1 4 2 is_stmt 0 # test.c:4:2 +; X86-NEXT: [[CALL_LINE:^L.*]]:{{$}} ; X86: calll _g -; X86: .cv_loc 0 1 5 0 # test.c:5:0 +; X86-NEXT: [[RETURN_STMT:.*]]: ; X86: ret ; X86-NEXT: [[END_OF_F:.*]]: ; @@ -44,15 +43,44 @@ ; Padding ; X86-NEXT: .zero 3 ; Line table -; X86-NEXT: .cv_linetable 0, _f, [[END_OF_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 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]]: ; File index to string table offset subsection -; X86-NEXT: .cv_filechecksums +; X86-NEXT: .long 244 +; X86-NEXT: .long 8 +; X86-NEXT: .long 1 +; X86-NEXT: .long 0 ; String table -; X86-NEXT: .cv_stringtable +; 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 ; OBJ32: Section { ; OBJ32: Name: .debug$S (2E 64 65 62 75 67 24 53) -; OBJ32: Characteristics [ (0x42300040) +; OBJ32: Characteristics [ (0x42100040) ; OBJ32: ] ; OBJ32: Relocations [ ; OBJ32-NEXT: 0x2C IMAGE_REL_I386_SECREL _f @@ -80,7 +108,7 @@ ; OBJ32-NEXT: LineNumberStart: 4 ; OBJ32-NEXT: LineNumberEndDelta: 0 ; OBJ32-NEXT: IsStatement: Yes -; OBJ32-NEXT: ColStart: 2 +; OBJ32-NEXT: ColStart: 0 ; OBJ32-NEXT: ColEnd: 0 ; OBJ32-NEXT: ] ; OBJ32-NEXT: +0x5 [ @@ -95,13 +123,12 @@ ; X64-LABEL: f: ; X64-NEXT: .L{{.*}}:{{$}} -; X64: .cv_file 1 "D:\\test.c" -; X64: .cv_loc 0 1 3 0 is_stmt 0 # test.c:3:0 +; X64-NEXT: [[START:.*]]:{{$}} ; X64: # BB ; X64: subq $40, %rsp -; X64: .cv_loc 0 1 4 2 # test.c:4:2 +; X64-NEXT: [[CALL_LINE:.*]]:{{$}} ; X64-NEXT: callq g -; X64: .cv_loc 0 1 5 0 # test.c:5:0 +; X64-NEXT: [[EPILOG_AND_RET:.*]]: ; X64: addq $40, %rsp ; X64-NEXT: ret ; X64-NEXT: [[END_OF_F:.*]]: @@ -130,15 +157,48 @@ ; Padding ; X64-NEXT: .zero 3 ; Line table -; X64-NEXT: .cv_linetable 0, f, [[END_OF_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 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]]: ; File index to string table offset subsection -; X64-NEXT: .cv_filechecksums +; X64-NEXT: .long 244 +; X64-NEXT: .long 8 +; X64-NEXT: .long 1 +; X64-NEXT: .long 0 ; String table -; X64-NEXT: .cv_stringtable +; 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 ; OBJ64: Section { ; OBJ64: Name: .debug$S (2E 64 65 62 75 67 24 53) -; OBJ64: Characteristics [ (0x42300040) +; OBJ64: Characteristics [ (0x42100040) ; OBJ64: ] ; OBJ64: Relocations [ ; OBJ64-NEXT: 0x2C IMAGE_REL_AMD64_SECREL f @@ -173,7 +233,7 @@ ; OBJ64-NEXT: LineNumberStart: 4 ; OBJ64-NEXT: LineNumberEndDelta: 0 ; OBJ64-NEXT: IsStatement: Yes -; OBJ64-NEXT: ColStart: 2 +; OBJ64-NEXT: ColStart: 0 ; OBJ64-NEXT: ColEnd: 0 ; OBJ64-NEXT: ] ; OBJ64-NEXT: +0x9 [ @@ -214,5 +274,5 @@ attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" " !9 = !{i32 2, !"CodeView", i32 1} !10 = !{i32 1, !"Debug Info Version", i32 3} !11 = !{!"clang version 3.5 "} -!12 = !DILocation(line: 4, column: 2, scope: !4) +!12 = !DILocation(line: 4, scope: !4) !13 = !DILocation(line: 5, scope: !4) diff --git a/llvm/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll b/llvm/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll index a231eccacc0d..a21c8bb0d973 100644 --- a/llvm/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll +++ b/llvm/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll @@ -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: .cv_loc 1 1 4 0 +; X86-NEXT: L{{.*}}: +; X86-NEXT: # BB +; X86-NEXT: [[JMP_LINE:^L.*]]:{{$}} ; X86: jmp "?foo@@YAXXZ" ; X86-NEXT: [[END_OF_BAR:^L.*]]:{{$}} ; X86-NOT: ret @@ -26,9 +26,13 @@ ; X86-LABEL: .section .debug$S,"dr" ; X86: .secrel32 "?bar@@YAXHZZ" ; X86-NEXT: .secidx "?bar@@YAXHZZ" -; X86: .cv_linetable 1, "?bar@@YAXHZZ", [[END_OF_BAR]] -; X86: .cv_filechecksums -; X86: .cv_stringtable +; 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 ; ModuleID = 'test.cpp' target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32" diff --git a/llvm/test/MC/COFF/cv-loc.s b/llvm/test/MC/COFF/cv-loc.s deleted file mode 100644 index 7cd845ebb372..000000000000 --- a/llvm/test/MC/COFF/cv-loc.s +++ /dev/null @@ -1,85 +0,0 @@ -# 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: ] diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp index a2f3e917e20b..0ac882866a7e 100644 --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -1116,7 +1116,8 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, uint32_t Offset = 6; // Skip relocations. uint16_t Flags = DE.getU16(&Offset); W.printHex("Flags", Flags); - bool HasColumnInformation = Flags & codeview::LineFlags::HaveColumns; + bool HasColumnInformation = + Flags & COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS; uint32_t FunctionSize = DE.getU32(&Offset); W.printHex("CodeSize", FunctionSize); while (DE.isValidOffset(Offset)) { @@ -1150,11 +1151,11 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, char Buffer[32]; format("+0x%X", PC).snprint(Buffer, 32); ListScope PCScope(W, Buffer); - uint32_t LineNumberStart = LineData & codeview::LineInfo::StartLineMask; + uint32_t LineNumberStart = LineData & COFF::CVL_MaxLineNumber; uint32_t LineNumberEndDelta = - (LineData & codeview::LineInfo::EndLineDeltaMask) >> - codeview::LineInfo::EndLineDeltaShift; - bool IsStatement = codeview::LineInfo::StatementFlag; + (LineData >> COFF::CVL_LineNumberStartBits) & + COFF::CVL_LineNumberEndDeltaMask; + bool IsStatement = LineData & COFF::CVL_IsStatement; W.printNumber("LineNumberStart", LineNumberStart); W.printNumber("LineNumberEndDelta", LineNumberEndDelta); W.printBoolean("IsStatement", IsStatement); diff --git a/llvm/unittests/MC/StringTableBuilderTest.cpp b/llvm/unittests/MC/StringTableBuilderTest.cpp index f78d3588ffff..4cc0bda0a03a 100644 --- a/llvm/unittests/MC/StringTableBuilderTest.cpp +++ b/llvm/unittests/MC/StringTableBuilderTest.cpp @@ -68,27 +68,4 @@ TEST(StringTableBuilderTest, BasicWinCOFF) { 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")); -} - }