diff options
author | Reid Kleckner <rnk@google.com> | 2016-01-29 00:49:42 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2016-01-29 00:49:42 +0000 |
commit | 2214ed8937a05b9457b167a84d6732a448fad27f (patch) | |
tree | 8418d7840e286b16568c7f6c3301757fbd92771e /llvm/lib/CodeGen/AsmPrinter | |
parent | 0407108020ed12d8c34582d847d2c37cd68d1d0b (diff) | |
download | bcm5719-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.cpp | 184 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h | 70 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/LLVMBuild.txt | 2 |
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 |