Skip to content

Commit 96e8d7c

Browse files
authored
Merge pull request llvm#8112 from augusto2112/class-dwarf
[lldb] Add support for class info lookup from DWARF
2 parents d70bd0e + ff077c5 commit 96e8d7c

File tree

6 files changed

+136
-33
lines changed

6 files changed

+136
-33
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,13 @@ class DWARFASTParserSwift : public lldb_private::plugin::dwarf::DWARFASTParser,
8989
std::unique_ptr<swift::reflection::BuiltinTypeDescriptorBase>
9090
getBuiltinTypeDescriptor(const swift::reflection::TypeRef *TR) override;
9191

92+
private:
93+
/// Returns the canonical demangle tree of a die's type.
94+
NodePointer GetCanonicalDemangleTree(DWARFDIE &die);
95+
9296
protected:
9397
lldb_private::TypeSystemSwiftTypeRef &m_swift_typesystem;
98+
swift::Demangle::Demangler m_dem;
9499
};
95100

96101
#endif // SymbolFileDWARF_DWARFASTParserSwift_h_

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

Lines changed: 87 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@
1313
//
1414
//===----------------------------------------------------------------------===//
1515

16+
#include <sstream>
17+
18+
#include "DWARFDebugInfo.h"
1619
#include "DWARFASTParserSwift.h"
1720

1821
#include "DWARFDIE.h"
19-
#include "DWARFDebugInfo.h"
2022

21-
#include "Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h"
2223
#include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h"
23-
2424
#include "swift/RemoteInspection/TypeLowering.h"
2525

26+
#include "lldb/Utility/LLDBLog.h"
27+
#include "lldb/Utility/Log.h"
28+
#include "lldb/Target/Target.h"
2629

2730
using namespace lldb;
2831
using namespace lldb_private;
@@ -38,30 +41,46 @@ getTypeAndDie(TypeSystemSwiftTypeRef &ts,
3841
swift::Demangle::Demangler dem;
3942
swift::Demangle::NodePointer node = TR->getDemangling(dem);
4043
auto type = ts.RemangleAsType(dem, node);
41-
if (!type)
44+
if (!type) {
45+
if (auto log = GetLog(LLDBLog::Types)) {
46+
std::stringstream ss;
47+
TR->dump(ss);
48+
LLDB_LOG(log, "Could not find type for typeref: {0}", ss.str());
49+
}
4250
return {};
51+
}
4352

4453
auto *dwarf = llvm::cast_or_null<SymbolFileDWARF>(ts.GetSymbolFile());
4554
if (!dwarf)
4655
return {};
4756
auto lldb_type = ts.FindTypeInModule(type.GetOpaqueQualType());
48-
if (!lldb_type)
57+
if (!lldb_type) {
4958
// TODO: for embedded Swift this is fine but consult other modules here for
5059
// general case?
60+
LLDB_LOGV(GetLog(LLDBLog::Types), "Could not find type {0} in module",
61+
type.GetMangledTypeName());
5162
return {};
63+
}
5264
auto die = dwarf->GetDIE(lldb_type->GetID());
5365
return {{type, die}};
5466
}
5567

5668
static std::optional<swift::reflection::FieldDescriptorKind>
57-
getFieldDescriptorKindForDie(DWARFDIE &die) {
58-
if (die.Tag() == DW_TAG_structure_type) {
59-
if (die.HasChildren() && die.GetFirstChild().Tag() == llvm::dwarf::DW_TAG_variant_part)
60-
return swift::reflection::FieldDescriptorKind::Enum;
69+
getFieldDescriptorKindForDie(CompilerType type) {
70+
auto type_class = type.GetTypeClass();
71+
switch (type_class) {
72+
case lldb::eTypeClassClass:
73+
return swift::reflection::FieldDescriptorKind::Class;
74+
case lldb::eTypeClassStruct:
6175
return swift::reflection::FieldDescriptorKind::Struct;
76+
case lldb::eTypeClassEnumeration:
77+
return swift::reflection::FieldDescriptorKind::Enum;
78+
default:
79+
LLDB_LOG(GetLog(LLDBLog::Types),
80+
"Could not determine file descriptor kind for type: {0}",
81+
type.GetMangledTypeName());
82+
return {};
6283
}
63-
// TODO: handle more cases, for now we only support structs and enums.
64-
return {};
6584
}
6685

6786
namespace {
@@ -108,20 +127,23 @@ class DWARFFieldDescriptorImpl : public swift::reflection::FieldDescriptorBase {
108127
TypeSystemSwiftTypeRef &m_type_system;
109128
ConstString m_mangled_name;
110129
DIERef m_die_ref;
130+
NodePointer m_superclass_node;
111131

112132
public:
113133
DWARFFieldDescriptorImpl(swift::reflection::FieldDescriptorKind kind,
114-
bool has_superclass,
134+
NodePointer superclass_node,
115135
TypeSystemSwiftTypeRef &type_system,
116136
ConstString mangled_name, DIERef die_ref)
117-
: swift::reflection::FieldDescriptorBase(kind, has_superclass),
137+
: swift::reflection::FieldDescriptorBase(kind,
138+
superclass_node != nullptr),
118139
m_type_system(type_system), m_mangled_name(mangled_name),
119-
m_die_ref(die_ref) {}
140+
m_die_ref(die_ref), m_superclass_node(superclass_node) {}
120141

121142
~DWARFFieldDescriptorImpl() override = default;
122143

123-
// TODO: implement this.
124-
swift::Demangle::NodePointer demangleSuperclass() override { return nullptr; }
144+
swift::Demangle::NodePointer demangleSuperclass() override {
145+
return m_superclass_node;
146+
}
125147

126148
std::vector<std::unique_ptr<swift::reflection::FieldRecordBase>>
127149
getFieldRecords() override {
@@ -139,17 +161,22 @@ class DWARFFieldDescriptorImpl : public swift::reflection::FieldDescriptorBase {
139161

140162
switch (Kind) {
141163
case swift::reflection::FieldDescriptorKind::Struct:
142-
return getFieldRecordsFromStruct(die, dwarf_parser);
164+
case swift::reflection::FieldDescriptorKind::Class:
165+
return getFieldRecordsFromStructOrClass(die, dwarf_parser);
143166
case swift::reflection::FieldDescriptorKind::Enum:
144167
return getFieldRecordsFromEnum(die, dwarf_parser);
145168
default:
146169
// TODO: handle more cases.
170+
LLDB_LOG(GetLog(LLDBLog::Types),
171+
"Trying to get field records of unexpected kind: {0}",
172+
(uint8_t)Kind);
173+
assert(false && "Trying to get field records of unexpected kind");
147174
return {};
148175
}
149176
}
150177

151178
std::vector<std::unique_ptr<swift::reflection::FieldRecordBase>>
152-
getFieldRecordsFromStruct(const DWARFDIE &die,
179+
getFieldRecordsFromStructOrClass(const DWARFDIE &die,
153180
plugin::dwarf::DWARFASTParser *dwarf_parser) {
154181
std::vector<std::unique_ptr<swift::reflection::FieldRecordBase>> fields;
155182
for (DWARFDIE child_die : die.children()) {
@@ -221,12 +248,14 @@ DWARFASTParserSwift::getBuiltinTypeDescriptor(
221248
return nullptr;
222249
auto &[type, die] = *pair;
223250

224-
if (die.Tag() == llvm::dwarf::DW_TAG_structure_type) {
225-
auto child = die.GetFirstChild();
226-
if (child.Tag() != llvm::dwarf::DW_TAG_variant_part)
251+
if (!TypeSystemSwiftTypeRef::IsBuiltinType(type)) {
252+
if (die.Tag() == llvm::dwarf::DW_TAG_structure_type) {
253+
auto child = die.GetFirstChild();
254+
if (child.Tag() != llvm::dwarf::DW_TAG_variant_part)
255+
return nullptr;
256+
} else if (die.Tag() != llvm::dwarf::DW_TAG_base_type)
227257
return nullptr;
228-
} else if (die.Tag() != llvm::dwarf::DW_TAG_base_type)
229-
return nullptr;
258+
}
230259

231260
auto byte_size =
232261
die.GetAttributeValueAsUnsigned(DW_AT_byte_size, LLDB_INVALID_ADDRESS);
@@ -249,6 +278,35 @@ DWARFASTParserSwift::getBuiltinTypeDescriptor(
249278
type.GetMangledTypeName());
250279
}
251280

281+
namespace {
282+
DWARFDIE FindSuperClassDIE(DWARFDIE &die) {
283+
const auto inheritance_die_it =
284+
llvm::find_if(die.children(), [&](const DWARFDIE &child_die) {
285+
return child_die.Tag() == llvm::dwarf::DW_TAG_inheritance;
286+
});
287+
288+
if (inheritance_die_it == die.children().end())
289+
return {};
290+
291+
auto inheritance_die = *inheritance_die_it;
292+
const auto superclass_type_die =
293+
inheritance_die.GetAttributeValueAsReferenceDIE(llvm::dwarf::DW_AT_type);
294+
return superclass_type_die;
295+
}
296+
} // namespace
297+
298+
NodePointer DWARFASTParserSwift::GetCanonicalDemangleTree(DWARFDIE &die) {
299+
const auto name = StringRef(
300+
die.GetAttributeValueAsString(llvm::dwarf::DW_AT_linkage_name, ""));
301+
302+
if (name.empty())
303+
return nullptr;
304+
305+
auto *node =
306+
m_swift_typesystem.GetCanonicalDemangleTree(m_dem, name);
307+
return node;
308+
}
309+
252310
std::unique_ptr<swift::reflection::FieldDescriptorBase>
253311
DWARFASTParserSwift::getFieldDescriptor(const swift::reflection::TypeRef *TR) {
254312
if (!Target::GetGlobalProperties().GetSwiftEnableFullDwarfDebugging())
@@ -260,12 +318,14 @@ DWARFASTParserSwift::getFieldDescriptor(const swift::reflection::TypeRef *TR) {
260318
auto [type, die] = *pair;
261319
if (!die)
262320
return nullptr;
263-
auto kind = getFieldDescriptorKindForDie(die);
321+
auto kind = getFieldDescriptorKindForDie(type);
264322
if (!kind)
265323
return nullptr;
266-
// TODO: encode this in DWARF, maybe as a DW_AT_containing_type?
267-
bool has_superclass = false;
324+
325+
DWARFDIE superclass_die = FindSuperClassDIE(die);
326+
NodePointer superclass_pointer = GetCanonicalDemangleTree(superclass_die);
327+
268328
return std::make_unique<DWARFFieldDescriptorImpl>(
269-
*kind, has_superclass, m_swift_typesystem, type.GetMangledTypeName(),
329+
*kind, superclass_pointer, m_swift_typesystem, type.GetMangledTypeName(),
270330
*die.GetDIERef());
271331
}

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,17 @@ GetNominal(swift::Demangle::Demangler &dem, swift::Demangle::NodePointer node) {
474474
return {};
475475
}
476476

477+
bool
478+
TypeSystemSwiftTypeRef::IsBuiltinType(CompilerType type) {
479+
assert(type.GetTypeSystem().isa_and_nonnull<TypeSystemSwift>() &&
480+
"Unexpected type system!");
481+
Demangler dem;
482+
auto *node = GetDemangledType(dem, type.GetMangledTypeName());
483+
if (!node)
484+
return false;
485+
return node->getKind() == Node::Kind::BuiltinTypeName;
486+
}
487+
477488
/// Return a pair of module name and type name, given a mangled name.
478489
static llvm::Optional<std::pair<StringRef, StringRef>>
479490
GetNominal(llvm::StringRef mangled_name, swift::Demangle::Demangler &dem) {
@@ -1830,7 +1841,8 @@ TypeSystemSwiftTypeRef::FindTypeInModule(opaque_compiler_type_t opaque_type) {
18301841
ConstString module(module_type->first);
18311842
ConstString type(module_type->second);
18321843
llvm::SmallVector<CompilerContext, 2> decl_context;
1833-
decl_context.push_back({CompilerContextKind::Module, module});
1844+
if (!module.IsEmpty())
1845+
decl_context.push_back({CompilerContextKind::Module, module});
18341846
decl_context.push_back({CompilerContextKind::AnyType, type});
18351847

18361848
TypeQuery query(decl_context, TypeQueryOptions::e_find_one |
@@ -3329,6 +3341,12 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
33293341
return impl();
33303342
#ifndef NDEBUG
33313343
auto result = impl();
3344+
if (ShouldSkipValidation(type))
3345+
return result;
3346+
3347+
if (!ModuleList::GetGlobalModuleListProperties().GetSwiftValidateTypeSystem())
3348+
return result;
3349+
33323350
// FIXME:
33333351
// No point comparing the results if the reflection data has more
33343352
// information. There's a nasty chicken & egg problem buried here:
@@ -3339,8 +3357,6 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
33393357
runtime->GetNumChildren({weak_from_this(), type}, exe_scope)
33403358
.value_or(0))
33413359
return result;
3342-
if (ShouldSkipValidation(type))
3343-
return result;
33443360
// When the child compiler type is an anonymous clang type,
33453361
// GetChildCompilerTypeAtIndex will return the clang type directly. In this
33463362
// case validation will fail as it can't correctly compare the mangled
@@ -3359,9 +3375,6 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
33593375
bool ast_child_is_deref_of_parent = false;
33603376
uint64_t ast_language_flags = 0;
33613377
auto defer = llvm::make_scope_exit([&] {
3362-
if (!ModuleList::GetGlobalModuleListProperties()
3363-
.GetSwiftValidateTypeSystem())
3364-
return;
33653378
// Ignore if SwiftASTContext got no result.
33663379
if (ast_child_name.empty())
33673380
return;

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
318318
llvm::Optional<TupleElement>
319319
GetTupleElement(lldb::opaque_compiler_type_t type, size_t idx);
320320

321+
/// Returns true if the compiler type is a Builtin (belongs to the "Builtin
322+
/// module").
323+
static bool IsBuiltinType(CompilerType type);
324+
321325
/// Creates a GenericTypeParamType with the desired depth and index.
322326
CompilerType CreateGenericTypeParamType(unsigned int depth,
323327
unsigned int index) override;

lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,8 @@ def test(self):
3131
)
3232

3333
# TODO: test enums when "rdar://119343683 (Embedded Swift trivial case enum fails to link)" is solved
34+
35+
self.expect("frame variable sup", substrs=["Sup) sup = ", "supField = 42"])
36+
self.expect("frame variable sub", substrs=["Sub) sub = ", "Sup = {", "supField = 42", "subField = {", "a = (field = 4.2000000000000002", "b = 123456"])
37+
self.expect("frame variable subSub", substrs=["SubSub) subSub =", "a.Sub = {", "a.Sup = {", "supField = 42", "subField = {", "a = (field = 4.2000000000000002", "b = 123456", "subSubField = (field = 4.2000000000000002)"])
38+

lldb/test/API/lang/swift/embedded/frame_variable/main.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,29 @@ struct B {
2626
// case nonPayloadTwo
2727
// }
2828

29+
class Sup {
30+
var supField: Int8 = 42
31+
}
32+
33+
class Sub: Sup {
34+
var subField = B()
35+
}
36+
37+
class SubSub: Sub {
38+
var subSubField = A()
39+
}
40+
2941
let varB = B()
3042
let tuple = (A(), B())
3143
// let trivial = TrivialEnum.theCase
3244
// let nonPayload1 = NonPayloadEnum.one
3345
// let nonPayload2 = NonPayloadEnum.two
3446
// let singlePayload = SinglePayloadEnum.payload(B())
3547
// let emptySinglePayload = SinglePayloadEnum.nonPayloadTwo
48+
let sup = Sup()
49+
let sub = Sub()
50+
let subSub = SubSub()
51+
let sup2: Sup = SubSub()
3652

3753
// Dummy statement to set breakpoint print can't be used in embedded Swift for now.
3854
let dummy = A() // break here

0 commit comments

Comments
 (0)