Skip to content

Commit 5914f73

Browse files
[DebugInfo] Add symbol for debugger with VTable information.
One of the points mentioned by the reviewers is the usage (pros and cons) of the global variable that contains the vtable information: - The consumer needs to have access to that variable in order to get the vtable information. This patch eliminates that global variable and it moves the vtable information into the static member; in that way, a consumer always will have access to the vtable information, just by having an object instance or the object definition.
1 parent e811ab7 commit 5914f73

File tree

7 files changed

+94
-20
lines changed

7 files changed

+94
-20
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2545,25 +2545,27 @@ void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable,
25452545
llvm::DIScope *DContext = getContextDescriptor(cast<Decl>(DC), TheCU);
25462546
auto *Ctxt = cast<llvm::DICompositeType>(DContext);
25472547
llvm::DIFile *Unit = getOrCreateFile(Loc);
2548-
llvm::DIType *VTy = getOrCreateType(VoidPtr, Unit);
2548+
llvm::DIType *VTableType = getOrCreateType(VoidPtr, Unit);
25492549
llvm::DINode::DIFlags Flags = getAccessFlag(AccessSpecifier::AS_private, RD) |
25502550
llvm::DINode::FlagArtificial;
25512551
auto Tag = CGM.getCodeGenOpts().DwarfVersion >= 5
25522552
? llvm::dwarf::DW_TAG_variable
25532553
: llvm::dwarf::DW_TAG_member;
25542554
llvm::DIDerivedType *DT = DBuilder.createStaticMemberType(
2555-
Ctxt, SymbolName, Unit, /*LineNumber=*/0, VTy, Flags,
2555+
Ctxt, SymbolName, Unit, /*LineNumber=*/0, VTableType, Flags,
25562556
/*Val=*/nullptr, Tag);
25572557

25582558
// Use the same vtable pointer to global alignment for the symbol.
25592559
unsigned PAlign = CGM.getGlobalVarAlignment();
25602560

25612561
// The global variable is in the CU scope, and links back to the type it's
25622562
// "within" via the declaration field.
2563+
// No debug information is created for it. It is just used to generate the
2564+
// debug information within the static data member.
25632565
llvm::DIGlobalVariableExpression *GVE =
25642566
DBuilder.createGlobalVariableExpression(
2565-
TheCU, SymbolName, VTable->getName(), Unit, /*LineNo=*/0,
2566-
getOrCreateType(VoidPtr, Unit), VTable->hasLocalLinkage(),
2567+
TheCU, SymbolName, VTable->getName(), Unit, /*LineNo=*/0, VTableType,
2568+
VTable->hasLocalLinkage(),
25672569
/*isDefined=*/true, nullptr, DT, /*TemplateParameters=*/nullptr,
25682570
PAlign);
25692571
VTable->addDebugInfo(GVE);

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,72 @@ unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) {
175175
return LastFileID;
176176
}
177177

178+
// Create the static member to hold the vtable information.
179+
// The debug information generated for static members is composed of 2 DIEs:
180+
// <DIE-1> and <DIE-2>.
181+
//
182+
// - Variable definition with a DW_AT_specification pointing to the second DIE.
183+
// DIE-1: DW_TAG_variable
184+
// ..
185+
// DW_AT_specification <DIE-2>
186+
// DW_AT_location <some-location>
187+
// ..
188+
// - Parent for the static member.
189+
// DIE-3: DW_TAG_structure_type
190+
// ...
191+
// - Variable declaration
192+
// DIE-2: DW_TAG_variable
193+
// ..
194+
// DW_AT_declaration (true)
195+
// ..
196+
//
197+
// As this static member is mainly intended for debuggers, there are cases
198+
// where there is no access to <DIE-1> making difficult to associate the
199+
// vtable information with its structure/class, as we can't use <DIE-2> to
200+
// find its parent <DIE-3>.
201+
// Basically, having just an instance of a structure/class, we can't access
202+
// its associated vtable information.
203+
//
204+
// By eliminating the <DIE-1> and moving the location information to <DIE-2>,
205+
// the consumers, will be able to associate the vtable information to the
206+
// parent <DIE-3>, using just an object or an object instance.
207+
//
208+
// DIE-3: DW_TAG_structure_type
209+
// ...
210+
// DIE-2: DW_TAG_variable
211+
// ..
212+
// DW_AT_location <some-location>
213+
void DwarfCompileUnit::createGlobalVariableVTableDIE(
214+
const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) {
215+
// Check for pre-existence.
216+
if (getDIE(GV))
217+
return;
218+
219+
assert(GV);
220+
assert(GV->isDefinition());
221+
222+
DIDerivedType *SDMDecl = GV->getStaticDataMemberDeclaration();
223+
assert(SDMDecl && "Expected static member decl");
224+
assert(SDMDecl->isStaticMember() && "Expected static member decl");
225+
226+
// We need the declaration DIE that is in the static member's class.
227+
// As some debuggers will usually ignore DIEs with the DW_AT_declaration
228+
// attribute and assume that they'll be a specification DIE somewhere
229+
// else that refers to it. Skip the DW_AT_declaration generation.
230+
DIE *VariableSpecDIE =
231+
getOrCreateStaticMemberDIE(SDMDecl, /*IsDeclaration*/false);
232+
233+
if (uint32_t AlignInBytes = GV->getAlignInBytes())
234+
addUInt(*VariableSpecDIE, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
235+
AlignInBytes);
236+
237+
if (MDTuple *TP = GV->getTemplateParams())
238+
addTemplateParams(*VariableSpecDIE, DINodeArray(TP));
239+
240+
// Add location.
241+
addLocationAttribute(VariableSpecDIE, GV, GlobalExprs);
242+
}
243+
178244
DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
179245
const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) {
180246
// Check for pre-existence.

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ class DwarfCompileUnit final : public DwarfUnit {
178178

179179
std::vector<BaseTypeRef> ExprRefedBaseTypes;
180180

181+
/// Create global variable DIE for VTable.
182+
void createGlobalVariableVTableDIE(const DIGlobalVariable *GV,
183+
ArrayRef<GlobalExpr> GlobalExprs);
184+
181185
/// Get or create global variable DIE.
182186
DIE *
183187
getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV,

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1212,7 +1212,11 @@ void DwarfDebug::beginModule(Module *M) {
12121212
for (auto *GVE : CUNode->getGlobalVariables()) {
12131213
DIGlobalVariable *GV = GVE->getVariable();
12141214
if (Processed.insert(GV).second)
1215-
CU.getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV]));
1215+
// Check if we are dealing with a variable representing a vtable.
1216+
if (GV->getDisplayName() == "_vtable$" && GV->isDefinition())
1217+
CU.createGlobalVariableVTableDIE(GV, sortGlobalExprs(GVMap[GV]));
1218+
else
1219+
CU.getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV]));
12161220
}
12171221

12181222
for (auto *Ty : CUNode->getEnumTypes())

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,8 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
18431843
return MemberDie;
18441844
}
18451845

1846-
DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
1846+
DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT,
1847+
bool IsDeclaration) {
18471848
if (!DT)
18481849
return nullptr;
18491850

@@ -1864,7 +1865,8 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
18641865
addType(StaticMemberDIE, Ty);
18651866
addSourceLine(StaticMemberDIE, DT);
18661867
addFlag(StaticMemberDIE, dwarf::DW_AT_external);
1867-
addFlag(StaticMemberDIE, dwarf::DW_AT_declaration);
1868+
if (IsDeclaration)
1869+
addFlag(StaticMemberDIE, dwarf::DW_AT_declaration);
18681870

18691871
// Consider the case when the static member was created by the compiler.
18701872
if (DT->isArtificial())

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,8 @@ class DwarfUnit : public DIEUnit {
328328
~DwarfUnit();
329329

330330
/// Create new static data member DIE.
331-
DIE *getOrCreateStaticMemberDIE(const DIDerivedType *DT);
331+
DIE *getOrCreateStaticMemberDIE(const DIDerivedType *DT,
332+
bool IsDeclaration = true);
332333

333334
/// Look up the source ID for the given file. If none currently exists,
334335
/// create a new ID and insert it in the line table.

llvm/test/DebugInfo/X86/vtable-debug-info-inheritance-simple.ll

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -172,35 +172,30 @@ attributes #0 = { mustprogress noinline norecurse nounwind uwtable "frame-pointe
172172

173173
; CHECK: .debug_info contents:
174174
; CHECK-NEXT: 0x00000000: Compile Unit:
175-
; CHECK: {{.*}}DW_TAG_variable
176-
; CHECK-NEXT: DW_AT_specification ([[VARDIE_1:.+]] "_vtable$")
177-
; CHECK-NEXT: DW_AT_alignment (8)
178-
; CHECK-NEXT: DW_AT_location (DW_OP_addrx 0x0)
179-
; CHECK-NEXT: DW_AT_linkage_name ("_ZTVN3NSP5CBaseE")
180175

181176
; CHECK: {{.*}}DW_TAG_namespace
182177
; CHECK-NEXT: DW_AT_name ("NSP")
183178

184179
; CHECK: {{.*}}DW_TAG_structure_type
185180
; CHECK: DW_AT_name ("CBase")
186181

187-
; CHECK: [[VARDIE_1]]: DW_TAG_variable
182+
; CHECK: DW_TAG_variable
188183
; CHECK-NEXT: DW_AT_name ("_vtable$")
189184
; CHECK-NEXT: DW_AT_type ({{.*}} "void *")
190185
; CHECK: DW_AT_artificial (true)
191186
; CHECK-NEXT: DW_AT_accessibility (DW_ACCESS_private)
192-
193-
; CHECK: {{.*}}DW_TAG_variable
194-
; CHECK-NEXT: DW_AT_specification ([[VARDIE_2:.+]] "_vtable$")
195187
; CHECK-NEXT: DW_AT_alignment (8)
196-
; CHECK-NEXT: DW_AT_location (DW_OP_addrx 0x1)
197-
; CHECK-NEXT: DW_AT_linkage_name ("_ZTV8CDerived")
188+
; CHECK-NEXT: DW_AT_location (DW_OP_addrx 0x0)
189+
; CHECK-NEXT: DW_AT_linkage_name ("_ZTVN3NSP5CBaseE")
198190

199191
; CHECK: {{.*}}DW_TAG_structure_type
200192
; CHECK: DW_AT_name ("CDerived")
201193

202-
; CHECK: [[VARDIE_2]]: DW_TAG_variable
194+
; CHECK: DW_TAG_variable
203195
; CHECK-NEXT: DW_AT_name ("_vtable$")
204196
; CHECK-NEXT: DW_AT_type ({{.*}} "void *")
205197
; CHECK: DW_AT_artificial (true)
206198
; CHECK-NEXT: DW_AT_accessibility (DW_ACCESS_private)
199+
; CHECK-NEXT: DW_AT_alignment (8)
200+
; CHECK-NEXT: DW_AT_location (DW_OP_addrx 0x1)
201+
; CHECK-NEXT: DW_AT_linkage_name ("_ZTV8CDerived")

0 commit comments

Comments
 (0)