[llvm] [llvm] Implement S_INLINEES debug symbol (PR #67490)

Daniel Paoliello via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 26 14:15:04 PDT 2023


https://github.com/dpaoliello created https://github.com/llvm/llvm-project/pull/67490

The `S_INLINEES` debug symbol is used to record all the functions that are directly inlined within the current function (nested inlining is ignored).

This change implements support for emitting the `S_INLINEES` debug symbol in LLVM, and cleans up how the `S_INLINEES` and `S_CALLEES` debug symbols are dumped.

>From 134c307be38b2a0757e5d1d3dd60af95a110c96c Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao at microsoft.com>
Date: Tue, 26 Sep 2023 14:11:48 -0700
Subject: [PATCH] Implement S_INLINEES debug symbol

---
 llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 29 ++++++++++++++++++-
 llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h   |  6 ++++
 llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp  | 17 ++++++++++-
 llvm/test/DebugInfo/COFF/inlining-files.ll    |  6 ++++
 llvm/test/DebugInfo/COFF/inlining-header.ll   |  7 +++++
 llvm/test/DebugInfo/COFF/inlining-levels.ll   |  6 ++++
 llvm/test/DebugInfo/COFF/inlining-padding.ll  |  9 ++++++
 .../test/DebugInfo/COFF/inlining-same-name.ll |  6 ++++
 llvm/test/DebugInfo/COFF/inlining.ll          |  6 ++++
 .../llvm-readobj/COFF/codeview-inlinees.test  |  2 +-
 .../llvm-pdbutil/MinimalSymbolDumper.cpp      | 17 ++++++++++-
 11 files changed, 107 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index b25a38b26344138..411f7343f27bf0a 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 (ParentFuncId == CurFn->FuncId)
+      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,26 @@ void CodeViewDebug::emitDebugInfoForJumpTables(const FunctionInfo &FI) {
     endSymbolRecord(JumpTableEnd);
   }
 }
+
+void CodeViewDebug::emitInlinees(const SmallSet<codeview::TypeIndex, 1> &Inlinees) {
+  // Divide the list of inlinees into chunks such that each chunk fits within one record.
+  constexpr auto ChunkSize = (MaxRecordLength - sizeof(SymbolKind) - sizeof(int)) / sizeof(int);
+
+  SmallVector<TypeIndex> 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 eb274d25de9197a..4c03bf79d04da75 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 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
     /// Ordered list of top-level inlined call sites.
     SmallVector<const DILocation *, 1> ChildSites;
 
+    /// Set of all functions directly inlined into this one.
+    SmallSet<codeview::TypeIndex, 1> Inlinees;
+
     SmallVector<LocalVariable, 1> Locals;
     SmallVector<CVGlobalVariable, 1> Globals;
 
@@ -371,6 +375,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
   void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt,
                            const InlineSite &Site);
 
+  void emitInlinees(const SmallSet<codeview::TypeIndex, 1> &Inlinees);
+
   using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
 
   void collectGlobalVariableInfo();
diff --git a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
index c86fb244f6887b9..197001c1bdca04d 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<CodeViewError>(
+          "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/test/DebugInfo/COFF/inlining-files.ll b/llvm/test/DebugInfo/COFF/inlining-files.ll
index 9678219eca380ee..37edc6b8878a519 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 0e990cbb0fccac6..9a8200ca9fc56d1 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 70195e5371f5f43..8af12512d2ab30d 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 afe899db310ccec..75254b3e9a7c604 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 da3cabcb2bf8d82..374630b94ba4b61 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 d0b03cc5b21e3d3..6953abc87813a60 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 9f818dfc289908a..f8720e35641a778 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 6b6ba48f9214d85..111a7d0500adfdf 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<CodeViewError>(
+          "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();
 }



More information about the llvm-commits mailing list