Skip to content

Commit 521f6d9

Browse files
authored
Merge pull request #2362 from apple/lldb-Add-enum-support-to-TypeSystemSwiftTypeRef-DumpTypeValue-next
[lldb] Add enum support to TypeSystemSwiftTypeRef::DumpTypeValue
2 parents 18bbdfc + f9a2dd3 commit 521f6d9

File tree

6 files changed

+161
-50
lines changed

6 files changed

+161
-50
lines changed

lldb/include/lldb/Target/SwiftLanguageRuntime.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,12 @@ class SwiftLanguageRuntime : public LanguageRuntime {
256256
llvm::Optional<unsigned> GetNumChildren(CompilerType type,
257257
ValueObject *valobj);
258258

259+
/// Determine the enum case name for the \p data value of the enum \p type.
260+
/// This is performed using Swift reflection.
261+
llvm::Optional<std::string> GetEnumCaseName(CompilerType type,
262+
const DataExtractor &data,
263+
ExecutionContext *exe_ctx);
264+
259265
llvm::Optional<size_t> GetIndexOfChildMemberWithName(
260266
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
261267
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes);

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

Lines changed: 85 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,7 +1422,26 @@ static bool ContainsSugaredParen(swift::Demangle::NodePointer node) {
14221422

14231423
return false;
14241424
}
1425-
1425+
1426+
swift::Demangle::NodePointer
1427+
StripPrivateIDs(swift::Demangle::Demangler &dem,
1428+
swift::Demangle::NodePointer node) {
1429+
using namespace swift::Demangle;
1430+
return TypeSystemSwiftTypeRef::Transform(dem, node, [&](NodePointer node) {
1431+
if (node->getKind() != Node::Kind::PrivateDeclName ||
1432+
node->getNumChildren() != 2)
1433+
return node;
1434+
1435+
assert(node->getFirstChild()->getKind() == Node::Kind::Identifier);
1436+
assert(node->getLastChild()->getKind() == Node::Kind::Identifier);
1437+
auto *new_node = dem.createNode(Node::Kind::PrivateDeclName);
1438+
auto *ident = dem.createNodeWithAllocatedText(
1439+
Node::Kind::Identifier, node->getLastChild()->getText());
1440+
new_node->addChild(ident, dem);
1441+
return new_node;
1442+
});
1443+
}
1444+
14261445
/// Compare two swift types from different type systems by comparing their
14271446
/// (canonicalized) mangled name.
14281447
template <> bool Equivalent<CompilerType>(CompilerType l, CompilerType r) {
@@ -1443,10 +1462,10 @@ template <> bool Equivalent<CompilerType>(CompilerType l, CompilerType r) {
14431462
if (ContainsUnresolvedTypeAlias(r_node) ||
14441463
ContainsGenericTypeParameter(r_node) || ContainsSugaredParen(r_node))
14451464
return true;
1446-
if (swift::Demangle::mangleNode(
1447-
TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, l_node)) ==
1448-
swift::Demangle::mangleNode(
1449-
TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, r_node)))
1465+
if (swift::Demangle::mangleNode(StripPrivateIDs(
1466+
dem, TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, l_node))) ==
1467+
swift::Demangle::mangleNode(StripPrivateIDs(
1468+
dem, TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, r_node))))
14501469
return true;
14511470

14521471
// SwiftASTContext hardcodes some less-precise types.
@@ -2293,6 +2312,8 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
22932312
child_bitfield_bit_offset, child_is_base_class,
22942313
child_is_deref_of_parent, valobj, language_flags);
22952314
};
2315+
auto ast_num_children = m_swift_ast_context->GetNumChildren(
2316+
ReconstructType(type), omit_empty_base_classes, exe_ctx);
22962317
auto impl = [&]() -> CompilerType {
22972318
ExecutionContextScope *exe_scope = nullptr;
22982319
if (exe_ctx)
@@ -2312,9 +2333,15 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
23122333
if (llvm::StringRef(AsMangledName(type))
23132334
.endswith("sSo18NSNotificationNameaD"))
23142335
return GetTypeFromMangledTypename(ConstString("$sSo8NSStringCD"));
2315-
// FIXME: Private discriminators come out in a different format.
2316-
if (result.GetMangledTypeName().GetStringRef().count('$') > 1)
2317-
return fallback();
2336+
if (result.GetMangledTypeName().GetStringRef().count('$') > 1 &&
2337+
ast_num_children == runtime->GetNumChildren({this, type}, valobj))
2338+
// If available, prefer the AST for private types. Private
2339+
// identifiers are not ABI; the runtime returns anonymous private
2340+
// identifiers (using a '$' prefix) which cannot match identifiers
2341+
// in the AST. Because these private types can't be used in an AST
2342+
// context, prefer the AST type if available.
2343+
if (auto ast_type = fallback())
2344+
return ast_type;
23182345
return result;
23192346
}
23202347
}
@@ -2413,8 +2440,7 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
24132440
// Because the API deals out an index into a list of children we
24142441
// can't mix&match between the two typesystems if there is such a
24152442
// divergence. We'll need to replace all calls at once.
2416-
if (m_swift_ast_context->GetNumChildren(ReconstructType(type),
2417-
omit_empty_base_classes, exe_ctx) <
2443+
if (ast_num_children <
24182444
runtime->GetNumChildren({this, type}, valobj).getValueOr(0))
24192445
return impl();
24202446

@@ -2433,9 +2459,9 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
24332459
ast_child_name = suffix.str();
24342460
assert((llvm::StringRef(child_name).contains('.') ||
24352461
Equivalent(child_name, ast_child_name)));
2436-
assert((Equivalent(llvm::Optional<uint64_t>(child_byte_size),
2437-
llvm::Optional<uint64_t>(ast_child_byte_size)) ||
2438-
ast_language_flags));
2462+
assert(ast_language_flags ||
2463+
(Equivalent(llvm::Optional<uint64_t>(child_byte_size),
2464+
llvm::Optional<uint64_t>(ast_child_byte_size))));
24392465
assert(Equivalent(llvm::Optional<uint64_t>(child_byte_offset),
24402466
llvm::Optional<uint64_t>(ast_child_byte_offset)));
24412467
assert(
@@ -2775,37 +2801,14 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue(
27752801
size_t data_byte_size, uint32_t bitfield_bit_size,
27762802
uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope,
27772803
bool is_base_class) {
2778-
if (!type)
2779-
return false;
2780-
2781-
using namespace swift::Demangle;
2782-
Demangler dem;
2783-
auto *node = DemangleCanonicalType(dem, type);
2784-
auto kind = node->getKind();
2785-
2786-
switch (kind) {
2787-
case Node::Kind::Structure: {
2788-
// TODO: Handle ObjC enums masquerading as structs.
2789-
// In rare instances, a Swift `Structure` wraps an ObjC enum. An example is
2790-
// `$sSo16ComparisonResultVD`. For now, use `SwiftASTContext` to handle
2791-
// these enum structs.
2792-
auto resolved = ResolveTypeAlias(m_swift_ast_context, dem, node, true);
2793-
auto clang_type = std::get<CompilerType>(resolved);
2794-
bool is_signed;
2795-
if (!clang_type.IsEnumerationType(is_signed))
2796-
break;
2797-
LLVM_FALLTHROUGH;
2798-
}
2799-
case Node::Kind::Enum:
2800-
case Node::Kind::BoundGenericEnum:
2801-
// TODO: Add support for Enums.
2802-
return m_swift_ast_context->DumpTypeValue(
2803-
ReconstructType(type), s, format, data, data_offset, data_byte_size,
2804-
bitfield_bit_size, bitfield_bit_offset, exe_scope, is_base_class);
2805-
}
2806-
28072804
auto impl = [&]() -> bool {
2808-
switch (kind) {
2805+
if (!type)
2806+
return false;
2807+
2808+
using namespace swift::Demangle;
2809+
Demangler dem;
2810+
auto *node = DemangleCanonicalType(dem, type);
2811+
switch (node->getKind()) {
28092812
case Node::Kind::Class:
28102813
case Node::Kind::BoundGenericClass:
28112814
if (is_base_class)
@@ -2865,9 +2868,47 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue(
28652868
s, format, data, data_offset, data_byte_size, bitfield_bit_size,
28662869
bitfield_bit_offset, exe_scope, is_base_class);
28672870
}
2868-
case Node::Kind::Structure:
28692871
case Node::Kind::BoundGenericStructure:
28702872
return false;
2873+
case Node::Kind::Structure: {
2874+
// In some instances, a swift `structure` wraps an objc enum. The enum
2875+
// case needs to be handled, but structs are no-ops.
2876+
auto resolved = ResolveTypeAlias(m_swift_ast_context, dem, node, true);
2877+
auto clang_type = std::get<CompilerType>(resolved);
2878+
if (!clang_type)
2879+
return false;
2880+
2881+
bool is_signed;
2882+
if (!clang_type.IsEnumerationType(is_signed))
2883+
// The type is a clang struct, not an enum.
2884+
return false;
2885+
2886+
// The type is an enum imported from clang. Try Swift type metadata first,
2887+
// and failing that fallback to the AST.
2888+
LLVM_FALLTHROUGH;
2889+
}
2890+
case Node::Kind::Enum:
2891+
case Node::Kind::BoundGenericEnum: {
2892+
if (exe_scope)
2893+
if (auto runtime =
2894+
SwiftLanguageRuntime::Get(exe_scope->CalculateProcess())) {
2895+
ExecutionContext exe_ctx;
2896+
exe_scope->CalculateExecutionContext(exe_ctx);
2897+
if (auto case_name =
2898+
runtime->GetEnumCaseName({this, type}, data, &exe_ctx)) {
2899+
s->PutCString(*case_name);
2900+
return true;
2901+
}
2902+
}
2903+
2904+
// No result available from the runtime, fallback to the AST.
2905+
// This can happen in two cases:
2906+
// 1. MultiPayloadEnums not currently supported by Swift reflection
2907+
// 2. Some clang imported enums
2908+
return m_swift_ast_context->DumpTypeValue(
2909+
ReconstructType(type), s, format, data, data_offset, data_byte_size,
2910+
bitfield_bit_size, bitfield_bit_offset, exe_scope, is_base_class);
2911+
}
28712912
default:
28722913
assert(false && "Unhandled node kind");
28732914
LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),

lldb/source/Target/SwiftLanguageRuntime.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,13 @@ class SwiftLanguageRuntimeStub {
259259
return {};
260260
}
261261

262+
llvm::Optional<std::string> GetEnumCaseName(CompilerType type,
263+
const DataExtractor &data,
264+
ExecutionContext *exe_ctx) {
265+
STUB_LOG();
266+
return {};
267+
}
268+
262269
llvm::Optional<size_t> GetIndexOfChildMemberWithName(
263270
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
264271
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
@@ -2168,6 +2175,11 @@ SwiftLanguageRuntime::GetNumChildren(CompilerType type, ValueObject *valobj) {
21682175
FORWARD(GetNumChildren, type, valobj);
21692176
}
21702177

2178+
llvm::Optional<std::string> SwiftLanguageRuntime::GetEnumCaseName(
2179+
CompilerType type, const DataExtractor &data, ExecutionContext *exe_ctx) {
2180+
FORWARD(GetEnumCaseName, type, data, exe_ctx);
2181+
}
2182+
21712183
llvm::Optional<size_t> SwiftLanguageRuntime::GetIndexOfChildMemberWithName(
21722184
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
21732185
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {

lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
292292
} else {
293293
*result = 0;
294294
}
295-
break;
295+
return true;
296296
}
297297
case DLQ_GetPointerSize: {
298298
auto result = static_cast<uint8_t *>(outBuffer);
@@ -304,6 +304,15 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
304304
*result = m_process.GetAddressByteSize(); // FIXME: sizeof(size_t)
305305
return true;
306306
}
307+
case DLQ_GetLeastValidPointerValue: {
308+
auto *result = (uint64_t *)outBuffer;
309+
auto &triple = m_process.GetTarget().GetArchitecture().GetTriple();
310+
if (triple.isOSDarwin() && triple.isArch64Bit())
311+
*result = 0x100000000;
312+
else
313+
*result = 0x1000;
314+
return true;
315+
}
307316
}
308317

309318
return false;
@@ -381,8 +390,8 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
381390
uint64_t size) override {
382391
if (m_local_buffer) {
383392
auto addr = address.getAddressData();
384-
if (addr >= m_local_buffer &&
385-
addr + size <= m_local_buffer + m_local_buffer_size) {
393+
if (addr >= *m_local_buffer &&
394+
addr + size <= *m_local_buffer + m_local_buffer_size) {
386395
// If this crashes, the assumptions stated in
387396
// GetDynamicTypeAndAddress_Protocol() most likely no longer
388397
// hold.
@@ -472,15 +481,15 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
472481

473482
void popLocalBuffer() {
474483
lldbassert(m_local_buffer);
475-
m_local_buffer = 0;
484+
m_local_buffer.reset();
476485
m_local_buffer_size = 0;
477486
}
478487

479488
private:
480489
Process &m_process;
481490
size_t m_max_read_amount;
482491

483-
uint64_t m_local_buffer = 0;
492+
llvm::Optional<uint64_t> m_local_buffer;
484493
uint64_t m_local_buffer_size = 0;
485494
};
486495

@@ -1217,6 +1226,45 @@ findFieldWithName(const std::vector<swift::reflection::FieldInfo> &fields,
12171226
return child_indexes.size();
12181227
}
12191228

1229+
static llvm::Optional<std::string>
1230+
GetMultiPayloadEnumCaseName(const swift::reflection::EnumTypeInfo *eti,
1231+
const DataExtractor &data) {
1232+
assert(eti->getEnumKind() == swift::reflection::EnumKind::MultiPayloadEnum);
1233+
auto payload_capacity = eti->getPayloadSize();
1234+
if (data.GetByteSize() == payload_capacity + 1) {
1235+
auto tag = data.GetDataStart()[payload_capacity];
1236+
const auto &cases = eti->getCases();
1237+
if (tag >= 0 && tag < cases.size())
1238+
return cases[tag].Name;
1239+
}
1240+
return {};
1241+
}
1242+
1243+
llvm::Optional<std::string> SwiftLanguageRuntimeImpl::GetEnumCaseName(
1244+
CompilerType type, const DataExtractor &data, ExecutionContext *exe_ctx) {
1245+
using namespace swift::reflection;
1246+
using namespace swift::remote;
1247+
auto *ti = GetTypeInfo(type, exe_ctx->GetFramePtr());
1248+
if (ti->getKind() != TypeInfoKind::Enum)
1249+
return {};
1250+
1251+
auto *eti = llvm::cast<EnumTypeInfo>(ti);
1252+
PushLocalBuffer((int64_t)data.GetDataStart(), data.GetByteSize());
1253+
auto defer = llvm::make_scope_exit([&] { PopLocalBuffer(); });
1254+
RemoteAddress addr(data.GetDataStart());
1255+
int case_index;
1256+
if (eti->projectEnumValue(*GetMemoryReader(), addr, &case_index))
1257+
return eti->getCases()[case_index].Name;
1258+
1259+
// Temporary workaround.
1260+
if (eti->getEnumKind() == EnumKind::MultiPayloadEnum &&
1261+
type.GetMangledTypeName().GetStringRef().startswith(
1262+
"$s10Foundation9IndexPathV7Storage10"))
1263+
return GetMultiPayloadEnumCaseName(eti, data);
1264+
1265+
return {};
1266+
}
1267+
12201268
llvm::Optional<size_t> SwiftLanguageRuntimeImpl::GetIndexOfChildMemberWithName(
12211269
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
12221270
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {

lldb/source/Target/SwiftLanguageRuntimeImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ class SwiftLanguageRuntimeImpl {
123123
llvm::Optional<unsigned> GetNumFields(CompilerType type,
124124
ExecutionContext *exe_ctx);
125125

126+
llvm::Optional<std::string> GetEnumCaseName(CompilerType type,
127+
const DataExtractor &data,
128+
ExecutionContext *exe_ctx);
129+
126130
llvm::Optional<size_t> GetIndexOfChildMemberWithName(
127131
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
128132
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes);

lldb/test/API/lang/swift/foundation_value_types/indexpath/TestSwiftFoundationTypeIndexPath.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
from lldbsuite.test.decorators import *
1414

1515
lldbinline.MakeInlineTest(__file__, globals(),
16-
decorators=[swiftTest,skipIf(oslist=['windows'])])
16+
decorators=[swiftTest,skipIf(oslist=['windows', 'linux'])])

0 commit comments

Comments
 (0)