@@ -171,6 +171,38 @@ class MetadataReader {
171171 StoredPointer IndexedClassesCountPointer;
172172 StoredPointer LastIndexedClassesCount = 0 ;
173173
174+ enum class TaggedPointerEncodingKind {
175+ // / We haven't checked yet.
176+ Unknown,
177+
178+ // / There was an error trying to find out the tagged pointer encoding.
179+ Error,
180+
181+ // / The "extended" encoding.
182+ // /
183+ // / 1 bit: is-tagged
184+ // / 3 bits: class index (for objc_debug_taggedpointer_classes[])
185+ // / 60 bits: payload
186+ // /
187+ // / Class index 0b111 represents 256 additional classes:
188+ // /
189+ // / 1 bit: is-tagged
190+ // / 3 bits: 0b111
191+ // / 8 bits: extended class index (for objc_debug_taggedpointer_ext_classes[])
192+ // / 54 bits: payload
193+ Extended
194+ };
195+ TaggedPointerEncodingKind TaggedPointerEncoding =
196+ TaggedPointerEncodingKind::Unknown;
197+ StoredPointer TaggedPointerMask;
198+ StoredPointer TaggedPointerSlotShift;
199+ StoredPointer TaggedPointerSlotMask;
200+ StoredPointer TaggedPointerClasses;
201+ StoredPointer TaggedPointerExtendedMask;
202+ StoredPointer TaggedPointerExtendedSlotShift;
203+ StoredPointer TaggedPointerExtendedSlotMask;
204+ StoredPointer TaggedPointerExtendedClasses;
205+
174206 Demangle::NodeFactory Factory;
175207
176208 Demangle::NodeFactory &getNodeFactory () { return Factory; }
@@ -463,10 +495,28 @@ class MetadataReader {
463495 if (!Meta) return BuiltType ();
464496
465497 switch (Meta->getKind ()) {
466- case MetadataKind::Class:
467- if (!cast<TargetClassMetadata<Runtime>>(Meta)->isTypeMetadata ())
468- return BuiltType ();
498+ case MetadataKind::Class: {
499+ auto classMeta = cast<TargetClassMetadata<Runtime>>(Meta);
500+ if (!classMeta->isTypeMetadata ()) {
501+ std::string className;
502+ if (!readObjCClassName (MetadataAddress, className))
503+ return BuiltType ();
504+
505+ auto BuiltObjCClass = Builder.createObjCClassType (std::move (className));
506+ if (!BuiltObjCClass) {
507+ // Try the superclass.
508+ if (!classMeta->Superclass )
509+ return BuiltType ();
510+
511+ return readTypeFromMetadata (classMeta->Superclass ,
512+ skipArtificialSubclasses);
513+ }
514+
515+ TypeCache[MetadataAddress] = BuiltObjCClass;
516+ return BuiltObjCClass;
517+ }
469518 return readNominalTypeFromMetadata (Meta, skipArtificialSubclasses);
519+ }
470520 case MetadataKind::Struct:
471521 case MetadataKind::Enum:
472522 case MetadataKind::Optional:
@@ -657,10 +707,48 @@ class MetadataReader {
657707 return buildContextMangling (context, Dem);
658708 }
659709
710+ bool isTaggedPointer (StoredPointer objectAddress) {
711+ if (getTaggedPointerEncoding () != TaggedPointerEncodingKind::Extended)
712+ return false ;
713+
714+ return objectAddress & TaggedPointerMask;
715+ }
716+
717+ // / Read the isa pointer of an Object-C tagged pointer value.
718+ Optional<StoredPointer>
719+ readMetadataFromTaggedPointer (StoredPointer objectAddress) {
720+ auto readArrayElement = [&](StoredPointer base, StoredPointer tag)
721+ -> Optional<StoredPointer> {
722+ StoredPointer addr = base + tag * sizeof (StoredPointer);
723+ StoredPointer isa;
724+ if (!Reader->readInteger (RemoteAddress (addr), &isa))
725+ return None;
726+ return isa;
727+ };
728+
729+ // Extended pointers have a tag of 0b111, using 8 additional bits
730+ // to specify the class.
731+ if (TaggedPointerExtendedMask != 0 &&
732+ ((objectAddress & TaggedPointerExtendedMask)
733+ == TaggedPointerExtendedMask)) {
734+ auto tag = ((objectAddress >> TaggedPointerExtendedSlotShift) &
735+ TaggedPointerExtendedSlotMask);
736+ return readArrayElement (TaggedPointerExtendedClasses, tag);
737+ }
738+
739+ // Basic tagged pointers use a 3 bit tag to specify the class.
740+ auto tag = ((objectAddress >> TaggedPointerSlotShift) &
741+ TaggedPointerSlotMask);
742+ return readArrayElement (TaggedPointerClasses, tag);
743+ }
744+
660745 // / Read the isa pointer of a class or closure context instance and apply
661746 // / the isa mask.
662747 Optional<StoredPointer>
663748 readMetadataFromInstance (StoredPointer objectAddress) {
749+ if (isTaggedPointer (objectAddress))
750+ return readMetadataFromTaggedPointer (objectAddress);
751+
664752 StoredPointer isa;
665753 if (!Reader->readInteger (RemoteAddress (objectAddress), &isa))
666754 return None;
@@ -2290,9 +2378,71 @@ class MetadataReader {
22902378 }
22912379 }
22922380
2381+ # undef tryFindSymbol
2382+ # undef tryReadSymbol
2383+ # undef tryFindAndReadSymbol
2384+
22932385 return finish (IsaEncodingKind::None);
22942386 }
22952387
2388+ TaggedPointerEncodingKind getTaggedPointerEncoding () {
2389+ if (TaggedPointerEncoding != TaggedPointerEncodingKind::Unknown)
2390+ return TaggedPointerEncoding;
2391+
2392+ auto finish = [&](TaggedPointerEncodingKind result)
2393+ -> TaggedPointerEncodingKind {
2394+ TaggedPointerEncoding = result;
2395+ return result;
2396+ };
2397+
2398+ // / Look up the given global symbol and bind 'varname' to its
2399+ // / address if its exists.
2400+ # define tryFindSymbol (varname, symbolName ) \
2401+ auto varname = Reader->getSymbolAddress (symbolName); \
2402+ if (!varname) \
2403+ return finish (TaggedPointerEncodingKind::Error)
2404+ // / Read from the given pointer into 'dest'.
2405+ # define tryReadSymbol (varname, dest ) do { \
2406+ if (!Reader->readInteger (varname, &dest)) \
2407+ return finish (TaggedPointerEncodingKind::Error); \
2408+ } while (0 )
2409+ // / Read from the given global symbol into 'dest'.
2410+ # define tryFindAndReadSymbol (dest, symbolName ) do { \
2411+ tryFindSymbol (_address, symbolName); \
2412+ tryReadSymbol (_address, dest); \
2413+ } while (0 )
2414+
2415+ tryFindAndReadSymbol (TaggedPointerMask,
2416+ " objc_debug_taggedpointer_mask" );
2417+ tryFindAndReadSymbol (TaggedPointerSlotShift,
2418+ " objc_debug_taggedpointer_slot_shift" );
2419+ tryFindAndReadSymbol (TaggedPointerSlotMask,
2420+ " objc_debug_taggedpointer_slot_mask" );
2421+ tryFindSymbol (TaggedPointerClassesAddr,
2422+ " objc_debug_taggedpointer_classes" );
2423+ if (!TaggedPointerClassesAddr)
2424+ finish (TaggedPointerEncodingKind::Error);
2425+ TaggedPointerClasses = TaggedPointerClassesAddr.getAddressData ();
2426+ tryFindAndReadSymbol (TaggedPointerExtendedMask,
2427+ " objc_debug_taggedpointer_ext_mask" );
2428+ tryFindAndReadSymbol (TaggedPointerExtendedSlotShift,
2429+ " objc_debug_taggedpointer_ext_slot_shift" );
2430+ tryFindAndReadSymbol (TaggedPointerExtendedSlotMask,
2431+ " objc_debug_taggedpointer_ext_slot_mask" );
2432+ tryFindSymbol (TaggedPointerExtendedClassesAddr,
2433+ " objc_debug_taggedpointer_ext_classes" );
2434+ if (!TaggedPointerExtendedClassesAddr)
2435+ finish (TaggedPointerEncodingKind::Error);
2436+ TaggedPointerExtendedClasses =
2437+ TaggedPointerExtendedClassesAddr.getAddressData ();
2438+
2439+ # undef tryFindSymbol
2440+ # undef tryReadSymbol
2441+ # undef tryFindAndReadSymbol
2442+
2443+ return finish (TaggedPointerEncodingKind::Extended);
2444+ }
2445+
22962446 template <class T >
22972447 static constexpr T roundUpToAlignment (T offset, T alignment) {
22982448 return (offset + alignment - 1 ) & ~(alignment - 1 );
0 commit comments