Skip to content

Commit fe9624f

Browse files
committed
[clang][DebugInfo] Revert "emit variable definitions for constant-initialized static data-members"
This commit reverts the changes in llvm#71780 and all of its follow-up patches. We got reports of the `.debug_names/.debug_gnu_pubnames/gdb_index/etc.` sections growing by a non-trivial amount for some large projects. While GCC does index definitions for static data member constants, they do so *only* for explicitly `constexpr` members. We were indexing *all* constant-initialized const-static members, which is likely where the significant size difference comes from. However, only emitting explicitly `constexpr` variables into the index doesn't seem like a good way forward, since from clang's perspective `const`-static integrals are `constexpr` too, and that shouldn't be any different in the debug-info component. Also, as new code moves to `constexpr` instead of `const` static for constants, such solution would just delay the growth of the Names index. To prevent the size regression we revert to not emitting definitions for static data-members that have no location. To support access to such constants from LLDB we'll most likely have to have to make LLDB find the constants by looking at the containing class first.
1 parent fcd06d7 commit fe9624f

File tree

7 files changed

+10
-280
lines changed

7 files changed

+10
-280
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -69,29 +69,6 @@ static uint32_t getDeclAlignIfRequired(const Decl *D, const ASTContext &Ctx) {
6969
return D->hasAttr<AlignedAttr>() ? D->getMaxAlignment() : 0;
7070
}
7171

72-
/// Given a VarDecl corresponding to either the definition or
73-
/// declaration of a C++ static data member, if it has a constant
74-
/// initializer and is evaluatable, return the evaluated value.
75-
/// Returns std::nullopt otherwise.
76-
static std::optional<APValue>
77-
evaluateConstantInitializer(const clang::VarDecl *VD,
78-
const clang::ASTContext &Ctx) {
79-
assert(VD != nullptr);
80-
81-
if (!VD->isStaticDataMember())
82-
return std::nullopt;
83-
84-
if (!VD->isUsableInConstantExpressions(Ctx))
85-
return std::nullopt;
86-
87-
auto const *InitExpr = VD->getAnyInitializer();
88-
Expr::EvalResult Result;
89-
if (!InitExpr->EvaluateAsConstantExpr(Result, Ctx))
90-
return std::nullopt;
91-
92-
return Result.Val;
93-
}
94-
9572
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
9673
: CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
9774
DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs),
@@ -1724,7 +1701,6 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
17241701
llvm::DIDerivedType *GV = DBuilder.createStaticMemberType(
17251702
RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Tag, Align);
17261703
StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV);
1727-
StaticDataMemberDefinitionsToEmit.push_back(Var->getCanonicalDecl());
17281704
return GV;
17291705
}
17301706

@@ -5628,41 +5604,6 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
56285604
TemplateParameters, Align));
56295605
}
56305606

5631-
void CGDebugInfo::EmitGlobalVariable(const VarDecl *VD) {
5632-
assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
5633-
if (VD->hasAttr<NoDebugAttr>())
5634-
return;
5635-
5636-
const auto CacheIt = DeclCache.find(VD);
5637-
if (CacheIt != DeclCache.end())
5638-
return;
5639-
5640-
const auto InitVal = evaluateConstantInitializer(VD, CGM.getContext());
5641-
if (!InitVal)
5642-
return;
5643-
5644-
llvm::DIFile *Unit = nullptr;
5645-
llvm::DIScope *DContext = nullptr;
5646-
unsigned LineNo;
5647-
StringRef DeclName, LinkageName;
5648-
QualType T;
5649-
llvm::MDTuple *TemplateParameters = nullptr;
5650-
collectVarDeclProps(VD, Unit, LineNo, T, DeclName, LinkageName,
5651-
TemplateParameters, DContext);
5652-
5653-
auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
5654-
llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(VD);
5655-
llvm::DIExpression *InitExpr = createConstantValueExpression(VD, *InitVal);
5656-
5657-
// Omit linkage name for variable definitions that represent constants.
5658-
// There hasn't been a need from consumers yet to have it attached.
5659-
DeclCache[VD].reset(DBuilder.createGlobalVariableExpression(
5660-
TheCU, DeclName, /* LinkageName */ {}, Unit, LineNo,
5661-
getOrCreateType(T, Unit), true, true, InitExpr,
5662-
getOrCreateStaticDataMemberDeclarationOrNull(VD), TemplateParameters,
5663-
Align, Annotations));
5664-
}
5665-
56665607
void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var,
56675608
const VarDecl *D) {
56685609
assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
@@ -5867,20 +5808,6 @@ void CGDebugInfo::setDwoId(uint64_t Signature) {
58675808
}
58685809

58695810
void CGDebugInfo::finalize() {
5870-
// We can't use a for-each here because `EmitGlobalVariable`
5871-
// may push new decls into `StaticDataMemberDefinitionsToEmit`,
5872-
// which would invalidate any iterator.
5873-
for (size_t i = 0; i < StaticDataMemberDefinitionsToEmit.size(); ++i) {
5874-
auto const *VD = StaticDataMemberDefinitionsToEmit[i];
5875-
5876-
assert(VD && VD->isStaticDataMember());
5877-
5878-
if (DeclCache.contains(VD))
5879-
continue;
5880-
5881-
EmitGlobalVariable(VD);
5882-
}
5883-
58845811
// Creating types might create further types - invalidating the current
58855812
// element and the size(), so don't cache/reference them.
58865813
for (size_t i = 0; i != ObjCInterfaceCache.size(); ++i) {

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,6 @@ class CGDebugInfo {
161161
llvm::DenseMap<const Decl *, llvm::TypedTrackingMDRef<llvm::DIDerivedType>>
162162
StaticDataMemberCache;
163163

164-
/// Keeps track of static data members for which we should emit a definition.
165-
std::vector<const VarDecl *> StaticDataMemberDefinitionsToEmit;
166-
167164
using ParamDecl2StmtTy = llvm::DenseMap<const ParmVarDecl *, const Stmt *>;
168165
using Param2DILocTy =
169166
llvm::DenseMap<const ParmVarDecl *, llvm::DILocalVariable *>;
@@ -529,9 +526,6 @@ class CGDebugInfo {
529526
/// Emit a constant global variable's debug info.
530527
void EmitGlobalVariable(const ValueDecl *VD, const APValue &Init);
531528

532-
/// Emit debug-info for a variable with a constant initializer.
533-
void EmitGlobalVariable(const VarDecl *VD);
534-
535529
/// Emit information about an external variable.
536530
void EmitExternalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
537531

clang/test/CodeGenCXX/debug-info-class.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,18 +117,11 @@ int main(int argc, char **argv) {
117117
// CHECK-NOT: identifier:
118118
// CHECK-SAME: ){{$}}
119119

120-
// CHECK: !DIGlobalVariableExpression(var: ![[HDR_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 52, DW_OP_stack_value))
121-
// CHECK: ![[HDR_VAR]] = distinct !DIGlobalVariable(name: "HdrSize",
122-
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[HDR_VAR_DECL:[0-9]+]])
123-
// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int"
124-
// CHECK: ![[HDR_VAR_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "HdrSize"
125-
126-
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A"
127-
128120
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "I"
129121
// CHECK-NOT: DIFlagFwdDecl
130122
// CHECK-SAME: ){{$}}
131123

124+
// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int"
132125
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo"
133126
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "bar"
134127
// CHECK: !DICompositeType(tag: DW_TAG_union_type, name: "baz"
@@ -194,5 +187,8 @@ int main(int argc, char **argv) {
194187
// CHECK: [[G_INNER_I]] = !DIDerivedType(tag: DW_TAG_member, name: "j"
195188
// CHECK-SAME: baseType: ![[INT]]
196189

190+
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A"
191+
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "HdrSize"
192+
197193
// CHECK: ![[EXCEPTLOC]] = !DILocation(line: 100,
198194
// CHECK: ![[RETLOC]] = !DILocation(line: 99,

clang/test/CodeGenCXX/debug-info-static-inline-member.cpp

Lines changed: 0 additions & 104 deletions
This file was deleted.

clang/test/CodeGenCXX/debug-info-static-member.cpp

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,CPP11,NOT-MS %s
1+
// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,NOT-MS %s
22
// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 -std=c++98 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,NOT-MS %s
3-
// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,CPP11,NOT-MS %s
4-
// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-5 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF5,CPP11 %s
5-
// RUN: %clangxx -target x86_64-windows-msvc -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,CPP11 %s
3+
// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,NOT-MS %s
4+
// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-5 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF5 %s
5+
// RUN: %clangxx -target x86_64-windows-msvc -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4 %s
66
// PR14471
77

88
// CHECK: @{{.*}}a{{.*}} = dso_local global i32 4, align 4, !dbg [[A:![0-9]+]]
@@ -166,15 +166,3 @@ struct y {
166166
};
167167
int y::z;
168168
}
169-
170-
// CHECK: !DIGlobalVariableExpression(var: ![[CONST_A_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
171-
// CHECK: ![[CONST_A_VAR]] = distinct !DIGlobalVariable(name: "const_a"
172-
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_A_DECL]])
173-
174-
// CPP11: !DIGlobalVariableExpression(var: ![[CONST_B_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value))
175-
// CPP11: ![[CONST_B_VAR]] = distinct !DIGlobalVariable(name: "const_b"
176-
// CPP11-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_B_DECL]])
177-
178-
// CHECK: !DIGlobalVariableExpression(var: ![[CONST_C_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18, DW_OP_stack_value))
179-
// CHECK: ![[CONST_C_VAR]] = distinct !DIGlobalVariable(name: "const_c"
180-
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_C_DECL]])

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -142,54 +142,6 @@ static bool ShouldIgnoreArtificialField(llvm::StringRef FieldName) {
142142
|| FieldName.starts_with("_vptr.");
143143
}
144144

145-
std::optional<DWARFFormValue>
146-
DWARFASTParserClang::FindConstantOnVariableDefinition(DWARFDIE die) {
147-
assert(die.Tag() == DW_TAG_member || die.Tag() == DW_TAG_variable);
148-
149-
auto *dwarf = die.GetDWARF();
150-
if (!dwarf)
151-
return {};
152-
153-
ConstString name{die.GetName()};
154-
if (!name)
155-
return {};
156-
157-
auto *CU = die.GetCU();
158-
if (!CU)
159-
return {};
160-
161-
DWARFASTParser *dwarf_ast = dwarf->GetDWARFParser(*CU);
162-
auto parent_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF(die);
163-
164-
// Make sure we populate the GetDieToVariable cache.
165-
VariableList variables;
166-
dwarf->FindGlobalVariables(name, parent_decl_ctx, UINT_MAX, variables);
167-
168-
// The cache contains the variable definition whose DW_AT_specification
169-
// points to our declaration DIE. Look up that definition using our
170-
// declaration.
171-
auto const &die_to_var = dwarf->GetDIEToVariable();
172-
auto it = die_to_var.find(die.GetDIE());
173-
if (it == die_to_var.end())
174-
return {};
175-
176-
auto var_sp = it->getSecond();
177-
assert(var_sp != nullptr);
178-
179-
if (!var_sp->GetLocationIsConstantValueData())
180-
return {};
181-
182-
auto def = dwarf->GetDIE(var_sp->GetID());
183-
auto def_attrs = def.GetAttributes();
184-
DWARFFormValue form_value;
185-
if (!def_attrs.ExtractFormValueAtIndex(
186-
def_attrs.FindAttributeIndex(llvm::dwarf::DW_AT_const_value),
187-
form_value))
188-
return {};
189-
190-
return form_value;
191-
}
192-
193145
TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
194146
const DWARFDIE &die,
195147
Log *log) {
@@ -2916,23 +2868,11 @@ void DWARFASTParserClang::CreateStaticMemberVariable(
29162868

29172869
bool unused;
29182870
// TODO: Support float/double static members as well.
2919-
if (!ct.IsIntegerOrEnumerationType(unused))
2871+
if (!ct.IsIntegerOrEnumerationType(unused) || !attrs.const_value_form)
29202872
return;
29212873

2922-
auto maybe_const_form_value = attrs.const_value_form;
2923-
2924-
// Newer versions of Clang don't emit the DW_AT_const_value
2925-
// on the declaration of an inline static data member. Instead
2926-
// it's attached to the definition DIE. If that's the case,
2927-
// try and fetch it.
2928-
if (!maybe_const_form_value) {
2929-
maybe_const_form_value = FindConstantOnVariableDefinition(die);
2930-
if (!maybe_const_form_value)
2931-
return;
2932-
}
2933-
29342874
llvm::Expected<llvm::APInt> const_value_or_err =
2935-
ExtractIntFromFormValue(ct, *maybe_const_form_value);
2875+
ExtractIntFromFormValue(ct, *attrs.const_value_form);
29362876
if (!const_value_or_err) {
29372877
LLDB_LOG_ERROR(log, const_value_or_err.takeError(),
29382878
"Failed to add const value to variable {1}: {0}",

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -413,17 +413,6 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
413413
lldb_private::CompilerType &class_clang_type,
414414
const lldb::AccessType default_accesibility,
415415
lldb_private::ClangASTImporter::LayoutInfo &layout_info);
416-
417-
/// Tries to find the definition DW_TAG_variable DIE of the the specified
418-
/// DW_TAG_member 'die'. If such definition exists, returns the
419-
/// DW_AT_const_value of that definition if available. Returns std::nullopt
420-
/// otherwise.
421-
///
422-
/// In newer versions of clang, DW_AT_const_value attributes are not attached
423-
/// to the declaration of a inline static data-member anymore, but rather on
424-
/// its definition. This function is used to locate said constant.
425-
std::optional<lldb_private::plugin::dwarf::DWARFFormValue>
426-
FindConstantOnVariableDefinition(lldb_private::plugin::dwarf::DWARFDIE die);
427416
};
428417

429418
/// Parsed form of all attributes that are relevant for type reconstruction.

0 commit comments

Comments
 (0)