Skip to content

Commit 729428b

Browse files
committed
Reflection: Type lowering for metatypes
The thin vs thick distinction is handled a little awkwardly. Instead of passing around abstraction patterns, we add a "must be thick" bit to MetatypeTypeRef, and thicken substitutions (to handle T; T := C.Type) and the result of a subtitution (to handle T.Type; T := C). With the exception of enums this completes <rdar://problem/25738849>.
1 parent 595b745 commit 729428b

File tree

8 files changed

+369
-14
lines changed

8 files changed

+369
-14
lines changed

include/swift/Reflection/TypeLowering.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ enum class RecordKind : unsigned {
4848
// A class existential is a retainable pointer followed by witness
4949
// tables.
5050
ClassExistential,
51+
52+
// An existential metatype.
53+
ExistentialMetatype,
5154
};
5255

5356
enum class ReferenceCounting : unsigned {
@@ -157,6 +160,7 @@ class TypeConverter {
157160
const TypeRef *NativeObjectTR = nullptr;
158161
const TypeRef *UnknownObjectTR = nullptr;
159162
const TypeInfo *ThickFunctionTI = nullptr;
163+
const TypeInfo *EmptyTI = nullptr;
160164

161165
public:
162166
explicit TypeConverter(TypeRefBuilder &Builder) : Builder(Builder) {}
@@ -174,6 +178,7 @@ class TypeConverter {
174178
const TypeRef *getNativeObjectTypeRef();
175179
const TypeRef *getUnknownObjectTypeRef();
176180
const TypeInfo *getThickFunctionTypeInfo();
181+
const TypeInfo *getEmptyTypeInfo();
177182

178183
template <typename TypeInfoTy, typename... Args>
179184
const TypeInfoTy *makeTypeInfo(Args... args) {

include/swift/Reflection/TypeRef.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,15 +274,22 @@ class ProtocolCompositionTypeRef final : public TypeRef {
274274

275275
class MetatypeTypeRef final : public TypeRef {
276276
const TypeRef *InstanceType;
277+
bool WasAbstract;
277278

278279
public:
279-
MetatypeTypeRef(const TypeRef *InstanceType)
280-
: TypeRef(TypeRefKind::Metatype), InstanceType(InstanceType) {}
280+
MetatypeTypeRef(const TypeRef *InstanceType, bool WasAbstract)
281+
: TypeRef(TypeRefKind::Metatype), InstanceType(InstanceType),
282+
WasAbstract(WasAbstract) {}
281283

282284
template <typename Allocator>
283285
static const MetatypeTypeRef *create(Allocator &A,
284-
const TypeRef *InstanceType) {
285-
return A.template makeTypeRef<MetatypeTypeRef>(InstanceType);
286+
const TypeRef *InstanceType,
287+
bool WasAbstract = false) {
288+
return A.template makeTypeRef<MetatypeTypeRef>(InstanceType, WasAbstract);
289+
}
290+
291+
bool wasAbstract() const {
292+
return WasAbstract;
286293
}
287294

288295
const TypeRef *getInstanceType() const {

include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ typedef enum swift_layout_kind_t {
5353
SWIFT_THICK_FUNCTION,
5454
SWIFT_EXISTENTIAL,
5555
SWIFT_CLASS_EXISTENTIAL,
56+
SWIFT_EXISTENTIAL_METATYPE,
5657

5758
// References to other objects in the heap.
5859
SWIFT_STRONG_REFERENCE,

stdlib/public/Reflection/TypeLowering.cpp

Lines changed: 190 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ class PrintTypeInfo {
113113
case RecordKind::ClassExistential:
114114
printHeader("class_existential");
115115
break;
116+
case RecordKind::ExistentialMetatype:
117+
printHeader("existential_metatype");
118+
break;
116119
}
117120
printBasic(TI);
118121
printFields(RecordTI);
@@ -311,6 +314,26 @@ class ExistentialTypeInfoBuilder {
311314

312315
return builder.build();
313316
}
317+
318+
const TypeInfo *buildMetatype() {
319+
if (Invalid)
320+
return nullptr;
321+
322+
if (ObjC) {
323+
if (WitnessTableCount > 0)
324+
return nullptr;
325+
326+
return TC.getTypeInfo(TC.getRawPointerTypeRef());
327+
}
328+
329+
RecordTypeInfoBuilder builder(TC, RecordKind::ExistentialMetatype);
330+
331+
builder.addField("metadata", TC.getRawPointerTypeRef());
332+
for (unsigned i = 0; i < WitnessTableCount; i++)
333+
builder.addField("wtable", TC.getRawPointerTypeRef());
334+
335+
return builder.build();
336+
}
314337
};
315338

316339
}
@@ -360,6 +383,14 @@ TypeConverter::getThickFunctionTypeInfo() {
360383
return ThickFunctionTI;
361384
}
362385

386+
const TypeInfo *TypeConverter::getEmptyTypeInfo() {
387+
if (EmptyTI != nullptr)
388+
return EmptyTI;
389+
390+
EmptyTI = makeTypeInfo<TypeInfo>(TypeInfoKind::Builtin, 0, 1, 0, 0);
391+
return EmptyTI;
392+
}
393+
363394
const TypeRef *TypeConverter::getRawPointerTypeRef() {
364395
if (RawPointerTR != nullptr)
365396
return RawPointerTR;
@@ -384,6 +415,143 @@ const TypeRef *TypeConverter::getUnknownObjectTypeRef() {
384415
return UnknownObjectTR;
385416
}
386417

418+
enum class MetatypeRepresentation : unsigned {
419+
Thin,
420+
Thick,
421+
Unknown
422+
};
423+
424+
MetatypeRepresentation combineRepresentations(MetatypeRepresentation rep1,
425+
MetatypeRepresentation rep2) {
426+
if (rep1 == rep2)
427+
return rep1;
428+
429+
if (rep1 == MetatypeRepresentation::Unknown ||
430+
rep2 == MetatypeRepresentation::Unknown)
431+
return MetatypeRepresentation::Unknown;
432+
433+
if (rep1 == MetatypeRepresentation::Thick ||
434+
rep2 == MetatypeRepresentation::Thick)
435+
return MetatypeRepresentation::Thick;
436+
437+
return MetatypeRepresentation::Thin;
438+
}
439+
440+
class HasSingletonMetatype
441+
: public TypeRefVisitor<HasSingletonMetatype, MetatypeRepresentation> {
442+
TypeRefBuilder &Builder;
443+
444+
public:
445+
HasSingletonMetatype(TypeRefBuilder &Builder) : Builder(Builder) {}
446+
447+
using TypeRefVisitor<HasSingletonMetatype, MetatypeRepresentation>::visit;
448+
449+
MetatypeRepresentation visitBuiltinTypeRef(const BuiltinTypeRef *B) {
450+
return MetatypeRepresentation::Thin;
451+
}
452+
453+
MetatypeRepresentation visitAnyNominalTypeRef(const TypeRef *TR) {
454+
const FieldDescriptor *FD = Builder.getFieldTypeInfo(TR);
455+
if (FD == nullptr)
456+
return MetatypeRepresentation::Unknown;
457+
458+
switch (FD->Kind) {
459+
case FieldDescriptorKind::Class:
460+
return MetatypeRepresentation::Thick;
461+
462+
case FieldDescriptorKind::Struct:
463+
case FieldDescriptorKind::Enum:
464+
return MetatypeRepresentation::Thin;
465+
466+
case FieldDescriptorKind::ObjCProtocol:
467+
case FieldDescriptorKind::ClassProtocol:
468+
case FieldDescriptorKind::Protocol:
469+
return MetatypeRepresentation::Unknown;
470+
}
471+
}
472+
473+
MetatypeRepresentation visitNominalTypeRef(const NominalTypeRef *N) {
474+
return visitAnyNominalTypeRef(N);
475+
}
476+
477+
MetatypeRepresentation visitBoundGenericTypeRef(const BoundGenericTypeRef *BG) {
478+
return visitAnyNominalTypeRef(BG);
479+
}
480+
481+
MetatypeRepresentation visitTupleTypeRef(const TupleTypeRef *T) {
482+
auto result = MetatypeRepresentation::Thin;
483+
for (auto Element : T->getElements())
484+
result = combineRepresentations(result, visit(Element));
485+
return result;
486+
}
487+
488+
MetatypeRepresentation visitFunctionTypeRef(const FunctionTypeRef *F) {
489+
auto result = visit(F->getResult());
490+
for (auto Arg : F->getArguments())
491+
result = combineRepresentations(result, visit(Arg));
492+
return result;
493+
}
494+
495+
MetatypeRepresentation visitProtocolTypeRef(const ProtocolTypeRef *P) {
496+
return MetatypeRepresentation::Thin;
497+
}
498+
499+
MetatypeRepresentation
500+
visitProtocolCompositionTypeRef(const ProtocolCompositionTypeRef *PC) {
501+
return MetatypeRepresentation::Thin;
502+
}
503+
504+
MetatypeRepresentation visitMetatypeTypeRef(const MetatypeTypeRef *M) {
505+
if (M->wasAbstract())
506+
return MetatypeRepresentation::Thick;
507+
return visit(M->getInstanceType());
508+
}
509+
510+
MetatypeRepresentation
511+
visitExistentialMetatypeTypeRef(const ExistentialMetatypeTypeRef *EM) {
512+
return MetatypeRepresentation::Thin;
513+
}
514+
515+
MetatypeRepresentation
516+
visitGenericTypeParameterTypeRef(const GenericTypeParameterTypeRef *GTP) {
517+
assert(false && "Must have concrete TypeRef");
518+
return MetatypeRepresentation::Unknown;
519+
}
520+
521+
MetatypeRepresentation
522+
visitDependentMemberTypeRef(const DependentMemberTypeRef *DM) {
523+
assert(false && "Must have concrete TypeRef");
524+
return MetatypeRepresentation::Unknown;
525+
}
526+
527+
MetatypeRepresentation
528+
visitForeignClassTypeRef(const ForeignClassTypeRef *F) {
529+
return MetatypeRepresentation::Unknown;
530+
}
531+
532+
MetatypeRepresentation visitObjCClassTypeRef(const ObjCClassTypeRef *OC) {
533+
return MetatypeRepresentation::Unknown;
534+
}
535+
536+
MetatypeRepresentation
537+
visitUnownedStorageTypeRef(const UnownedStorageTypeRef *US) {
538+
return MetatypeRepresentation::Unknown;
539+
}
540+
541+
MetatypeRepresentation visitWeakStorageTypeRef(const WeakStorageTypeRef *WS) {
542+
return MetatypeRepresentation::Unknown;
543+
}
544+
545+
MetatypeRepresentation
546+
visitUnmanagedStorageTypeRef(const UnmanagedStorageTypeRef *US) {
547+
return MetatypeRepresentation::Unknown;
548+
}
549+
550+
MetatypeRepresentation visitOpaqueTypeRef(const OpaqueTypeRef *O) {
551+
return MetatypeRepresentation::Unknown;
552+
}
553+
};
554+
387555
class LowerType
388556
: public TypeRefVisitor<LowerType, const TypeInfo *> {
389557
TypeConverter &TC;
@@ -508,14 +676,31 @@ class LowerType
508676
}
509677

510678
const TypeInfo *visitMetatypeTypeRef(const MetatypeTypeRef *M) {
511-
// FIXME
512-
return nullptr;
679+
switch (HasSingletonMetatype(TC.getBuilder()).visit(M)) {
680+
case MetatypeRepresentation::Unknown:
681+
return nullptr;
682+
case MetatypeRepresentation::Thin:
683+
return TC.getEmptyTypeInfo();
684+
case MetatypeRepresentation::Thick:
685+
return TC.getTypeInfo(TC.getRawPointerTypeRef());
686+
}
513687
}
514688

515689
const TypeInfo *
516690
visitExistentialMetatypeTypeRef(const ExistentialMetatypeTypeRef *EM) {
517-
// FIXME
518-
return nullptr;
691+
ExistentialTypeInfoBuilder builder(TC);
692+
auto *TR = EM->getInstanceType();
693+
694+
if (auto *P = dyn_cast<ProtocolTypeRef>(TR)) {
695+
builder.addProtocol(P);
696+
} else if (auto *PC = dyn_cast<ProtocolCompositionTypeRef>(TR)) {
697+
for (auto *P : PC->getProtocols())
698+
builder.addProtocol(P);
699+
} else {
700+
return nullptr;
701+
}
702+
703+
return builder.buildMetatype();
519704
}
520705

521706
const TypeInfo *
@@ -594,7 +779,7 @@ class LowerType
594779
return visitAnyStorageTypeRef(US, ReferenceKind::Unmanaged);
595780
}
596781

597-
const TypeInfo *visitOpaqueTypeRef(const OpaqueTypeRef *Op) {
782+
const TypeInfo *visitOpaqueTypeRef(const OpaqueTypeRef *O) {
598783
assert(false && "Can't lower opaque TypeRef");
599784
return nullptr;
600785
}

0 commit comments

Comments
 (0)