diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h index e371fecff123..6271c7b8b2c5 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h @@ -226,6 +226,7 @@ public: Error visitKnownRecord(CVSymbol &Record, UDTSym &UDT) override; Error visitKnownRecord(CVSymbol &Record, UsingNamespaceSym &UN) override; Error visitKnownRecord(CVSymbol &Record, JumpTableSym &JumpTable) override; + Error visitKnownRecord(CVSymbol &Record, CallerSym &Caller) override; }; // Visitor for CodeView types and symbols to populate elements. diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index b25a38b26344..335eccb10651 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -250,7 +250,10 @@ CodeViewDebug::getInlineSite(const DILocation *InlinedAt, InlinedAt->getLine(), InlinedAt->getColumn(), SMLoc()); Site->Inlinee = Inlinee; InlinedSubprograms.insert(Inlinee); - getFuncIdForSubprogram(Inlinee); + auto InlineeIdx = getFuncIdForSubprogram(Inlinee); + + if (InlinedAt->getInlinedAt() == nullptr) + CurFn->Inlinees.insert(InlineeIdx); } return *Site; } @@ -1194,6 +1197,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, OS.emitInt32(uint32_t(FI.FrameProcOpts)); endSymbolRecord(FrameProcEnd); + emitInlinees(FI.Inlinees); emitLocalVariableList(FI, FI.Locals); emitGlobalVariableList(FI.Globals); emitLexicalBlockList(FI.ChildBlocks, FI); @@ -3588,3 +3592,31 @@ void CodeViewDebug::emitDebugInfoForJumpTables(const FunctionInfo &FI) { endSymbolRecord(JumpTableEnd); } } + +void CodeViewDebug::emitInlinees( + const SmallSet &Inlinees) { + // Divide the list of inlinees into chunks such that each chunk fits within + // one record. + constexpr auto ChunkSize = + (MaxRecordLength - sizeof(SymbolKind) - sizeof(uint32_t)) / + sizeof(uint32_t); + + SmallVector SortedInlinees{Inlinees.begin(), Inlinees.end()}; + llvm::sort(SortedInlinees); + + uint64_t CurrentIndex = 0; + while (CurrentIndex < SortedInlinees.size()) { + auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES); + auto CurrentChunkSize = + std::min(ChunkSize, SortedInlinees.size() - CurrentIndex); + OS.AddComment("Count"); + OS.emitInt32(CurrentChunkSize); + + const uint64_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize; + for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) { + OS.AddComment("Inlinee"); + OS.emitInt32(SortedInlinees[CurrentIndex].getIndex()); + } + endSymbolRecord(Symbol); + } +} diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index eb274d25de91..4c03bf79d04d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -20,6 +20,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/DbgEntityHistoryCalculator.h" #include "llvm/CodeGen/DebugHandlerBase.h" @@ -158,6 +159,9 @@ private: /// Ordered list of top-level inlined call sites. SmallVector ChildSites; + /// Set of all functions directly inlined into this one. + SmallSet Inlinees; + SmallVector Locals; SmallVector Globals; @@ -371,6 +375,8 @@ private: void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt, const InlineSite &Site); + void emitInlinees(const SmallSet &Inlinees); + using InlinedEntity = DbgValueHistoryMap::InlinedEntity; void collectGlobalVariableInfo(); diff --git a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp index c86fb244f688..f56739db7c75 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -589,7 +589,22 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, } Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) { - ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers"); + llvm::StringRef ScopeName; + switch (CVR.kind()) { + case S_CALLEES: + ScopeName = "Callees"; + break; + case S_CALLERS: + ScopeName = "Callers"; + break; + case S_INLINEES: + ScopeName = "Inlinees"; + break; + default: + return llvm::make_error( + "Unknown CV Record type for a CallerSym object!"); + } + ListScope S(W, ScopeName); for (auto FuncID : Caller.Indices) printTypeIndex("FuncID", FuncID); return Error::success(); diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp index fdb089c1a5f7..5a6414f5564f 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp @@ -1705,6 +1705,31 @@ Error LVSymbolVisitor::visitKnownRecord(CVSymbol &CVR, return Error::success(); } +// S_CALLERS, S_CALLEES, S_INLINEES +Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, CallerSym &Caller) { + LLVM_DEBUG({ + llvm::StringRef FieldName; + switch (Caller.getKind()) { + case SymbolRecordKind::CallerSym: + FieldName = "Callee"; + break; + case SymbolRecordKind::CalleeSym: + FieldName = "Caller"; + break; + case SymbolRecordKind::InlineesSym: + FieldName = "Inlinee"; + break; + default: + return llvm::make_error( + "Unknown CV Record type for a CallerSym object!"); + } + for (auto FuncID : Caller.Indices) { + printTypeIndex(FieldName, FuncID); + } + }); + return Error::success(); +} + #undef DEBUG_TYPE #define DEBUG_TYPE "CodeViewLogicalVisitor" diff --git a/llvm/test/DebugInfo/COFF/inlining-files.ll b/llvm/test/DebugInfo/COFF/inlining-files.ll index 9678219eca38..37edc6b8878a 100644 --- a/llvm/test/DebugInfo/COFF/inlining-files.ll +++ b/llvm/test/DebugInfo/COFF/inlining-files.ll @@ -21,6 +21,12 @@ ; OBJ: {{.*}}Proc{{.*}}Sym { ; OBJ: DisplayName: f ; OBJ: } +; OBJ: InlineesSym { +; OBJ-NEXT: Kind: S_INLINEES (0x1168) +; OBJ-NEXT: Inlinees [ +; OBJ-NEXT: FuncID: file_change (0x1002) +; OBJ-NEXT: ] +; OBJ-NEXT:} ; OBJ: InlineSiteSym { ; OBJ: PtrParent: 0x0 ; OBJ: PtrEnd: 0x0 diff --git a/llvm/test/DebugInfo/COFF/inlining-header.ll b/llvm/test/DebugInfo/COFF/inlining-header.ll index 0e990cbb0fcc..9a8200ca9fc5 100644 --- a/llvm/test/DebugInfo/COFF/inlining-header.ll +++ b/llvm/test/DebugInfo/COFF/inlining-header.ll @@ -75,6 +75,13 @@ ; OBJ: LinkageName: _main ; OBJ: } +; OBJ: InlineesSym { +; OBJ-NEXT: Kind: S_INLINEES (0x1168) +; OBJ-NEXT: Inlinees [ +; OBJ-NEXT: FuncID: g (0x1002) +; OBJ-NEXT: ] +; OBJ-NEXT: } + ; Previously, g's InlineSiteSym referenced t.h, which was wasteful. ; OBJ: InlineSiteSym { ; OBJ: Inlinee: g (0x1002) diff --git a/llvm/test/DebugInfo/COFF/inlining-levels.ll b/llvm/test/DebugInfo/COFF/inlining-levels.ll index 70195e5371f5..8af12512d2ab 100644 --- a/llvm/test/DebugInfo/COFF/inlining-levels.ll +++ b/llvm/test/DebugInfo/COFF/inlining-levels.ll @@ -19,6 +19,12 @@ ; OBJ: Subsection [ ; OBJ: SubSectionType: Symbols (0xF1) ; OBJ: {{.*}}Proc{{.*}}Sym { +; OBJ: InlineesSym { +; OBJ-NEXT: Kind: S_INLINEES (0x1168) +; OBJ-NEXT: Inlinees [ +; OBJ-NEXT: FuncID: h (0x1002) +; OBJ-NEXT: ] +; OBJ-NEXT:} ; OBJ: InlineSiteSym { ; OBJ: Inlinee: h (0x1002) ; OBJ: } diff --git a/llvm/test/DebugInfo/COFF/inlining-padding.ll b/llvm/test/DebugInfo/COFF/inlining-padding.ll index afe899db310c..75254b3e9a7c 100644 --- a/llvm/test/DebugInfo/COFF/inlining-padding.ll +++ b/llvm/test/DebugInfo/COFF/inlining-padding.ll @@ -33,6 +33,15 @@ ; CHECK: ) ; CHECK: } +; CHECK: InlineesSym { +; CHECK-NEXT: Kind: S_INLINEES (0x1168) +; CHECK-NEXT: Inlinees [ +; CHECK-NEXT: FuncID: a (0x1002) +; CHECK-NEXT: FuncID: ab (0x1003) +; CHECK-NEXT: FuncID: abc (0x1004) +; CHECK-NEXT: FuncID: abcd (0x1005) +; CHECK-NEXT: ] + ; C++ source used to generate the IR: ; ; extern volatile int x; diff --git a/llvm/test/DebugInfo/COFF/inlining-same-name.ll b/llvm/test/DebugInfo/COFF/inlining-same-name.ll index da3cabcb2bf8..374630b94ba4 100644 --- a/llvm/test/DebugInfo/COFF/inlining-same-name.ll +++ b/llvm/test/DebugInfo/COFF/inlining-same-name.ll @@ -18,6 +18,12 @@ ; CHECK: {{.*}}Proc{{.*}}Sym { ; CHECK: DisplayName: main ; CHECK: } +; CHECK: InlineesSym { +; CHECK-NEXT: Kind: S_INLINEES (0x1168) +; CHECK-NEXT: Inlinees [ +; CHECK-NEXT: FuncID: same_name (0x1002) +; CHECK-NEXT: ] +; CHECK-NEXT:} ; CHECK: InlineSiteSym { ; CHECK: Inlinee: same_name (0x1002) ; CHECK: } diff --git a/llvm/test/DebugInfo/COFF/inlining.ll b/llvm/test/DebugInfo/COFF/inlining.ll index d0b03cc5b21e..6953abc87813 100644 --- a/llvm/test/DebugInfo/COFF/inlining.ll +++ b/llvm/test/DebugInfo/COFF/inlining.ll @@ -166,6 +166,12 @@ ; OBJ: DisplayName: baz ; OBJ: LinkageName: ?baz@@YAXXZ ; OBJ: } +; OBJ: InlineesSym { +; OBJ-NEXT: Kind: S_INLINEES (0x1168) +; OBJ-NEXT: Inlinees [ +; OBJ-NEXT: FuncID: bar (0x1002) +; OBJ-NEXT: ] +; OBJ-NEXT:} ; OBJ: InlineSiteSym { ; OBJ: PtrParent: 0x0 ; OBJ: PtrEnd: 0x0 diff --git a/llvm/test/tools/llvm-readobj/COFF/codeview-inlinees.test b/llvm/test/tools/llvm-readobj/COFF/codeview-inlinees.test index 9f818dfc2899..f8720e35641a 100644 --- a/llvm/test/tools/llvm-readobj/COFF/codeview-inlinees.test +++ b/llvm/test/tools/llvm-readobj/COFF/codeview-inlinees.test @@ -28,7 +28,7 @@ CHECK: Kind: S_INLINESITE (0x114D) CHECK: Inlinee: f (0x1003) CHECK: InlineesSym { CHECK-NEXT: Kind: S_INLINEES (0x1168) -CHECK-NEXT: Callers [ +CHECK-NEXT: Inlinees [ CHECK-NEXT: FuncID: f (0x1003) CHECK-NEXT: FuncID: h (0x1004) CHECK-NEXT: ] diff --git a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp index 6b6ba48f9214..1beb2d282744 100644 --- a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp +++ b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp @@ -875,9 +875,24 @@ Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, } Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) { + const char *Format; + switch (CVR.kind()) { + case S_CALLEES: + Format = "callee: {0}"; + break; + case S_CALLERS: + Format = "caller: {0}"; + break; + case S_INLINEES: + Format = "inlinee: {0}"; + break; + default: + return llvm::make_error( + "Unknown CV Record type for a CallerSym object!"); + } AutoIndent Indent(P, 7); for (const auto &I : Caller.Indices) { - P.formatLine("callee: {0}", idIndex(I)); + P.formatLine(Format, idIndex(I)); } return Error::success(); }