This reverts commit r259117.
The LineInfo constructor is defined in the codeview library and we have
to link against it now. Doing that isn't trivial, so reverting for now.
llvm-svn: 259126
class LineInfo {
public:
- enum : uint32_t {
- AlwaysStepIntoLineNumber = 0xfeefee,
- NeverStepIntoLineNumber = 0xf00f00
- };
-
- enum : int { EndLineDeltaShift = 24 };
-
- 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;
- }
+ static const uint32_t AlwaysStepIntoLineNumber = 0xfeefee;
+ static const uint32_t NeverStepIntoLineNumber = 0xf00f00;
+
+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; }
// Checksum bytes follow.
};
-enum LineFlags : uint32_t {
- HaveColumns = 1, // CV_LINES_HAVE_COLUMNS
-};
-
} // namespace codeview
} // namespace llvm
+++ /dev/null
-//===- 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
#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"
class MCSectionMachO;
class MCSectionELF;
class MCSectionCOFF;
- class CodeViewContext;
/// Context object for machine code objects. This class owns all of the
/// sections that it creates.
/// 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
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;
const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; }
- CodeViewContext &getCVContext();
-
void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; }
void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; }
/// @}
-
- /// \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; }
void EmitFrames(MCAsmBackend *MAB);
void EmitCFISections(bool EH, bool Debug) override;
+protected:
MCFragment *getCurrentFragment() const;
void insert(MCFragment *F) {
/// 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
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,
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.
size_t Size = 0;
Kind K;
- void finalizeStringTable(bool Optimize);
-
public:
StringTableBuilder(Kind K);
/// 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 {
}
};
+ 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,
};
#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"
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.
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)
// 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();
}
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();
// 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<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);
}
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
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();
}
// to the end of the function.
struct FunctionInfo {
DebugLoc LastLoc;
- MCSymbol *End = nullptr;
- unsigned FuncId = 0;
- unsigned LastFileId;
- bool HaveLineInfo = false;
+ SmallVector<MCSymbol *, 10> Instrs;
+ MCSymbol *End;
+ FunctionInfo() : End(nullptr) {}
};
FunctionInfo *CurFn;
- 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 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;
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);
- 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);
MCAssembler.cpp
MCCodeEmitter.cpp
MCCodeGenInfo.cpp
- MCCodeView.cpp
MCContext.cpp
MCDwarf.cpp
MCELFObjectTargetWriter.cpp
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;
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";
+++ /dev/null
-//===- 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);
-}
#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"
DwarfCompileUnitID = 0;
CurrentDwarfLoc = MCDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0);
- CVContext.reset();
-
MachOUniquingMap.clear();
ELFUniquingMap.clear();
COFFUniquingMap.clear();
[&](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
//===----------------------------------------------------------------------===//
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
- MCCVLineEntry::Make(this);
MCDwarfLineEntry::Make(this, getCurrentSection().first);
// Avoid fixups when possible.
// 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.
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());
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,
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();
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:
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() {
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;
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) {
}
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<StringRef, size_t> StringPair;
}
void StringTableBuilder::finalize() {
- 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;
+ std::vector<std::pair<StringRef, size_t> *> Strings;
Strings.reserve(StringIndexMap.size());
- for (StringOffsetPair &P : StringIndexMap)
+ for (std::pair<StringRef, size_t> &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:
}
StringRef Previous;
- for (StringOffsetPair *P : Strings) {
+ for (std::pair<StringRef, size_t> *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';
; 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.*]]:
;
; 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
; 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
; 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:.*]]:
; 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
; 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
; 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: ]
; 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:.*]]:
;
; 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
; 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
; 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 [
; 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 [
; 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:.*]]:
; 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
; 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
; 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 [
; 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 [
; 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 [
; 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: ]
; 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:.*]]:
;
; 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:.*]]
; 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:.*]]
; 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
; 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:.*]]:
; 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:.*]]
; 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:.*]]
; 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
; 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:.*]]:
;
; 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
; 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 [
; 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:.*]]:
; 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
; 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 [
!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)
; 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
; 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"
+++ /dev/null
-# 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: ]
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)) {
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);
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"));
-}
-
}