Skip to content

Commit db47c9b

Browse files
authored
Merge pull request #7860 from augusto2112/dwarf-enum
[lldb] Add support for enums info lookup from DWARF
2 parents 022d128 + cb87efd commit db47c9b

File tree

3 files changed

+78
-4
lines changed

3 files changed

+78
-4
lines changed

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

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,12 @@ getTypeAndDie(TypeSystemSwiftTypeRef &ts,
5555

5656
static std::optional<swift::reflection::FieldDescriptorKind>
5757
getFieldDescriptorKindForDie(DWARFDIE &die) {
58-
if (die.Tag() == DW_TAG_structure_type)
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;
5961
return swift::reflection::FieldDescriptorKind::Struct;
60-
// TODO: handle more cases, for now we only support structs.
62+
}
63+
// TODO: handle more cases, for now we only support structs and enums.
6164
return {};
6265
}
6366

@@ -134,10 +137,20 @@ class DWARFFieldDescriptorImpl : public swift::reflection::FieldDescriptorBase {
134137
if (!die)
135138
return {};
136139

137-
// For now we only support structs.
138-
if (Kind != swift::reflection::FieldDescriptorKind::Struct)
140+
switch (Kind) {
141+
case swift::reflection::FieldDescriptorKind::Struct:
142+
return getFieldRecordsFromStruct(die, dwarf_parser);
143+
case swift::reflection::FieldDescriptorKind::Enum:
144+
return getFieldRecordsFromEnum(die, dwarf_parser);
145+
default:
146+
// TODO: handle more cases.
139147
return {};
148+
}
149+
}
140150

151+
std::vector<std::unique_ptr<swift::reflection::FieldRecordBase>>
152+
getFieldRecordsFromStruct(const DWARFDIE &die,
153+
plugin::dwarf::DWARFASTParser *dwarf_parser) {
141154
std::vector<std::unique_ptr<swift::reflection::FieldRecordBase>> fields;
142155
for (DWARFDIE child_die : die.children()) {
143156
auto tag = child_die.Tag();
@@ -159,6 +172,40 @@ class DWARFFieldDescriptorImpl : public swift::reflection::FieldDescriptorBase {
159172
}
160173
return fields;
161174
}
175+
176+
std::vector<std::unique_ptr<swift::reflection::FieldRecordBase>>
177+
getFieldRecordsFromEnum(const DWARFDIE &die,
178+
plugin::dwarf::DWARFASTParser *dwarf_parser) {
179+
std::vector<std::unique_ptr<swift::reflection::FieldRecordBase>> fields;
180+
auto variant_part = die.GetFirstChild();
181+
for (DWARFDIE child_die : variant_part.children()) {
182+
auto tag = child_die.Tag();
183+
if (tag != llvm::dwarf::DW_TAG_variant)
184+
continue;
185+
auto member = child_die.GetFirstChild();
186+
tag = member.Tag();
187+
if (tag != llvm::dwarf::DW_TAG_member)
188+
continue;
189+
const auto *member_field_name =
190+
member.GetAttributeValueAsString(llvm::dwarf::DW_AT_name, "");
191+
auto *member_type = dwarf_parser->GetTypeForDIE(member);
192+
193+
// Empty enum cases don' have a type.
194+
auto member_mangled_typename =
195+
member_type
196+
? member_type->GetForwardCompilerType().GetMangledTypeName()
197+
: ConstString();
198+
199+
// Only matters for enums, so set to false for structs.
200+
bool is_indirect_case = false;
201+
// Unused by type info construction.
202+
bool is_var = false;
203+
fields.emplace_back(std::make_unique<DWARFFieldRecordImpl>(
204+
is_indirect_case, is_var, ConstString(member_field_name),
205+
member_mangled_typename));
206+
}
207+
return fields;
208+
}
162209
};
163210
} // namespace
164211

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ def test(self):
2929
"b = 123456",
3030
],
3131
)
32+
33+
# TODO: test enums when "rdar://119343683 (Embedded Swift trivial case enum fails to link)" is solved

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,33 @@ struct B {
77
let b = 123456
88
}
99

10+
// TODO: test enums when "rdar://119343683 (Embedded Swift trivial case enum fails to link)" is solved
11+
// // Enum with a single non-payload case.
12+
// enum TrivialEnum {
13+
// case theCase
14+
// }
15+
16+
// // Enum with 2 or more non-payload cases and no payload cases
17+
// enum NonPayloadEnum {
18+
// case one
19+
// case two
20+
// }
21+
22+
// // Enum with 1 payload case and zero or more non-payload cases
23+
// enum SinglePayloadEnum {
24+
// case nonPayloadOne
25+
// case payload(B)
26+
// case nonPayloadTwo
27+
// }
28+
1029
let varB = B()
1130
let tuple = (A(), B())
31+
// let trivial = TrivialEnum.theCase
32+
// let nonPayload1 = NonPayloadEnum.one
33+
// let nonPayload2 = NonPayloadEnum.two
34+
// let singlePayload = SinglePayloadEnum.payload(B())
35+
// let emptySinglePayload = SinglePayloadEnum.nonPayloadTwo
36+
1237
// Dummy statement to set breakpoint print can't be used in embedded Swift for now.
1338
let dummy = A() // break here
1439

0 commit comments

Comments
 (0)