Skip to content

Commit 95652f3

Browse files
authored
Merge pull request #18320 from rjmccall/runtime-only-type-ref-string
Reference runtime-only ObjC classes with bare strings
2 parents 9156ecb + d102393 commit 95652f3

File tree

12 files changed

+276
-158
lines changed

12 files changed

+276
-158
lines changed

include/swift/ABI/Metadata.h

Lines changed: 85 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2150,32 +2150,37 @@ struct TargetTypeMetadataRecord {
21502150
union {
21512151
/// A direct reference to a nominal type descriptor.
21522152
RelativeDirectPointerIntPair<TargetTypeContextDescriptor<Runtime>,
2153-
TypeMetadataRecordKind>
2153+
TypeReferenceKind>
21542154
DirectNominalTypeDescriptor;
21552155

21562156
/// An indirect reference to a nominal type descriptor.
21572157
RelativeDirectPointerIntPair<TargetTypeContextDescriptor<Runtime> * const,
2158-
TypeMetadataRecordKind>
2158+
TypeReferenceKind>
21592159
IndirectNominalTypeDescriptor;
2160+
2161+
// We only allow a subset of the TypeReferenceKinds here.
2162+
// Should we just acknowledge that this is a different enum?
21602163
};
21612164

21622165
public:
2163-
TypeMetadataRecordKind getTypeKind() const {
2166+
TypeReferenceKind getTypeKind() const {
21642167
return DirectNominalTypeDescriptor.getInt();
21652168
}
21662169

21672170
const TargetTypeContextDescriptor<Runtime> *
21682171
getTypeContextDescriptor() const {
21692172
switch (getTypeKind()) {
2170-
case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
2173+
case TypeReferenceKind::DirectNominalTypeDescriptor:
21712174
return DirectNominalTypeDescriptor.getPointer();
21722175

2173-
case TypeMetadataRecordKind::Reserved:
2174-
case TypeMetadataRecordKind::IndirectObjCClass:
2175-
return nullptr;
2176-
2177-
case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
2176+
case TypeReferenceKind::IndirectNominalTypeDescriptor:
21782177
return *IndirectNominalTypeDescriptor.getPointer();
2178+
2179+
// These types (and any others we might add to TypeReferenceKind
2180+
// in the future) are just never used in these lists.
2181+
case TypeReferenceKind::DirectObjCClassName:
2182+
case TypeReferenceKind::IndirectObjCClass:
2183+
return nullptr;
21792184
}
21802185

21812186
return nullptr;
@@ -2250,6 +2255,66 @@ class RelativeTargetProtocolDescriptorPointer {
22502255
}
22512256
};
22522257

2258+
/// A referenc to a type.
2259+
template <typename Runtime>
2260+
struct TargetTypeReference {
2261+
union {
2262+
/// A direct reference to a nominal type descriptor.
2263+
RelativeDirectPointer<TargetTypeContextDescriptor<Runtime>>
2264+
DirectNominalTypeDescriptor;
2265+
2266+
/// An indirect reference to a nominal type descriptor.
2267+
RelativeDirectPointer<
2268+
ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor>>
2269+
IndirectNominalTypeDescriptor;
2270+
2271+
/// An indirect reference to an Objective-C class.
2272+
RelativeDirectPointer<
2273+
ConstTargetMetadataPointer<Runtime, TargetClassMetadata>>
2274+
IndirectObjCClass;
2275+
2276+
/// A direct reference to an Objective-C class name.
2277+
RelativeDirectPointer<const char>
2278+
DirectObjCClassName;
2279+
};
2280+
2281+
const TargetTypeContextDescriptor<Runtime> *
2282+
getTypeContextDescriptor(TypeReferenceKind kind) const {
2283+
switch (kind) {
2284+
case TypeReferenceKind::DirectNominalTypeDescriptor:
2285+
return DirectNominalTypeDescriptor;
2286+
2287+
case TypeReferenceKind::IndirectNominalTypeDescriptor:
2288+
return *IndirectNominalTypeDescriptor;
2289+
2290+
case TypeReferenceKind::DirectObjCClassName:
2291+
case TypeReferenceKind::IndirectObjCClass:
2292+
return nullptr;
2293+
}
2294+
2295+
return nullptr;
2296+
}
2297+
2298+
#if SWIFT_OBJC_INTEROP
2299+
/// If this type reference is one of the kinds that supports ObjC
2300+
/// references,
2301+
const TargetClassMetadata<Runtime> *
2302+
getObjCClass(TypeReferenceKind kind) const;
2303+
#endif
2304+
2305+
const TargetClassMetadata<Runtime> * const *
2306+
getIndirectObjCClass(TypeReferenceKind kind) const {
2307+
assert(kind == TypeReferenceKind::IndirectObjCClass);
2308+
return IndirectObjCClass.get();
2309+
}
2310+
2311+
const char *getDirectObjCClassName(TypeReferenceKind kind) const {
2312+
assert(kind == TypeReferenceKind::DirectObjCClassName);
2313+
return DirectObjCClassName.get();
2314+
}
2315+
};
2316+
using TypeReference = TargetTypeReference<InProcess>;
2317+
22532318
/// The structure of a protocol conformance.
22542319
///
22552320
/// This contains enough static information to recover the witness table for a
@@ -2284,21 +2349,7 @@ struct TargetProtocolConformanceDescriptor final
22842349
RelativeIndirectablePointer<ProtocolDescriptor> Protocol;
22852350

22862351
// Some description of the type that conforms to the protocol.
2287-
union {
2288-
/// A direct reference to a nominal type descriptor.
2289-
RelativeDirectPointer<TargetTypeContextDescriptor<Runtime>>
2290-
DirectNominalTypeDescriptor;
2291-
2292-
/// An indirect reference to a nominal type descriptor.
2293-
RelativeDirectPointer<
2294-
ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor>>
2295-
IndirectNominalTypeDescriptor;
2296-
2297-
/// An indirect reference to the metadata.
2298-
RelativeDirectPointer<
2299-
ConstTargetMetadataPointer<Runtime, TargetClassMetadata>>
2300-
IndirectObjCClass;
2301-
};
2352+
TargetTypeReference<Runtime> TypeRef;
23022353

23032354
// The conformance, or a generator function for the conformance.
23042355
union {
@@ -2318,45 +2369,24 @@ struct TargetProtocolConformanceDescriptor final
23182369
return Protocol;
23192370
}
23202371

2321-
TypeMetadataRecordKind getTypeKind() const {
2372+
TypeReferenceKind getTypeKind() const {
23222373
return Flags.getTypeReferenceKind();
23232374
}
23242375

23252376
typename ConformanceFlags::ConformanceKind getConformanceKind() const {
23262377
return Flags.getConformanceKind();
23272378
}
2328-
2329-
const TargetClassMetadata<Runtime> * const *getIndirectObjCClass() const {
2330-
switch (getTypeKind()) {
2331-
case TypeMetadataRecordKind::IndirectObjCClass:
2332-
break;
23332379

2334-
case TypeMetadataRecordKind::Reserved:
2335-
return nullptr;
2380+
const char *getDirectObjCClassName() const {
2381+
return TypeRef.getDirectObjCClassName(getTypeKind());
2382+
}
23362383

2337-
case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
2338-
case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
2339-
assert(false && "not indirect class object");
2340-
}
2341-
2342-
return IndirectObjCClass.get();
2384+
const TargetClassMetadata<Runtime> * const *getIndirectObjCClass() const {
2385+
return TypeRef.getIndirectObjCClass(getTypeKind());
23432386
}
23442387

2345-
const TargetTypeContextDescriptor<Runtime> *
2346-
getTypeContextDescriptor() const {
2347-
switch (getTypeKind()) {
2348-
case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
2349-
return DirectNominalTypeDescriptor;
2350-
2351-
case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
2352-
return *IndirectNominalTypeDescriptor;
2353-
2354-
case TypeMetadataRecordKind::Reserved:
2355-
case TypeMetadataRecordKind::IndirectObjCClass:
2356-
return nullptr;
2357-
}
2358-
2359-
return nullptr;
2388+
const TargetTypeContextDescriptor<Runtime> *getTypeContextDescriptor() const {
2389+
return TypeRef.getTypeContextDescriptor(getTypeKind());
23602390
}
23612391

23622392
/// Retrieve the context of a retroactive conformance.
@@ -2418,7 +2448,7 @@ struct TargetProtocolConformanceDescriptor final
24182448
///
24192449
/// We currently check that the descriptor:
24202450
///
2421-
/// 1. Has a valid TypeMetadataRecordKind.
2451+
/// 1. Has a valid TypeReferenceKind.
24222452
/// 2. Has a valid conformance kind.
24232453
void verify() const LLVM_ATTRIBUTE_USED;
24242454
#endif
@@ -3563,7 +3593,7 @@ class TargetClassDescriptor final
35633593
return !Superclass.isNull();
35643594
}
35653595

3566-
TypeMetadataRecordKind getSuperclassReferenceKind() const {
3596+
TypeReferenceKind getSuperclassReferenceKind() const {
35673597
return getTypeContextDescriptorFlags().class_getSuperclassReferenceKind();
35683598
}
35693599

include/swift/ABI/MetadataValues.h

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ enum : unsigned {
350350
};
351351

352352
/// Kinds of type metadata/protocol conformance records.
353-
enum class TypeMetadataRecordKind : unsigned {
353+
enum class TypeReferenceKind : unsigned {
354354
/// The conformance is for a nominal type referenced directly;
355355
/// getNominalTypeDescriptor() points to the nominal type descriptor.
356356
DirectNominalTypeDescriptor = 0x00,
@@ -359,9 +359,10 @@ enum class TypeMetadataRecordKind : unsigned {
359359
/// getNominalTypeDescriptor() points to the nominal type descriptor.
360360
IndirectNominalTypeDescriptor = 0x01,
361361

362-
/// Reserved for future use.
363-
Reserved = 0x02,
364-
362+
/// The conformance is for an Objective-C class that should be looked up
363+
/// by class name.
364+
DirectObjCClassName = 0x02,
365+
365366
/// The conformance is for an Objective-C class that has no nominal type
366367
/// descriptor.
367368
/// getIndirectObjCClass() points to a variable that contains the pointer to
@@ -371,6 +372,8 @@ enum class TypeMetadataRecordKind : unsigned {
371372
/// unused.
372373
IndirectObjCClass = 0x03,
373374

375+
// We only reserve three bits for this in the various places we store it.
376+
374377
First_Kind = DirectNominalTypeDescriptor,
375378
Last_Kind = IndirectObjCClass,
376379
};
@@ -593,7 +596,7 @@ class ConformanceFlags {
593596
return ConformanceFlags((Value & ~ConformanceKindMask) | int_type(kind));
594597
}
595598

596-
ConformanceFlags withTypeReferenceKind(TypeMetadataRecordKind kind) const {
599+
ConformanceFlags withTypeReferenceKind(TypeReferenceKind kind) const {
597600
return ConformanceFlags((Value & ~TypeMetadataKindMask)
598601
| (int_type(kind) << TypeMetadataKindShift));
599602
}
@@ -621,8 +624,8 @@ class ConformanceFlags {
621624
}
622625

623626
/// Retrieve the type reference kind kind.
624-
TypeMetadataRecordKind getTypeReferenceKind() const {
625-
return TypeMetadataRecordKind(
627+
TypeReferenceKind getTypeReferenceKind() const {
628+
return TypeReferenceKind(
626629
(Value & TypeMetadataKindMask) >> TypeMetadataKindShift);
627630
}
628631

@@ -1237,16 +1240,16 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
12371240
/// Only meaningful for class descriptors.
12381241
Class_HasResilientSuperclass = 14,
12391242

1243+
/// Whether the immediate class members in this metadata are allocated
1244+
/// at negative offsets. For now, we don't use this.
1245+
Class_AreImmediateMembersNegative = 13,
1246+
12401247
/// The kind of reference that this class makes to its superclass
1241-
/// descriptor. A TypeMetadataRecordKind.
1248+
/// descriptor. A TypeReferenceKind.
12421249
///
12431250
/// Only meaningful for class descriptors.
1244-
Class_SuperclassReferenceKind = 12,
1245-
Class_SuperclassReferenceKind_width = 2,
1246-
1247-
/// Whether the immediate class members in this metadata are allocated
1248-
/// at negative offsets. For now, we don't use this.
1249-
Class_AreImmediateMembersNegative = 11,
1251+
Class_SuperclassReferenceKind = 10,
1252+
Class_SuperclassReferenceKind_width = 3,
12501253
};
12511254

12521255
public:
@@ -1333,7 +1336,7 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
13331336

13341337
FLAGSET_DEFINE_FIELD_ACCESSORS(Class_SuperclassReferenceKind,
13351338
Class_SuperclassReferenceKind_width,
1336-
TypeMetadataRecordKind,
1339+
TypeReferenceKind,
13371340
class_getSuperclassReferenceKind,
13381341
class_setSuperclassReferenceKind)
13391342
};

include/swift/Remote/MetadataReader.h

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -740,16 +740,23 @@ class MetadataReader {
740740
return llvm::None;
741741

742742
return cls->getClassBoundsAsSwiftSuperclass();
743+
},
744+
[](StoredPointer objcClassName) -> llvm::Optional<ClassMetadataBounds> {
745+
// We have no ability to look up an ObjC class by name.
746+
// FIXME: add a query for this; clients may have a way to do it.
747+
return llvm::None;
743748
});
744749
}
745750

746-
template <class Result, class DescriptorFn, class MetadataFn>
751+
template <class Result, class DescriptorFn, class MetadataFn,
752+
class ClassNameFn>
747753
llvm::Optional<Result>
748-
forTypeReference(TypeMetadataRecordKind refKind, StoredPointer ref,
754+
forTypeReference(TypeReferenceKind refKind, StoredPointer ref,
749755
const DescriptorFn &descriptorFn,
750-
const MetadataFn &metadataFn) {
756+
const MetadataFn &metadataFn,
757+
const ClassNameFn &classNameFn) {
751758
switch (refKind) {
752-
case TypeMetadataRecordKind::IndirectNominalTypeDescriptor: {
759+
case TypeReferenceKind::IndirectNominalTypeDescriptor: {
753760
StoredPointer descriptorAddress = 0;
754761
if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress))
755762
return llvm::None;
@@ -758,15 +765,18 @@ class MetadataReader {
758765
LLVM_FALLTHROUGH;
759766
}
760767

761-
case TypeMetadataRecordKind::DirectNominalTypeDescriptor: {
768+
case TypeReferenceKind::DirectNominalTypeDescriptor: {
762769
auto descriptor = readContextDescriptor(ref);
763770
if (!descriptor)
764771
return llvm::None;
765772

766773
return descriptorFn(descriptor);
767774
}
768775

769-
case TypeMetadataRecordKind::IndirectObjCClass: {
776+
case TypeReferenceKind::DirectObjCClassName:
777+
return classNameFn(ref);
778+
779+
case TypeReferenceKind::IndirectObjCClass: {
770780
StoredPointer classRef = 0;
771781
if (!Reader->readInteger(RemoteAddress(ref), &classRef))
772782
return llvm::None;
@@ -777,10 +787,9 @@ class MetadataReader {
777787

778788
return metadataFn(metadata);
779789
}
780-
781-
default:
782-
return llvm::None;
783790
}
791+
792+
return llvm::None;
784793
}
785794

786795
/// Read a single generic type argument from a bound generic type

0 commit comments

Comments
 (0)