diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 139 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h | 30 | ||||
-rw-r--r-- | llvm/lib/MC/MCObjectFileInfo.cpp | 13 |
3 files changed, 177 insertions, 5 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index b503f1dc31e..e3c48296f34 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -15,6 +15,8 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/COFF.h" @@ -87,6 +89,17 @@ unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) { return Insertion.first->second; } +CodeViewDebug::InlineSite &CodeViewDebug::getInlineSite(const DILocation *Loc) { + const DILocation *InlinedAt = Loc->getInlinedAt(); + auto Insertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()}); + if (Insertion.second) { + InlineSite &Site = Insertion.first->second; + Site.SiteFuncId = NextFuncId++; + Site.Inlinee = Loc->getScope()->getSubprogram(); + } + 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. @@ -115,7 +128,28 @@ void CodeViewDebug::maybeRecordLocation(DebugLoc DL, else FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile()); CurFn->LastLoc = DL; - Asm->OutStreamer->EmitCVLocDirective(CurFn->FuncId, FileId, DL.getLine(), + + unsigned FuncId = CurFn->FuncId; + if (const DILocation *Loc = DL->getInlinedAt()) { + // If this location was actually inlined from somewhere else, give it the ID + // of the inline call site. + FuncId = getInlineSite(DL.get()).SiteFuncId; + // Ensure we have links in the tree of inline call sites. + const DILocation *ChildLoc = nullptr; + while (Loc->getInlinedAt()) { + InlineSite &Site = getInlineSite(Loc); + if (ChildLoc) { + // Record the child inline site if not already present. + auto B = Site.ChildSites.begin(), E = Site.ChildSites.end(); + if (std::find(B, E, Loc) != E) + break; + Site.ChildSites.push_back(Loc); + } + ChildLoc = Loc; + } + } + + Asm->OutStreamer->EmitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(), /*PrologueEnd=*/false, /*IsStmt=*/false, DL->getFilename()); } @@ -139,6 +173,8 @@ void CodeViewDebug::endModule() { if (FnDebugInfo.empty()) return; + emitTypeInformation(); + // FIXME: For functions that are comdat, we should emit separate .debug$S // sections that are comdat associative with the main function instead of // having one big .debug$S section. @@ -167,6 +203,60 @@ void CodeViewDebug::endModule() { clear(); } +template <typename T> static void emitRecord(MCStreamer &OS, const T &Rec) { + OS.EmitBytes(StringRef(reinterpret_cast<const char *>(&Rec), sizeof(Rec))); +} + +void CodeViewDebug::emitTypeInformation() { + // Start the .debug$T section with 0x4. + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getCOFFDebugTypesSection()); + Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC); + + NamedMDNode *CU_Nodes = + Asm->MMI->getModule()->getNamedMetadata("llvm.dbg.cu"); + if (!CU_Nodes) + return; + + // This type info currently only holds function ids for use with inline call + // frame info. All functions are assigned a simple 'void ()' type. Emit that + // type here. + TypeIndex ArgListIdx = getNextTypeIndex(); + Asm->EmitInt16(2 + sizeof(ArgList)); + Asm->EmitInt16(LF_ARGLIST); + Asm->EmitInt32(0); + + TypeIndex VoidProcIdx = getNextTypeIndex(); + Asm->EmitInt16(2 + sizeof(ProcedureType)); + Asm->EmitInt16(LF_PROCEDURE); + ProcedureType Proc{}; // Zero initialize. + Proc.ReturnType = TypeIndex::Void(); + Proc.CallConv = CallingConvention::NearC; + Proc.Options = FunctionOptions::None; + Proc.NumParameters = 0; + Proc.ArgListType = ArgListIdx; + emitRecord(*Asm->OutStreamer, Proc); + + for (MDNode *N : CU_Nodes->operands()) { + auto *CUNode = cast<DICompileUnit>(N); + for (auto *SP : CUNode->getSubprograms()) { + StringRef DisplayName = SP->getDisplayName(); + Asm->EmitInt16(2 + sizeof(FuncId) + DisplayName.size() + 1); + Asm->EmitInt16(LF_FUNC_ID); + + FuncId Func{}; // Zero initialize. + Func.ParentScope = TypeIndex(); + Func.FunctionType = VoidProcIdx; + emitRecord(*Asm->OutStreamer, Func); + Asm->OutStreamer->EmitBytes(DisplayName); + Asm->EmitInt8(0); + + TypeIndex FuncIdIdx = getNextTypeIndex(); + SubprogramToFuncId.insert(std::make_pair(SP, FuncIdIdx)); + } + } +} + static void EmitLabelDiff(MCStreamer &Streamer, const MCSymbol *From, const MCSymbol *To, unsigned int Size = 4) { @@ -179,6 +269,44 @@ static void EmitLabelDiff(MCStreamer &Streamer, Streamer.EmitValue(AddrDelta, Size); } +void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI, + const DILocation *InlinedAt, + const InlineSite &Site) { + MCStreamer &OS = *Asm->OutStreamer; + + MCSymbol *InlineBegin = Asm->MMI->getContext().createTempSymbol(), + *InlineEnd = Asm->MMI->getContext().createTempSymbol(); + + assert(SubprogramToFuncId.count(Site.Inlinee)); + TypeIndex InlineeIdx = SubprogramToFuncId[Site.Inlinee]; + + // SymbolRecord + EmitLabelDiff(OS, InlineBegin, InlineEnd, 2); // RecordLength + OS.EmitLabel(InlineBegin); + Asm->EmitInt16(SymbolRecordKind::S_INLINESITE); // RecordKind + + InlineSiteSym SiteBytes{}; + SiteBytes.Inlinee = InlineeIdx; + Asm->OutStreamer->EmitBytes( + StringRef(reinterpret_cast<const char *>(&SiteBytes), sizeof(SiteBytes))); + + // FIXME: annotations + + OS.EmitLabel(InlineEnd); + + // Recurse on child inlined call sites before closing the scope. + for (const DILocation *ChildSite : Site.ChildSites) { + auto I = FI.InlineSites.find(ChildSite); + assert(I != FI.InlineSites.end() && + "child site not in function inline site map"); + emitInlinedCallSite(FI, ChildSite, I->second); + } + + // Close the scope. + Asm->EmitInt16(2); // RecordLength + Asm->EmitInt16(SymbolRecordKind::S_INLINESITE_END); // RecordKind +} + void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI) { // For each function there is a separate subsection @@ -224,6 +352,15 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, Asm->EmitInt8(0); Asm->OutStreamer->EmitLabel(ProcSegmentEnd); + // Emit inlined call site information. Only emit functions inlined directly + // into the parent function. We'll emit the other sites recursively as part + // of their parent inline site. + for (auto &KV : FI.InlineSites) { + const DILocation *InlinedAt = KV.first; + if (!InlinedAt->getInlinedAt()) + emitInlinedCallSite(FI, InlinedAt, KV.second); + } + // We're done with this function. Asm->EmitInt16(0x0002); Asm->EmitInt16(unsigned(SymbolRecordKind::S_PROC_ID_END)); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index 77b5ed39c1f..4883905e907 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -22,6 +22,7 @@ #include "llvm/CodeGen/LexicalScopes.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DebugLoc.h" #include "llvm/MC/MCStreamer.h" @@ -33,19 +34,31 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler { AsmPrinter *Asm; DebugLoc PrevInstLoc; + struct InlineSite { + TinyPtrVector<const DILocation *> ChildSites; + const DISubprogram *Inlinee = nullptr; + unsigned SiteFuncId = 0; + }; + // For each function, store a vector of labels to its instructions, as well as // to the end of the function. struct FunctionInfo { + /// Map from inlined call site to inlined instructions and child inlined + /// call sites. Listed in program order. + MapVector<const DILocation *, InlineSite> InlineSites; + DebugLoc LastLoc; MCSymbol *End = nullptr; unsigned FuncId = 0; - unsigned LastFileId; + unsigned LastFileId = 0; bool HaveLineInfo = false; }; FunctionInfo *CurFn; unsigned NextFuncId = 0; + InlineSite &getInlineSite(const DILocation *Loc); + /// 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; @@ -53,6 +66,16 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler { /// Map from DIFile to .cv_file id. DenseMap<const DIFile *, unsigned> FileIdMap; + DenseMap<const DISubprogram *, codeview::TypeIndex> SubprogramToFuncId; + + unsigned TypeCount = 0; + + /// Gets the next type index and increments the count of types streamed so + /// far. + codeview::TypeIndex getNextTypeIndex() { + return codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex + TypeCount++); + } + typedef std::map<const DIFile *, std::string> FileToFilepathMapTy; FileToFilepathMapTy FileToFilepathMap; StringRef getFullFilepath(const DIFile *S); @@ -68,8 +91,13 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler { FileToFilepathMap.clear(); } + void emitTypeInformation(); + void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI); + void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt, + const InlineSite &Site); + public: CodeViewDebug(AsmPrinter *Asm); diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp index 0c86fa81c1b..05eadeb44a5 100644 --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -191,6 +191,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) { SectionKind::getReadOnlyWithRel()); COFFDebugSymbolsSection = nullptr; + COFFDebugTypesSection = nullptr; if (useCompactUnwind(T)) { CompactUnwindSection = @@ -484,6 +485,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { ELF::SHF_ALLOC); COFFDebugSymbolsSection = nullptr; + COFFDebugTypesSection = nullptr; // Debug Info Sections. DwarfAbbrevSection = Ctx->getELFSection(".debug_abbrev", ELF::SHT_PROGBITS, 0, @@ -623,9 +625,14 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) { // Debug info. COFFDebugSymbolsSection = - Ctx->getCOFFSection(".debug$S", COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, + Ctx->getCOFFSection(".debug$S", (COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ), + SectionKind::getMetadata()); + COFFDebugTypesSection = + Ctx->getCOFFSection(".debug$T", (COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ), SectionKind::getMetadata()); DwarfAbbrevSection = Ctx->getCOFFSection( |