Skip to content

Commit b428d0d

Browse files
authored
Merge pull request #2330 from apple/lldb-Add-enum-support-to-TypeSystemSwiftTypeRef-DumpTypeValue
[lldb] Add enum support to TypeSystemSwiftTypeRef::DumpTypeValue
2 parents 41c42bb + 3dad37a commit b428d0d

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.
@@ -2296,6 +2315,8 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
22962315
child_bitfield_bit_offset, child_is_base_class,
22972316
child_is_deref_of_parent, valobj, language_flags);
22982317
};
2318+
auto ast_num_children = m_swift_ast_context->GetNumChildren(
2319+
ReconstructType(type), omit_empty_base_classes, exe_ctx);
22992320
auto impl = [&]() -> CompilerType {
23002321
ExecutionContextScope *exe_scope = nullptr;
23012322
if (exe_ctx)
@@ -2315,9 +2336,15 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
23152336
if (llvm::StringRef(AsMangledName(type))
23162337
.endswith("sSo18NSNotificationNameaD"))
23172338
return GetTypeFromMangledTypename(ConstString("$sSo8NSStringCD"));
2318-
// FIXME: Private discriminators come out in a different format.
2319-
if (result.GetMangledTypeName().GetStringRef().count('$') > 1)
2320-
return fallback();
2339+
if (result.GetMangledTypeName().GetStringRef().count('$') > 1 &&
2340+
ast_num_children == runtime->GetNumChildren({this, type}, valobj))
2341+
// If available, prefer the AST for private types. Private
2342+
// identifiers are not ABI; the runtime returns anonymous private
2343+
// identifiers (using a '$' prefix) which cannot match identifiers
2344+
// in the AST. Because these private types can't be used in an AST
2345+
// context, prefer the AST type if available.
2346+
if (auto ast_type = fallback())
2347+
return ast_type;
23212348
return result;
23222349
}
23232350
}
@@ -2416,8 +2443,7 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
24162443
// Because the API deals out an index into a list of children we
24172444
// can't mix&match between the two typesystems if there is such a
24182445
// divergence. We'll need to replace all calls at once.
2419-
if (m_swift_ast_context->GetNumChildren(ReconstructType(type),
2420-
omit_empty_base_classes, exe_ctx) <
2446+
if (ast_num_children <
24212447
runtime->GetNumChildren({this, type}, valobj).getValueOr(0))
24222448
return impl();
24232449

@@ -2436,9 +2462,9 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
24362462
ast_child_name = suffix.str();
24372463
assert((llvm::StringRef(child_name).contains('.') ||
24382464
Equivalent(child_name, ast_child_name)));
2439-
assert((Equivalent(llvm::Optional<uint64_t>(child_byte_size),
2440-
llvm::Optional<uint64_t>(ast_child_byte_size)) ||
2441-
ast_language_flags));
2465+
assert(ast_language_flags ||
2466+
(Equivalent(llvm::Optional<uint64_t>(child_byte_size),
2467+
llvm::Optional<uint64_t>(ast_child_byte_size))));
24422468
assert(Equivalent(llvm::Optional<uint64_t>(child_byte_offset),
24432469
llvm::Optional<uint64_t>(ast_child_byte_offset)));
24442470
assert(
@@ -2778,37 +2804,14 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue(
27782804
size_t data_byte_size, uint32_t bitfield_bit_size,
27792805
uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope,
27802806
bool is_base_class) {
2781-
if (!type)
2782-
return false;
2783-
2784-
using namespace swift::Demangle;
2785-
Demangler dem;
2786-
auto *node = DemangleCanonicalType(dem, type);
2787-
auto kind = node->getKind();
2788-
2789-
switch (kind) {
2790-
case Node::Kind::Structure: {
2791-
// TODO: Handle ObjC enums masquerading as structs.
2792-
// In rare instances, a Swift `Structure` wraps an ObjC enum. An example is
2793-
// `$sSo16ComparisonResultVD`. For now, use `SwiftASTContext` to handle
2794-
// these enum structs.
2795-
auto resolved = ResolveTypeAlias(m_swift_ast_context, dem, node, true);
2796-
auto clang_type = std::get<CompilerType>(resolved);
2797-
bool is_signed;
2798-
if (!clang_type.IsEnumerationType(is_signed))
2799-
break;
2800-
LLVM_FALLTHROUGH;
2801-
}
2802-
case Node::Kind::Enum:
2803-
case Node::Kind::BoundGenericEnum:
2804-
// TODO: Add support for Enums.
2805-
return m_swift_ast_context->DumpTypeValue(
2806-
ReconstructType(type), s, format, data, data_offset, data_byte_size,
2807-
bitfield_bit_size, bitfield_bit_offset, exe_scope, is_base_class);
2808-
}
2809-
28102807
auto impl = [&]() -> bool {
2811-
switch (kind) {
2808+
if (!type)
2809+
return false;
2810+
2811+
using namespace swift::Demangle;
2812+
Demangler dem;
2813+
auto *node = DemangleCanonicalType(dem, type);
2814+
switch (node->getKind()) {
28122815
case Node::Kind::Class:
28132816
case Node::Kind::BoundGenericClass:
28142817
if (is_base_class)
@@ -2868,9 +2871,47 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue(
28682871
s, format, data, data_offset, data_byte_size, bitfield_bit_size,
28692872
bitfield_bit_offset, exe_scope, is_base_class);
28702873
}
2871-
case Node::Kind::Structure:
28722874
case Node::Kind::BoundGenericStructure:
28732875
return false;
2876+
case Node::Kind::Structure: {
2877+
// In some instances, a swift `structure` wraps an objc enum. The enum
2878+
// case needs to be handled, but structs are no-ops.
2879+
auto resolved = ResolveTypeAlias(m_swift_ast_context, dem, node, true);
2880+
auto clang_type = std::get<CompilerType>(resolved);
2881+
if (!clang_type)
2882+
return false;
2883+
2884+
bool is_signed;
2885+
if (!clang_type.IsEnumerationType(is_signed))
2886+
// The type is a clang struct, not an enum.
2887+
return false;
2888+
2889+
// The type is an enum imported from clang. Try Swift type metadata first,
2890+
// and failing that fallback to the AST.
2891+
LLVM_FALLTHROUGH;
2892+
}
2893+
case Node::Kind::Enum:
2894+
case Node::Kind::BoundGenericEnum: {
2895+
if (exe_scope)
2896+
if (auto runtime =
2897+
SwiftLanguageRuntime::Get(exe_scope->CalculateProcess())) {
2898+
ExecutionContext exe_ctx;
2899+
exe_scope->CalculateExecutionContext(exe_ctx);
2900+
if (auto case_name =
2901+
runtime->GetEnumCaseName({this, type}, data, &exe_ctx)) {
2902+
s->PutCString(*case_name);
2903+
return true;
2904+
}
2905+
}
2906+
2907+
// No result available from the runtime, fallback to the AST.
2908+
// This can happen in two cases:
2909+
// 1. MultiPayloadEnums not currently supported by Swift reflection
2910+
// 2. Some clang imported enums
2911+
return m_swift_ast_context->DumpTypeValue(
2912+
ReconstructType(type), s, format, data, data_offset, data_byte_size,
2913+
bitfield_bit_size, bitfield_bit_offset, exe_scope, is_base_class);
2914+
}
28742915
default:
28752916
assert(false && "Unhandled node kind");
28762917
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

@@ -1219,6 +1228,45 @@ findFieldWithName(const std::vector<swift::reflection::FieldInfo> &fields,
12191228
return child_indexes.size();
12201229
}
12211230

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