Skip to content

Commit 95ec562

Browse files
committed
Add interface for lookup of externally stored field descriptors
This is a follow up patch that wraps field descriptors and field records in an abstract interface, and allows descriptor finders to look them up.
1 parent 3d9533d commit 95ec562

File tree

4 files changed

+154
-29
lines changed

4 files changed

+154
-29
lines changed

include/swift/RemoteInspection/DescriptorFinder.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#ifndef SWIFT_REFLECTION_DESCRIPTOR_FINDER_H
1414
#define SWIFT_REFLECTION_DESCRIPTOR_FINDER_H
1515

16+
#include "swift/Demangling/Demangle.h"
17+
#include "swift/RemoteInspection/Records.h"
1618
#include "llvm/ADT/StringRef.h"
1719

1820
namespace swift {
@@ -39,13 +41,69 @@ struct BuiltinTypeDescriptorBase {
3941
virtual llvm::StringRef getMangledTypeName() = 0;
4042
};
4143

44+
/// An abstract interface for a field record.
45+
struct FieldRecordBase {
46+
const bool IsIndirectCase;
47+
const bool IsVar;
48+
const bool HasMangledTypeName;
49+
50+
FieldRecordBase(bool IsIndirectCase, bool IsVar,
51+
bool HasMangledTypeName)
52+
: IsIndirectCase(IsIndirectCase), IsVar(IsVar),
53+
HasMangledTypeName(HasMangledTypeName) {}
54+
55+
virtual ~FieldRecordBase(){};
56+
57+
virtual llvm::StringRef getFieldName() = 0;
58+
virtual Demangle::Node *demangleMangledTypeName() = 0;
59+
};
60+
61+
/// An abstract interface for a field descriptor.
62+
struct FieldDescriptorBase {
63+
const FieldDescriptorKind Kind;
64+
const bool HasSuperClass;
65+
66+
FieldDescriptorBase(FieldDescriptorKind Kind, bool HasSuperClass)
67+
: Kind(Kind), HasSuperClass(HasSuperClass) {}
68+
69+
bool isEnum() const {
70+
return (Kind == FieldDescriptorKind::Enum ||
71+
Kind == FieldDescriptorKind::MultiPayloadEnum);
72+
}
73+
74+
bool isClass() const {
75+
return (Kind == FieldDescriptorKind::Class ||
76+
Kind == FieldDescriptorKind::ObjCClass);
77+
}
78+
79+
bool isProtocol() const {
80+
return (Kind == FieldDescriptorKind::Protocol ||
81+
Kind == FieldDescriptorKind::ClassProtocol ||
82+
Kind == FieldDescriptorKind::ObjCProtocol);
83+
}
84+
85+
bool isStruct() const {
86+
return Kind == FieldDescriptorKind::Struct;
87+
}
88+
89+
virtual ~FieldDescriptorBase(){};
90+
91+
virtual Demangle::Node *demangleSuperclass() = 0;
92+
virtual std::vector<std::unique_ptr<FieldRecordBase>>
93+
getFieldRecords() = 0;
94+
};
95+
4296
/// Interface for finding type descriptors. Implementors may provide descriptors
4397
/// that live inside or outside reflection metadata.
4498
struct DescriptorFinder {
4599
virtual ~DescriptorFinder(){};
46100

47101
virtual std::unique_ptr<BuiltinTypeDescriptorBase>
48102
getBuiltinTypeDescriptor(const TypeRef *TR) = 0;
103+
104+
105+
virtual std::unique_ptr<FieldDescriptorBase>
106+
getFieldDescriptor(const TypeRef *TR) = 0;
49107
};
50108

51109
} // namespace reflection

include/swift/RemoteInspection/TypeRefBuilder.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,8 @@ class TypeRefBuilder {
476476
return ReflectionInfos;
477477
}
478478

479-
/// Load unsubstituted field types for a nominal type.
480-
RemoteRef<FieldDescriptor> getFieldTypeInfo(const TypeRef *TR);
479+
std::unique_ptr<FieldDescriptorBase>
480+
getFieldDescriptor(const TypeRef *TR) override;
481481

482482
std::unique_ptr<BuiltinTypeDescriptorBase>
483483
getBuiltinTypeDescriptor(const TypeRef *TR) override;
@@ -512,6 +512,9 @@ class TypeRefBuilder {
512512
/// Get the primitive type lowering for a builtin type.
513513
RemoteRef<BuiltinTypeDescriptor> getBuiltinTypeInfo(const TypeRef *TR);
514514

515+
/// Load unsubstituted field types for a nominal type.
516+
RemoteRef<FieldDescriptor> getFieldTypeInfo(const TypeRef *TR);
517+
515518
void populateFieldTypeInfoCacheWithReflectionAtIndex(size_t Index);
516519

517520
llvm::Optional<RemoteRef<FieldDescriptor>>
@@ -1532,12 +1535,11 @@ class TypeRefBuilder {
15321535
}
15331536
const TypeRef *lookupSuperclass(const TypeRef *TR);
15341537

1535-
RemoteRef<FieldDescriptor> getFieldTypeInfo(const TypeRef *TR) {
1536-
return RDF.getFieldTypeInfo(TR);
1537-
}
1538+
std::unique_ptr<FieldDescriptorBase>
1539+
getFieldDescriptor(const TypeRef *TR);
15381540

15391541
/// Get the parsed and substituted field types for a nominal type.
1540-
bool getFieldTypeRefs(const TypeRef *TR, RemoteRef<FieldDescriptor> FD,
1542+
bool getFieldTypeRefs(const TypeRef *TR, FieldDescriptorBase &FD,
15411543
remote::TypeInfoProvider *ExternalTypeInfo,
15421544
std::vector<FieldTypeInfo> &Fields);
15431545

stdlib/public/RemoteInspection/TypeLowering.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,7 +1332,7 @@ class ExistentialTypeInfoBuilder {
13321332
continue;
13331333
}
13341334

1335-
auto FD = TC.getBuilder().getFieldTypeInfo(P);
1335+
auto FD = TC.getBuilder().getFieldDescriptor(P);
13361336
if (FD == nullptr) {
13371337
DEBUG_LOG(fprintf(stderr, "No field descriptor: "); P->dump())
13381338
Invalid = true;
@@ -1424,7 +1424,7 @@ class ExistentialTypeInfoBuilder {
14241424
return;
14251425
}
14261426

1427-
const auto &FD = TC.getBuilder().getFieldTypeInfo(T);
1427+
const auto &FD = TC.getBuilder().getFieldDescriptor(T);
14281428
if (FD == nullptr) {
14291429
DEBUG_LOG(fprintf(stderr, "No field descriptor: "); T->dump())
14301430
Invalid = true;
@@ -2093,7 +2093,7 @@ class EnumTypeInfoBuilder {
20932093
: TC(TC), Size(0), Alignment(1), NumExtraInhabitants(0),
20942094
BitwiseTakable(true), Invalid(false) {}
20952095

2096-
const TypeInfo *build(const TypeRef *TR, RemoteRef<FieldDescriptor> FD,
2096+
const TypeInfo *build(const TypeRef *TR, FieldDescriptorBase &FD,
20972097
remote::TypeInfoProvider *ExternalTypeInfo) {
20982098
// Count various categories of cases:
20992099
unsigned NonPayloadCases = 0; // `case a`
@@ -2415,7 +2415,7 @@ class LowerType
24152415
return nullptr;
24162416
};
24172417

2418-
auto FD = TC.getBuilder().getFieldTypeInfo(TR);
2418+
auto FD = TC.getBuilder().getFieldDescriptor(TR);
24192419
if (FD == nullptr || FD->isStruct()) {
24202420
// Maybe this type is opaque -- look for a builtin
24212421
// descriptor to see if we at least know its size
@@ -2454,7 +2454,8 @@ class LowerType
24542454
RecordTypeInfoBuilder builder(TC, RecordKind::Struct);
24552455

24562456
std::vector<FieldTypeInfo> Fields;
2457-
if (!TC.getBuilder().getFieldTypeRefs(TR, FD, ExternalTypeInfo, Fields))
2457+
if (!TC.getBuilder().getFieldTypeRefs(TR, *FD.get(), ExternalTypeInfo,
2458+
Fields))
24582459
return nullptr;
24592460

24602461
for (auto Field : Fields)
@@ -2464,7 +2465,7 @@ class LowerType
24642465
case FieldDescriptorKind::Enum:
24652466
case FieldDescriptorKind::MultiPayloadEnum: {
24662467
EnumTypeInfoBuilder builder(TC);
2467-
return builder.build(TR, FD, ExternalTypeInfo);
2468+
return builder.build(TR, *FD.get(), ExternalTypeInfo);
24682469
}
24692470
case FieldDescriptorKind::ObjCClass:
24702471
return TC.getReferenceTypeInfo(ReferenceKind::Strong,
@@ -2706,7 +2707,7 @@ TypeConverter::getTypeInfo(const TypeRef *TR,
27062707
const RecordTypeInfo *TypeConverter::getClassInstanceTypeInfo(
27072708
const TypeRef *TR, unsigned start,
27082709
remote::TypeInfoProvider *ExternalTypeInfo) {
2709-
auto FD = getBuilder().getFieldTypeInfo(TR);
2710+
auto FD = getBuilder().getFieldDescriptor(TR);
27102711
if (FD == nullptr) {
27112712
DEBUG_LOG(fprintf(stderr, "No field descriptor: "); TR->dump());
27122713
return nullptr;
@@ -2720,7 +2721,7 @@ const RecordTypeInfo *TypeConverter::getClassInstanceTypeInfo(
27202721
RecordTypeInfoBuilder builder(*this, RecordKind::ClassInstance);
27212722

27222723
std::vector<FieldTypeInfo> Fields;
2723-
if (!getBuilder().getFieldTypeRefs(TR, FD, ExternalTypeInfo, Fields))
2724+
if (!getBuilder().getFieldTypeRefs(TR, *FD.get(), ExternalTypeInfo, Fields))
27242725
return nullptr;
27252726

27262727
// Start layout from the given instance start offset. This should

stdlib/public/RemoteInspection/TypeRefBuilder.cpp

Lines changed: 79 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -195,15 +195,15 @@ TypeRefBuilder::ReflectionTypeDescriptorFinder::lookupTypeWitness(
195195
}
196196

197197
const TypeRef *TypeRefBuilder::lookupSuperclass(const TypeRef *TR) {
198-
const auto &FD = getFieldTypeInfo(TR);
198+
const auto &FD = getFieldDescriptor(TR);
199199
if (FD == nullptr)
200200
return nullptr;
201201

202-
if (!FD->hasSuperclass())
202+
if (!FD->HasSuperClass)
203203
return nullptr;
204204

205205
ScopedNodeFactoryCheckpoint checkpoint(this);
206-
auto Demangled = demangleTypeRef(readTypeRef(FD, FD->Superclass));
206+
auto Demangled = FD->demangleSuperclass();
207207
auto Unsubstituted = decodeMangledType(Demangled);
208208
if (!Unsubstituted)
209209
return nullptr;
@@ -375,34 +375,96 @@ TypeRefBuilder::ReflectionTypeDescriptorFinder::getFieldTypeInfo(
375375
return nullptr;
376376
}
377377

378+
namespace {
379+
class FieldRecordImpl : public FieldRecordBase {
380+
RemoteRef<const FieldRecord> Field;
381+
TypeRefBuilder &Builder;
382+
383+
public:
384+
FieldRecordImpl(RemoteRef<const FieldRecord> FR, TypeRefBuilder &Builder)
385+
: FieldRecordBase(FR->isIndirectCase(), FR->isVar(),
386+
FR->hasMangledTypeName()),
387+
Field(FR), Builder(Builder) {}
388+
389+
~FieldRecordImpl() override {}
390+
391+
StringRef getFieldName() override {
392+
return Builder.getTypeRefString(
393+
Builder.readTypeRef(Field, Field->FieldName));
394+
}
395+
396+
NodePointer demangleMangledTypeName() override {
397+
return Builder.demangleTypeRef(
398+
Builder.readTypeRef(Field, Field->MangledTypeName));
399+
}
400+
};
401+
402+
/// A field descriptor implementation that wraps a reflection field
403+
/// descriptor.
404+
class FieldDescriptorImpl : public FieldDescriptorBase {
405+
RemoteRef<FieldDescriptor> FD;
406+
TypeRefBuilder &Builder;
407+
408+
public:
409+
FieldDescriptorImpl(RemoteRef<FieldDescriptor> FD, TypeRefBuilder &Builder)
410+
: FieldDescriptorBase(FD->Kind, FD->hasSuperclass()), FD(FD),
411+
Builder(Builder) {}
412+
413+
~FieldDescriptorImpl() override {}
414+
415+
NodePointer demangleSuperclass() override {
416+
return Builder.demangleTypeRef(Builder.readTypeRef(FD, FD->Superclass));
417+
}
418+
419+
std::vector<std::unique_ptr<FieldRecordBase>> getFieldRecords() override {
420+
std::vector<std::unique_ptr<FieldRecordBase>> FieldRecords;
421+
for (auto &FieldRef : *FD.getLocalBuffer()) {
422+
FieldRecords.emplace_back(
423+
std::make_unique<FieldRecordImpl>(FD.getField(FieldRef), Builder));
424+
}
425+
return FieldRecords;
426+
}
427+
};
428+
} // namespace
429+
430+
std::unique_ptr<FieldDescriptorBase>
431+
TypeRefBuilder::ReflectionTypeDescriptorFinder::getFieldDescriptor(
432+
const TypeRef *TR) {
433+
if (auto FDI = getFieldTypeInfo(TR))
434+
return std::make_unique<FieldDescriptorImpl>(FDI, Builder);
435+
return nullptr;
436+
}
437+
438+
std::unique_ptr<FieldDescriptorBase>
439+
TypeRefBuilder::getFieldDescriptor(const TypeRef *TR) {
440+
for (auto DF : getDescriptorFinders())
441+
if (auto descriptor = DF->getFieldDescriptor(TR))
442+
return descriptor;
443+
return nullptr;
444+
}
445+
378446
bool TypeRefBuilder::getFieldTypeRefs(
379-
const TypeRef *TR, RemoteRef<FieldDescriptor> FD,
447+
const TypeRef *TR, FieldDescriptorBase &FD,
380448
remote::TypeInfoProvider *ExternalTypeInfo,
381449
std::vector<FieldTypeInfo> &Fields) {
382-
if (FD == nullptr)
383-
return false;
384-
385450
auto Subs = TR->getSubstMap();
386451
if (!Subs)
387452
return false;
388453

389454
int FieldValue = -1;
390-
for (auto &FieldRef : *FD.getLocalBuffer()) {
391-
auto Field = FD.getField(FieldRef);
392-
393-
auto FieldName = getTypeRefString(readTypeRef(Field, Field->FieldName));
455+
for (auto &Field : FD.getFieldRecords()) {
456+
auto FieldName = Field->getFieldName();
394457
FieldValue += 1;
395458

396459
// Empty cases of enums do not have a type
397-
if (FD->isEnum() && !Field->hasMangledTypeName()) {
460+
if (FD.isEnum() && !Field->HasMangledTypeName) {
398461
Fields.push_back(
399462
FieldTypeInfo::forEmptyCase(FieldName.str(), FieldValue));
400463
continue;
401464
}
402465

403466
ScopedNodeFactoryCheckpoint checkpoint(this);
404-
auto Demangled =
405-
demangleTypeRef(readTypeRef(Field, Field->MangledTypeName));
467+
auto Demangled = Field->demangleMangledTypeName();
406468
auto Unsubstituted = decodeMangledType(Demangled);
407469
if (!Unsubstituted)
408470
return false;
@@ -412,7 +474,7 @@ bool TypeRefBuilder::getFieldTypeRefs(
412474
// `case a([T?])` is generic, but `case a([Int?])` is not.
413475
bool IsGeneric = false;
414476
auto Substituted = Unsubstituted->subst(*this, *Subs, IsGeneric);
415-
bool IsIndirect = FD->isEnum() && Field->isIndirectCase();
477+
bool IsIndirect = FD.isEnum() && Field->IsIndirectCase;
416478

417479
auto FieldTI = FieldTypeInfo(FieldName.str(), FieldValue, Substituted,
418480
IsIndirect, IsGeneric);
@@ -471,6 +533,7 @@ TypeRefBuilder::ReflectionTypeDescriptorFinder::getBuiltinTypeInfo(
471533
return nullptr;
472534
}
473535

536+
namespace {
474537
/// A builtin type descriptor implementation that wraps a reflection builtin
475538
/// type descriptor.
476539
class BuiltinTypeDescriptorImpl : public BuiltinTypeDescriptorBase {
@@ -491,6 +554,7 @@ class BuiltinTypeDescriptorImpl : public BuiltinTypeDescriptorBase {
491554
return Builder.getTypeRefString(Builder.readTypeRef(BTD, BTD->TypeName));
492555
};
493556
};
557+
} // namespace
494558

495559
std::unique_ptr<BuiltinTypeDescriptorBase>
496560
TypeRefBuilder::ReflectionTypeDescriptorFinder::getBuiltinTypeDescriptor(

0 commit comments

Comments
 (0)