Skip to content

Commit 94d100f

Browse files
authored
[lldb][dwarf] Compute fully qualified names on simplified template names with DWARFTypePrinter (#112811)
This is the second half of #90008. Essentially, it replaces the work of resolving template types when we just need the qualified names with walking the DIE tree using `DWARFTypePrinter`. ### Result For an internal target, the time spent on `expr *this` for the first time reduced from 28 secs to 17 secs.
1 parent 1ced565 commit 94d100f

File tree

14 files changed

+309
-70
lines changed

14 files changed

+309
-70
lines changed

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "clang/AST/Type.h"
4646
#include "clang/Basic/Specifiers.h"
4747
#include "llvm/ADT/StringExtras.h"
48+
#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
4849
#include "llvm/Demangle/Demangle.h"
4950

5051
#include <map>
@@ -826,11 +827,11 @@ std::string DWARFASTParserClang::GetDIEClassTemplateParams(DWARFDIE die) {
826827
if (llvm::StringRef(die.GetName()).contains("<"))
827828
return {};
828829

829-
TypeSystemClang::TemplateParameterInfos template_param_infos;
830-
if (ParseTemplateParameterInfos(die, template_param_infos))
831-
return m_ast.PrintTemplateParams(template_param_infos);
832-
833-
return {};
830+
std::string name;
831+
llvm::raw_string_ostream os(name);
832+
llvm::DWARFTypePrinter<DWARFDIE> type_printer(os);
833+
type_printer.appendAndTerminateTemplateParameters(die);
834+
return name;
834835
}
835836

836837
void DWARFASTParserClang::MapDeclDIEToDefDIE(
@@ -1618,9 +1619,9 @@ void DWARFASTParserClang::GetUniqueTypeNameAndDeclaration(
16181619
case DW_TAG_structure_type:
16191620
case DW_TAG_union_type: {
16201621
if (const char *class_union_struct_name = parent_decl_ctx_die.GetName()) {
1621-
qualified_name.insert(
1622-
0, GetDIEClassTemplateParams(parent_decl_ctx_die));
16231622
qualified_name.insert(0, "::");
1623+
qualified_name.insert(0,
1624+
GetDIEClassTemplateParams(parent_decl_ctx_die));
16241625
qualified_name.insert(0, class_union_struct_name);
16251626
}
16261627
parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
@@ -1673,6 +1674,12 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
16731674
if (attrs.name) {
16741675
GetUniqueTypeNameAndDeclaration(die, cu_language, unique_typename,
16751676
unique_decl);
1677+
if (log) {
1678+
dwarf->GetObjectFile()->GetModule()->LogMessage(
1679+
log, "SymbolFileDWARF({0:p}) - {1:x16}: {2} has unique name: {3} ",
1680+
static_cast<void *>(this), die.GetID(), DW_TAG_value_to_name(tag),
1681+
unique_typename.AsCString());
1682+
}
16761683
if (UniqueDWARFASTType *unique_ast_entry_type =
16771684
dwarf->GetUniqueDWARFASTTypeMap().Find(
16781685
unique_typename, die, unique_decl, byte_size,

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ class DWARFUnit;
2424
class DWARFDebugInfoEntry;
2525
class DWARFDeclContext;
2626
class SymbolFileDWARF;
27+
class DWARFFormValue;
2728

2829
class DWARFBaseDIE {
2930
public:
31+
using DWARFFormValue = dwarf::DWARFFormValue;
3032
DWARFBaseDIE() = default;
3133

3234
DWARFBaseDIE(DWARFUnit *cu, DWARFDebugInfoEntry *die)
@@ -117,6 +119,12 @@ class DWARFBaseDIE {
117119
enum class Recurse : bool { no, yes };
118120
DWARFAttributes GetAttributes(Recurse recurse = Recurse::yes) const;
119121

122+
// The following methods use LLVM naming convension in order to be are used by
123+
// LLVM libraries.
124+
dw_tag_t getTag() const { return Tag(); }
125+
126+
const char *getShortName() const { return GetName(); }
127+
120128
protected:
121129
DWARFUnit *m_cu = nullptr;
122130
DWARFDebugInfoEntry *m_die = nullptr;

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,43 @@ bool DWARFDIE::GetDIENamesAndRanges(
572572
return false;
573573
}
574574

575+
// The following methods use LLVM naming convension in order to be are used by
576+
// LLVM libraries.
575577
llvm::iterator_range<DWARFDIE::child_iterator> DWARFDIE::children() const {
576578
return llvm::make_range(child_iterator(*this), child_iterator());
577579
}
580+
581+
DWARFDIE::child_iterator DWARFDIE::begin() const {
582+
return child_iterator(*this);
583+
}
584+
585+
DWARFDIE::child_iterator DWARFDIE::end() const { return child_iterator(); }
586+
587+
std::optional<DWARFFormValue> DWARFDIE::find(const dw_attr_t attr) const {
588+
DWARFFormValue form_value;
589+
if (m_die->GetAttributeValue(m_cu, attr, form_value, nullptr, false))
590+
return form_value;
591+
return std::nullopt;
592+
}
593+
594+
std::optional<uint64_t> DWARFDIE::getLanguage() const {
595+
if (IsValid())
596+
return m_cu->GetDWARFLanguageType();
597+
return std::nullopt;
598+
}
599+
600+
DWARFDIE DWARFDIE::resolveReferencedType(dw_attr_t attr) const {
601+
return GetReferencedDIE(attr);
602+
}
603+
604+
DWARFDIE DWARFDIE::resolveReferencedType(DWARFFormValue v) const {
605+
if (IsValid())
606+
return v.Reference();
607+
return {};
608+
}
609+
610+
DWARFDIE DWARFDIE::resolveTypeUnitReference() const {
611+
if (DWARFDIE reference = GetReferencedDIE(DW_AT_signature))
612+
return reference;
613+
return *this;
614+
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,25 @@ class DWARFDIE : public DWARFBaseDIE {
103103
std::optional<int> &call_line, std::optional<int> &call_column,
104104
DWARFExpressionList *frame_base) const;
105105

106+
// The following methods use LLVM naming convension in order to be are used by
107+
// LLVM libraries.
108+
std::optional<uint64_t> getLanguage() const;
109+
110+
DWARFDIE getParent() const { return GetParent(); }
111+
112+
DWARFDIE resolveReferencedType(dw_attr_t attr) const;
113+
114+
DWARFDIE resolveReferencedType(DWARFFormValue v) const;
115+
116+
DWARFDIE resolveTypeUnitReference() const;
117+
118+
std::optional<DWARFFormValue> find(const dw_attr_t attr) const;
119+
106120
/// The range of all the children of this DIE.
107121
llvm::iterator_range<child_iterator> children() const;
122+
123+
child_iterator begin() const;
124+
child_iterator end() const;
108125
};
109126

110127
class DWARFDIE::child_iterator

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,31 @@ uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
574574
}
575575
}
576576

577+
std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
578+
if ((!IsDataForm(m_form)) || m_form == lldb_private::dwarf::DW_FORM_sdata)
579+
return std::nullopt;
580+
return m_value.uval;
581+
}
582+
583+
std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const {
584+
if ((!IsDataForm(m_form)) ||
585+
(m_form == lldb_private::dwarf::DW_FORM_udata &&
586+
uint64_t(std::numeric_limits<int64_t>::max()) < m_value.uval))
587+
return std::nullopt;
588+
switch (m_form) {
589+
case lldb_private::dwarf::DW_FORM_data4:
590+
return int32_t(m_value.uval);
591+
case lldb_private::dwarf::DW_FORM_data2:
592+
return int16_t(m_value.uval);
593+
case lldb_private::dwarf::DW_FORM_data1:
594+
return int8_t(m_value.uval);
595+
case lldb_private::dwarf::DW_FORM_sdata:
596+
case lldb_private::dwarf::DW_FORM_data8:
597+
default:
598+
return m_value.sval;
599+
}
600+
}
601+
577602
const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
578603

579604
bool DWARFFormValue::IsBlockForm(const dw_form_t form) {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ class DWARFFormValue {
7676
void Clear();
7777
static bool FormIsSupported(dw_form_t form);
7878

79+
// The following methods use LLVM naming convension in order to be are used by
80+
// LLVM libraries.
81+
std::optional<uint64_t> getAsUnsignedConstant() const;
82+
std::optional<int64_t> getAsSignedConstant() const;
83+
const char *getAsCString() const { return AsCString(); }
84+
7985
protected:
8086
// Compile unit where m_value was located.
8187
// It may be different from compile unit where m_value refers to.

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

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "SymbolFileDWARF.h"
1010

1111
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
12+
#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
1213
#include "llvm/Support/Casting.h"
1314
#include "llvm/Support/FileUtilities.h"
1415
#include "llvm/Support/Format.h"
@@ -2810,33 +2811,14 @@ void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) {
28102811
return true; // Keep iterating over index types, language mismatch.
28112812
}
28122813

2813-
// Check the context matches
2814-
std::vector<lldb_private::CompilerContext> die_context;
2815-
if (query.GetModuleSearch())
2816-
die_context = die.GetDeclContext();
2817-
else
2818-
die_context = die.GetTypeLookupContext();
2819-
assert(!die_context.empty());
2820-
if (!query_simple.ContextMatches(die_context))
2821-
return true; // Keep iterating over index types, context mismatch.
2822-
2823-
// Try to resolve the type.
2824-
if (Type *matching_type = ResolveType(die, true, true)) {
2825-
ConstString name = matching_type->GetQualifiedName();
2826-
// We have found a type that still might not match due to template
2827-
// parameters. If we create a new TypeQuery that uses the new type's
2828-
// fully qualified name, we can find out if this type matches at all
2829-
// context levels. We can't use just the "match_simple" context
2830-
// because all template parameters were stripped off. The fully
2831-
// qualified name of the type will have the template parameters and
2832-
// will allow us to make sure it matches correctly.
2833-
TypeQuery die_query(name.GetStringRef(),
2834-
TypeQueryOptions::e_exact_match);
2835-
if (!query.ContextMatches(die_query.GetContextRef()))
2836-
return true; // Keep iterating over index types, context mismatch.
2837-
2838-
results.InsertUnique(matching_type->shared_from_this());
2839-
}
2814+
std::string qualified_name;
2815+
llvm::raw_string_ostream os(qualified_name);
2816+
llvm::DWARFTypePrinter<DWARFDIE> type_printer(os);
2817+
type_printer.appendQualifiedName(die);
2818+
TypeQuery die_query(qualified_name, e_exact_match);
2819+
if (query.ContextMatches(die_query.GetContextRef()))
2820+
if (Type *matching_type = ResolveType(die, true, true))
2821+
results.InsertUnique(matching_type->shared_from_this());
28402822
return !results.Done(query); // Keep iterating if we aren't done.
28412823
});
28422824
if (results.Done(query)) {

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,26 +1403,6 @@ static TemplateParameterList *CreateTemplateParameterList(
14031403
return template_param_list;
14041404
}
14051405

1406-
std::string TypeSystemClang::PrintTemplateParams(
1407-
const TemplateParameterInfos &template_param_infos) {
1408-
llvm::SmallVector<NamedDecl *, 8> ignore;
1409-
clang::TemplateParameterList *template_param_list =
1410-
CreateTemplateParameterList(getASTContext(), template_param_infos,
1411-
ignore);
1412-
llvm::SmallVector<clang::TemplateArgument, 2> args(
1413-
template_param_infos.GetArgs());
1414-
if (template_param_infos.hasParameterPack()) {
1415-
llvm::ArrayRef<TemplateArgument> pack_args =
1416-
template_param_infos.GetParameterPackArgs();
1417-
args.append(pack_args.begin(), pack_args.end());
1418-
}
1419-
std::string str;
1420-
llvm::raw_string_ostream os(str);
1421-
clang::printTemplateArgumentList(os, args, GetTypePrintingPolicy(),
1422-
template_param_list);
1423-
return str;
1424-
}
1425-
14261406
clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl(
14271407
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
14281408
clang::FunctionDecl *func_decl,

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,10 +1148,6 @@ class TypeSystemClang : public TypeSystem {
11481148

11491149
bool SetDeclIsForcefullyCompleted(const clang::TagDecl *td);
11501150

1151-
/// Return the template parameters (including surrounding <>) in string form.
1152-
std::string
1153-
PrintTemplateParams(const TemplateParameterInfos &template_param_infos);
1154-
11551151
private:
11561152
/// Returns the PrintingPolicy used when generating the internal type names.
11571153
/// These type names are mostly used for the formatter selection.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Test lldb is able to compute the fully qualified names on templates with
2+
// -gsimple-template-names and -fdebug-types-section.
3+
4+
// REQUIRES: lld
5+
6+
// Test against logging to see if we print the fully qualified names correctly.
7+
// RUN: %clangxx --target=x86_64-pc-linux -g -gsimple-template-names %s -o %t
8+
// RUN: %lldb %t -o "log enable dwarf comp" -o "target variable v3" -o exit | FileCheck %s --check-prefix=LOG
9+
10+
// Test that we following DW_AT_signature correctly. If not, lldb might confuse the types of v1 and v2.
11+
// RUN: %clangxx --target=x86_64-pc-linux -g -gsimple-template-names -fdebug-types-section %s -o %t
12+
// RUN: %lldb %t -o "target variable v1 v2" -o exit | FileCheck %s --check-prefix=TYPE
13+
14+
// LOG: unique name: t3<t2<int> >::t4
15+
16+
// TYPE: (t2<outer_struct1::t1<int> >) v1 = {}
17+
// TYPE-NEXT: (t2<outer_struct2::t1<int> >) v2 = {}
18+
19+
struct outer_struct1 {
20+
template <typename> struct t1 {};
21+
};
22+
23+
struct outer_struct2 {
24+
template <typename> struct t1 {};
25+
};
26+
27+
template <typename> struct t2 {};
28+
t2<outer_struct1::t1<int>> v1;
29+
t2<outer_struct2::t1<int>> v2;
30+
31+
template <typename> struct t3 {
32+
struct t4 {};
33+
};
34+
t3<t2<int>>::t4 v3;
35+
36+
int main() {}

0 commit comments

Comments
 (0)