diff options
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 77 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h | 45 |
2 files changed, 51 insertions, 71 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index d2a8bfeb321..f1716361a1d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -22,20 +22,13 @@ using namespace llvm::codeview; namespace llvm { -StringRef CodeViewDebug::getFullFilepath(const MDNode *S) { - assert(S); - assert((isa<DICompileUnit>(S) || isa<DIFile>(S) || isa<DISubprogram>(S) || - isa<DILexicalBlockBase>(S)) && - "Unexpected scope info"); - - auto *Scope = cast<DIScope>(S); - StringRef Dir = Scope->getDirectory(), - Filename = Scope->getFilename(); - std::string &Filepath = - DirAndFilenameToFilepathMap[std::make_pair(Dir, Filename)]; +StringRef CodeViewDebug::getFullFilepath(const DIFile *File) { + std::string &Filepath = FileToFilepathMap[File]; if (!Filepath.empty()) return Filepath; + StringRef Dir = File->getDirectory(), Filename = File->getFilename(); + // Clang emits directory and relative filename info into the IR, but CodeView // operates on full paths. We could change Clang to emit full paths too, but // that would increase the IR size and probably not needed for other users. @@ -82,36 +75,25 @@ StringRef CodeViewDebug::getFullFilepath(const MDNode *S) { } void CodeViewDebug::maybeRecordLocation(DebugLoc DL, - const MachineFunction *MF) { - const MDNode *Scope = DL.getScope(); + const MachineFunction *MF) { + // Skip this instruction if it has the same location as the previous one. + if (DL == CurFn->LastLoc) + return; + + const DIScope *Scope = DL.get()->getScope(); if (!Scope) return; - unsigned LineNumber = DL.getLine(); + // Skip this line if it is longer than the maximum we can record. - if (LineNumber > COFF::CVL_MaxLineNumber) + if (DL.getLine() > COFF::CVL_MaxLineNumber) return; - unsigned ColumnNumber = DL.getCol(); - // Truncate the column number if it is longer than the maximum we can record. - if (ColumnNumber > COFF::CVL_MaxColumnNumber) - ColumnNumber = 0; - - StringRef Filename = getFullFilepath(Scope); - - // Skip this instruction if it has the same file:line as the previous one. - assert(CurFn); - if (!CurFn->Instrs.empty()) { - const InstrInfoTy &LastInstr = InstrInfo[CurFn->Instrs.back()]; - if (LastInstr.Filename == Filename && LastInstr.LineNumber == LineNumber && - LastInstr.ColumnNumber == ColumnNumber) - return; - } - FileNameRegistry.add(Filename); + CurFn->LastLoc = DL; MCSymbol *MCL = Asm->MMI->getContext().createTempSymbol(); Asm->OutStreamer->EmitLabel(MCL); CurFn->Instrs.push_back(MCL); - InstrInfo[MCL] = InstrInfoTy(Filename, LineNumber, ColumnNumber); + LabelsAndLocs[MCL] = DL; } CodeViewDebug::CodeViewDebug(AsmPrinter *AP) @@ -195,6 +177,10 @@ 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) { // For each function there is a separate subsection // which holds the PC to file:line table. @@ -258,13 +244,14 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV) { // number of the respective instruction that starts a new segment. DenseMap<size_t, size_t> FilenameSegmentLengths; size_t LastSegmentEnd = 0; - StringRef PrevFilename = InstrInfo[FI.Instrs[0]].Filename; + const DIFile *PrevFile = getFileFromLoc(LabelsAndLocs[FI.Instrs[0]]); for (size_t J = 1, F = FI.Instrs.size(); J != F; ++J) { - if (PrevFilename == InstrInfo[FI.Instrs[J]].Filename) + const DIFile *CurFile = getFileFromLoc(LabelsAndLocs[FI.Instrs[J]]); + if (PrevFile == CurFile) continue; FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd; LastSegmentEnd = J; - PrevFilename = InstrInfo[FI.Instrs[J]].Filename; + PrevFile = CurFile; } FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd; @@ -297,8 +284,11 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV) { for (size_t ColSegI = LastSegmentStart, ColSegEnd = ColSegI + FilenameSegmentLengths[LastSegmentStart]; ColSegI != ColSegEnd; ++ColSegI) { - unsigned ColumnNumber = InstrInfo[FI.Instrs[ColSegI]].ColumnNumber; - assert(ColumnNumber <= COFF::CVL_MaxColumnNumber); + 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 } @@ -307,22 +297,21 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV) { for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) { MCSymbol *Instr = FI.Instrs[J]; - assert(InstrInfo.count(Instr)); + assert(LabelsAndLocs.count(Instr)); if (FilenameSegmentLengths.count(J)) { // We came to a beginning of a new filename segment. FinishPreviousChunk(); - StringRef CurFilename = InstrInfo[FI.Instrs[J]].Filename; - assert(FileNameRegistry.Infos.count(CurFilename)); - size_t IndexInStringTable = - FileNameRegistry.Infos[CurFilename].FilenameID; + 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 * IndexInStringTable); + Asm->EmitInt32(8 * IndexInFileTable); // Number of PC records in the lookup table. size_t SegmentLength = FilenameSegmentLengths[J]; @@ -337,7 +326,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV) { // The first PC with the given linenumber and the linenumber itself. EmitLabelDiff(*Asm->OutStreamer, Fn, Instr); - uint32_t LineNumber = InstrInfo[Instr].LineNumber; + uint32_t LineNumber = LabelsAndLocs[Instr].getLine(); assert(LineNumber <= COFF::CVL_MaxLineNumber); uint32_t LineData = LineNumber | COFF::CVL_IsStatement; Asm->EmitInt32(LineData); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index 089c752caac..4294b4fd694 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -36,10 +36,12 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler { // For each function, store a vector of labels to its instructions, as well as // to the end of the function. struct FunctionInfo { + DebugLoc LastLoc; SmallVector<MCSymbol *, 10> Instrs; MCSymbol *End; FunctionInfo() : End(nullptr) {} - } *CurFn; + }; + FunctionInfo *CurFn; typedef DenseMap<const Function *, FunctionInfo> FnDebugInfoTy; FnDebugInfoTy FnDebugInfo; @@ -47,20 +49,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler { // order while emitting subsections. SmallVector<const Function *, 10> VisitedFunctions; - // InstrInfoTy - Holds the Filename:LineNumber information for every - // instruction with a unique debug location. - struct InstrInfoTy { - StringRef Filename; - unsigned LineNumber; - unsigned ColumnNumber; - - InstrInfoTy() : LineNumber(0), ColumnNumber(0) {} - - InstrInfoTy(StringRef Filename, unsigned LineNumber, unsigned ColumnNumber) - : Filename(Filename), LineNumber(LineNumber), - ColumnNumber(ColumnNumber) {} - }; - DenseMap<MCSymbol *, InstrInfoTy> InstrInfo; + DenseMap<MCSymbol *, DebugLoc> LabelsAndLocs; // FileNameRegistry - Manages filenames observed while generating debug info // by filtering out duplicates and bookkeeping the offsets in the string @@ -81,14 +70,17 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler { } // Add Filename to the registry, if it was not observed before. - void add(StringRef Filename) { - if (Infos.count(Filename)) - return; + size_t add(StringRef Filename) { size_t OldSize = Infos.size(); - Infos[Filename].FilenameID = OldSize; - Infos[Filename].StartOffset = LastOffset; - LastOffset += Filename.size() + 1; - Filenames.push_back(Filename); + 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() { @@ -98,17 +90,16 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler { } } FileNameRegistry; - typedef std::map<std::pair<StringRef, StringRef>, std::string> - DirAndFilenameToFilepathMapTy; - DirAndFilenameToFilepathMapTy DirAndFilenameToFilepathMap; - StringRef getFullFilepath(const MDNode *S); + typedef std::map<const DIFile *, std::string> FileToFilepathMapTy; + FileToFilepathMapTy FileToFilepathMap; + StringRef getFullFilepath(const DIFile *S); void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF); void clear() { assert(CurFn == nullptr); FileNameRegistry.clear(); - InstrInfo.clear(); + LabelsAndLocs.clear(); } void emitDebugInfoForFunction(const Function *GV); |