[llvm] Implement S_INLINEES debug symbol (#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.
This commit is contained in:
parent
a82368ca7b
commit
050bb26174
@ -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.
|
||||
|
||||
@ -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<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(uint32_t)) /
|
||||
sizeof(uint32_t);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<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 @@ private:
|
||||
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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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<CodeViewError>(
|
||||
"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"
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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: }
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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: }
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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: ]
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user