summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/AsmPrinter
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-01-29 00:49:42 +0000
committerReid Kleckner <rnk@google.com>2016-01-29 00:49:42 +0000
commit2214ed8937a05b9457b167a84d6732a448fad27f (patch)
tree8418d7840e286b16568c7f6c3301757fbd92771e /llvm/lib/CodeGen/AsmPrinter
parent0407108020ed12d8c34582d847d2c37cd68d1d0b (diff)
downloadbcm5719-llvm-2214ed8937a05b9457b167a84d6732a448fad27f.tar.gz
bcm5719-llvm-2214ed8937a05b9457b167a84d6732a448fad27f.zip
Reland "[CodeView] Use assembler directives for line tables"
This reverts commit r259126 and relands r259117. This time with updated library dependencies. llvm-svn: 259130
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp184
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h70
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/LLVMBuild.txt2
3 files changed, 61 insertions, 195 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index f1716361a1d..b503f1dc31e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -13,6 +13,7 @@
#include "CodeViewDebug.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSymbol.h"
@@ -74,6 +75,18 @@ StringRef CodeViewDebug::getFullFilepath(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.
@@ -85,15 +98,26 @@ void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
return;
// Skip this line if it is longer than the maximum we can record.
- if (DL.getLine() > COFF::CVL_MaxLineNumber)
+ LineInfo LI(DL.getLine(), DL.getLine(), /*IsStatement=*/true);
+ if (LI.getStartLine() != DL.getLine() || LI.isAlwaysStepInto() ||
+ LI.isNeverStepInto())
return;
- CurFn->LastLoc = DL;
+ ColumnInfo CI(DL.getCol(), /*EndColumn=*/0);
+ if (CI.getStartColumn() != DL.getCol())
+ return;
- MCSymbol *MCL = Asm->MMI->getContext().createTempSymbol();
- Asm->OutStreamer->EmitLabel(MCL);
- CurFn->Instrs.push_back(MCL);
- LabelsAndLocs[MCL] = DL;
+ if (!CurFn->HaveLineInfo)
+ CurFn->HaveLineInfo = true;
+ unsigned FileId = 0;
+ if (CurFn->LastLoc.get() && CurFn->LastLoc->getFile() == DL->getFile())
+ FileId = CurFn->LastFileId;
+ else
+ FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile());
+ CurFn->LastLoc = DL;
+ Asm->OutStreamer->EmitCVLocDirective(CurFn->FuncId, FileId, DL.getLine(),
+ DL.getCol(), /*PrologueEnd=*/false,
+ /*IsStmt=*/false, DL->getFilename());
}
CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
@@ -128,39 +152,17 @@ void CodeViewDebug::endModule() {
// of the payload followed by the payload itself. The subsections are 4-byte
// aligned.
- // Emit per-function debug information. This code is extracted into a
- // separate function for readability.
- for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I)
- emitDebugInfoForFunction(VisitedFunctions[I]);
+ // Emit per-function debug information.
+ for (auto &P : FnDebugInfo)
+ emitDebugInfoForFunction(P.first, P.second);
// This subsection holds a file index to offset in string table table.
Asm->OutStreamer->AddComment("File index to string table offset subsection");
- Asm->EmitInt32(unsigned(ModuleSubstreamKind::FileChecksums));
- size_t NumFilenames = FileNameRegistry.Infos.size();
- Asm->EmitInt32(8 * NumFilenames);
- for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
- StringRef Filename = FileNameRegistry.Filenames[I];
- // For each unique filename, just write its offset in the string table.
- Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset);
- // The function name offset is not followed by any additional data.
- Asm->EmitInt32(0);
- }
+ Asm->OutStreamer->EmitCVFileChecksumsDirective();
// This subsection holds the string table.
Asm->OutStreamer->AddComment("String table");
- Asm->EmitInt32(unsigned(ModuleSubstreamKind::StringTable));
- Asm->EmitInt32(FileNameRegistry.LastOffset);
- // The payload starts with a null character.
- Asm->EmitInt8(0);
-
- for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
- // Just emit unique filenames one by one, separated by a null character.
- Asm->OutStreamer->EmitBytes(FileNameRegistry.Filenames[I]);
- Asm->EmitInt8(0);
- }
-
- // No more subsections. Fill with zeros to align the end of the section by 4.
- Asm->OutStreamer->EmitFill((-FileNameRegistry.LastOffset) % 4, 0);
+ Asm->OutStreamer->EmitCVStringTableDirective();
clear();
}
@@ -177,21 +179,13 @@ static void EmitLabelDiff(MCStreamer &Streamer,
Streamer.EmitValue(AddrDelta, Size);
}
-static const DIFile *getFileFromLoc(DebugLoc DL) {
- return DL.get()->getScope()->getFile();
-}
-
-void CodeViewDebug::emitDebugInfoForFunction(const Function *GV) {
+void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
+ FunctionInfo &FI) {
// For each function there is a separate subsection
// which holds the PC to file:line table.
const MCSymbol *Fn = Asm->getSymbol(GV);
assert(Fn);
- const FunctionInfo &FI = FnDebugInfo[GV];
- if (FI.Instrs.empty())
- return;
- assert(FI.End && "Don't know where the function ends?");
-
StringRef FuncName;
if (auto *SP = getDISubprogram(GV))
FuncName = SP->getDisplayName();
@@ -238,102 +232,8 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV) {
// Every subsection must be aligned to a 4-byte boundary.
Asm->OutStreamer->EmitFill((-FuncName.size()) % 4, 0);
- // PCs/Instructions are grouped into segments sharing the same filename.
- // Pre-calculate the lengths (in instructions) of these segments and store
- // them in a map for convenience. Each index in the map is the sequential
- // number of the respective instruction that starts a new segment.
- DenseMap<size_t, size_t> FilenameSegmentLengths;
- size_t LastSegmentEnd = 0;
- const DIFile *PrevFile = getFileFromLoc(LabelsAndLocs[FI.Instrs[0]]);
- for (size_t J = 1, F = FI.Instrs.size(); J != F; ++J) {
- const DIFile *CurFile = getFileFromLoc(LabelsAndLocs[FI.Instrs[J]]);
- if (PrevFile == CurFile)
- continue;
- FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd;
- LastSegmentEnd = J;
- PrevFile = CurFile;
- }
- FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd;
-
- // Emit a line table subsection, required to do PC-to-file:line lookup.
- Asm->OutStreamer->AddComment("Line table subsection for " + Twine(FuncName));
- Asm->EmitInt32(unsigned(ModuleSubstreamKind::Lines));
- MCSymbol *LineTableBegin = Asm->MMI->getContext().createTempSymbol(),
- *LineTableEnd = Asm->MMI->getContext().createTempSymbol();
- EmitLabelDiff(*Asm->OutStreamer, LineTableBegin, LineTableEnd);
- Asm->OutStreamer->EmitLabel(LineTableBegin);
-
- // Identify the function this subsection is for.
- Asm->OutStreamer->EmitCOFFSecRel32(Fn);
- Asm->OutStreamer->EmitCOFFSectionIndex(Fn);
- // Insert flags after a 16-bit section index.
- Asm->EmitInt16(COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS);
-
- // Length of the function's code, in bytes.
- EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End);
-
- // PC-to-linenumber lookup table:
- MCSymbol *FileSegmentEnd = nullptr;
-
- // The start of the last segment:
- size_t LastSegmentStart = 0;
-
- auto FinishPreviousChunk = [&] {
- if (!FileSegmentEnd)
- return;
- for (size_t ColSegI = LastSegmentStart,
- ColSegEnd = ColSegI + FilenameSegmentLengths[LastSegmentStart];
- ColSegI != ColSegEnd; ++ColSegI) {
- unsigned ColumnNumber = LabelsAndLocs[FI.Instrs[ColSegI]].getCol();
- // Truncate the column number if it is longer than the maximum we can
- // record.
- if (ColumnNumber > COFF::CVL_MaxColumnNumber)
- ColumnNumber = 0;
- Asm->EmitInt16(ColumnNumber); // Start column
- Asm->EmitInt16(0); // End column
- }
- Asm->OutStreamer->EmitLabel(FileSegmentEnd);
- };
-
- for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) {
- MCSymbol *Instr = FI.Instrs[J];
- assert(LabelsAndLocs.count(Instr));
-
- if (FilenameSegmentLengths.count(J)) {
- // We came to a beginning of a new filename segment.
- FinishPreviousChunk();
- const DIFile *File = getFileFromLoc(LabelsAndLocs[FI.Instrs[J]]);
- StringRef CurFilename = getFullFilepath(File);
- size_t IndexInFileTable = FileNameRegistry.add(CurFilename);
- // Each segment starts with the offset of the filename
- // in the string table.
- Asm->OutStreamer->AddComment(
- "Segment for file '" + Twine(CurFilename) + "' begins");
- MCSymbol *FileSegmentBegin = Asm->MMI->getContext().createTempSymbol();
- Asm->OutStreamer->EmitLabel(FileSegmentBegin);
- Asm->EmitInt32(8 * IndexInFileTable);
-
- // Number of PC records in the lookup table.
- size_t SegmentLength = FilenameSegmentLengths[J];
- Asm->EmitInt32(SegmentLength);
-
- // Full size of the segment for this filename, including the prev two
- // records.
- FileSegmentEnd = Asm->MMI->getContext().createTempSymbol();
- EmitLabelDiff(*Asm->OutStreamer, FileSegmentBegin, FileSegmentEnd);
- LastSegmentStart = J;
- }
-
- // The first PC with the given linenumber and the linenumber itself.
- EmitLabelDiff(*Asm->OutStreamer, Fn, Instr);
- uint32_t LineNumber = LabelsAndLocs[Instr].getLine();
- assert(LineNumber <= COFF::CVL_MaxLineNumber);
- uint32_t LineData = LineNumber | COFF::CVL_IsStatement;
- Asm->EmitInt32(LineData);
- }
-
- FinishPreviousChunk();
- Asm->OutStreamer->EmitLabel(LineTableEnd);
+ // We have an assembler directive that takes care of the whole line table.
+ Asm->OutStreamer->EmitCVLinetableDirective(FI.FuncId, Fn, FI.End);
}
void CodeViewDebug::beginFunction(const MachineFunction *MF) {
@@ -344,8 +244,8 @@ void CodeViewDebug::beginFunction(const 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
@@ -384,9 +284,9 @@ void CodeViewDebug::endFunction(const MachineFunction *MF) {
assert(FnDebugInfo.count(GV));
assert(CurFn == &FnDebugInfo[GV]);
- if (CurFn->Instrs.empty()) {
+ // Don't emit anything if we don't have any line tables.
+ if (!CurFn->HaveLineInfo) {
FnDebugInfo.erase(GV);
- VisitedFunctions.pop_back();
} else {
CurFn->End = Asm->getFunctionEnd();
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 4294b4fd694..77b5ed39c1f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -37,72 +37,38 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler {
// to the end of the function.
struct FunctionInfo {
DebugLoc LastLoc;
- SmallVector<MCSymbol *, 10> Instrs;
- MCSymbol *End;
- FunctionInfo() : End(nullptr) {}
+ MCSymbol *End = nullptr;
+ unsigned FuncId = 0;
+ unsigned LastFileId;
+ bool HaveLineInfo = false;
};
FunctionInfo *CurFn;
- typedef DenseMap<const Function *, FunctionInfo> FnDebugInfoTy;
- FnDebugInfoTy FnDebugInfo;
- // Store the functions we've visited in a vector so we can maintain a stable
- // order while emitting subsections.
- SmallVector<const Function *, 10> VisitedFunctions;
-
- DenseMap<MCSymbol *, DebugLoc> LabelsAndLocs;
-
- // FileNameRegistry - Manages filenames observed while generating debug info
- // by filtering out duplicates and bookkeeping the offsets in the string
- // table to be generated.
- struct FileNameRegistryTy {
- SmallVector<StringRef, 10> Filenames;
- struct PerFileInfo {
- size_t FilenameID, StartOffset;
- };
- StringMap<PerFileInfo> Infos;
-
- // The offset in the string table where we'll write the next unique
- // filename.
- size_t LastOffset;
-
- FileNameRegistryTy() {
- clear();
- }
-
- // Add Filename to the registry, if it was not observed before.
- size_t add(StringRef Filename) {
- size_t OldSize = Infos.size();
- bool Inserted;
- StringMap<PerFileInfo>::iterator It;
- std::tie(It, Inserted) = Infos.insert(
- std::make_pair(Filename, PerFileInfo{OldSize, LastOffset}));
- if (Inserted) {
- LastOffset += Filename.size() + 1;
- Filenames.push_back(Filename);
- }
- return It->second.FilenameID;
- }
-
- void clear() {
- LastOffset = 1;
- Infos.clear();
- Filenames.clear();
- }
- } FileNameRegistry;
+ unsigned NextFuncId = 0;
+
+ /// Remember some debug info about each function. Keep it in a stable order to
+ /// emit at the end of the TU.
+ MapVector<const Function *, FunctionInfo> FnDebugInfo;
+
+ /// Map from DIFile to .cv_file id.
+ DenseMap<const DIFile *, unsigned> FileIdMap;
typedef std::map<const DIFile *, std::string> FileToFilepathMapTy;
FileToFilepathMapTy FileToFilepathMap;
StringRef getFullFilepath(const DIFile *S);
+ unsigned maybeRecordFile(const DIFile *F);
+
void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF);
void clear() {
assert(CurFn == nullptr);
- FileNameRegistry.clear();
- LabelsAndLocs.clear();
+ FileIdMap.clear();
+ FnDebugInfo.clear();
+ FileToFilepathMap.clear();
}
- void emitDebugInfoForFunction(const Function *GV);
+ void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
public:
CodeViewDebug(AsmPrinter *Asm);
diff --git a/llvm/lib/CodeGen/AsmPrinter/LLVMBuild.txt b/llvm/lib/CodeGen/AsmPrinter/LLVMBuild.txt
index bbdb0c7fc3c..e741a1a4c4e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/LLVMBuild.txt
+++ b/llvm/lib/CodeGen/AsmPrinter/LLVMBuild.txt
@@ -19,4 +19,4 @@
type = Library
name = AsmPrinter
parent = Libraries
-required_libraries = Analysis CodeGen Core MC MCParser Support Target TransformUtils
+required_libraries = Analysis CodeGen Core DebugInfoCodeView MC MCParser Support Target TransformUtils
OpenPOWER on IntegriCloud