Skip to content

Commit 254ecb6

Browse files
authored
Merge pull request #69752 from augusto2112/field-descriptor-interface
Add interface for lookup of externally stored field descriptors
2 parents 2c8bd79 + e05e3ae commit 254ecb6

File tree

4 files changed

+155
-29
lines changed

4 files changed

+155
-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 *getDemangledTypeName() = 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: 80 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,97 @@ TypeRefBuilder::ReflectionTypeDescriptorFinder::getFieldTypeInfo(
375375
return nullptr;
376376
}
377377

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

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

396460
// Empty cases of enums do not have a type
397-
if (FD->isEnum() && !Field->hasMangledTypeName()) {
461+
if (FD.isEnum() && !Field->HasMangledTypeName) {
398462
Fields.push_back(
399463
FieldTypeInfo::forEmptyCase(FieldName.str(), FieldValue));
400464
continue;
401465
}
402466

403467
ScopedNodeFactoryCheckpoint checkpoint(this);
404-
auto Demangled =
405-
demangleTypeRef(readTypeRef(Field, Field->MangledTypeName));
468+
auto Demangled = Field->getDemangledTypeName();
406469
auto Unsubstituted = decodeMangledType(Demangled);
407470
if (!Unsubstituted)
408471
return false;
@@ -412,7 +475,7 @@ bool TypeRefBuilder::getFieldTypeRefs(
412475
// `case a([T?])` is generic, but `case a([Int?])` is not.
413476
bool IsGeneric = false;
414477
auto Substituted = Unsubstituted->subst(*this, *Subs, IsGeneric);
415-
bool IsIndirect = FD->isEnum() && Field->isIndirectCase();
478+
bool IsIndirect = FD.isEnum() && Field->IsIndirectCase;
416479

417480
auto FieldTI = FieldTypeInfo(FieldName.str(), FieldValue, Substituted,
418481
IsIndirect, IsGeneric);
@@ -471,6 +534,7 @@ TypeRefBuilder::ReflectionTypeDescriptorFinder::getBuiltinTypeInfo(
471534
return nullptr;
472535
}
473536

537+
namespace {
474538
/// A builtin type descriptor implementation that wraps a reflection builtin
475539
/// type descriptor.
476540
class BuiltinTypeDescriptorImpl : public BuiltinTypeDescriptorBase {
@@ -491,6 +555,7 @@ class BuiltinTypeDescriptorImpl : public BuiltinTypeDescriptorBase {
491555
return Builder.getTypeRefString(Builder.readTypeRef(BTD, BTD->TypeName));
492556
};
493557
};
558+
} // namespace
494559

495560
std::unique_ptr<BuiltinTypeDescriptorBase>
496561
TypeRefBuilder::ReflectionTypeDescriptorFinder::getBuiltinTypeDescriptor(

0 commit comments

Comments
 (0)