//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "swift/Basic/Fallthrough.h" #include "swift/Runtime/Reflection.h" #include "swift/Runtime/HeapObject.h" #include "swift/Runtime/ObjCBridge.h" #include "swift/Runtime/Metadata.h" #include "Debug.h" #include #include #include #include #include #include #include #include using namespace swift; // Declare the debugQuickLookObject selector. @protocol DeclareQuickLookObject - (id)debugQuickLookObject; @end @class SwiftObject; namespace { /// The layout of protocol<>. using Any = OpaqueExistentialContainer; /// A Reflectable witness table. struct ReflectableWitnessTable { /// func getMirror() -> Mirror Mirror (*getMirror)(OpaqueValue *self, const Metadata *Self); }; struct MagicMirrorData; struct String; extern "C" void swift_stringFromUTF8InRawMemory(String *out, const char *start, intptr_t len); struct String { // Keep the details of String's implementation opaque to the runtime. const void *x, *y, *z; /// Keep String trivial on the C++ side so we can control its instantiation. String() = default; /// Wrap a string literal in a swift String. template explicit String(const char (&s)[N]) { swift_stringFromUTF8InRawMemory(this, s, N-1); } /// Copy an ASCII string into a swift String on the heap. explicit String(const char *ptr, size_t size) { swift_stringFromUTF8InRawMemory(this, ptr, size); } explicit String(const char *ptr) : String(ptr, strlen(ptr)) {} explicit String(NSString *s) // FIXME: Use the usual NSString bridging entry point. : String([s UTF8String]) {} }; struct Array { // Keep the details of Array's implementation opaque to the runtime. const void *x; }; struct QuickLookObject { struct RawData { Array Data; String Type; }; struct Rectangle { double x, y, w, h; }; struct Point { double x, y; }; struct Interval { uint64_t loc,len; }; union { String TextOrURL; int64_t Int; uint64_t UInt; double Float; Any Any; RawData Raw; Rectangle Rect; Point PointOrSize; bool Logical; Interval Range; }; enum class Tag : uint8_t { Text, Int, UInt, Float, Image, Sound, Color, BezierPath, AttributedString, Rectangle, Point, Size, Logical, Range, View, Sprite, URL, Raw, } Kind; }; struct StringMirrorTuple { String first; Mirror second; }; struct OptionalQuickLookObject { union { struct { union { String TextOrURL; int64_t Int; uint64_t UInt; double Float; Any Any; QuickLookObject::RawData Raw; QuickLookObject::Rectangle Rect; QuickLookObject::Point PointOrSize; bool Logical; QuickLookObject::Interval Range; }; QuickLookObject::Tag Kind; bool isNone; } optional; QuickLookObject payload; }; }; /// A Mirror witness table for use by MagicMirror. struct MirrorWitnessTable; /// The protocol descriptor for Reflectable from the stdlib. extern "C" const ProtocolDescriptor _TMpSs11Reflectable; // This structure needs to mirror _MagicMirrorData in the stdlib. struct MagicMirrorData { /// The owner pointer for the buffer the value lives in. For class values /// this is the class instance itself. The mirror owns a strong reference to /// this object. HeapObject *Owner; /// The pointer to the value. The mirror does not own the referenced value. const OpaqueValue *Value; /// The type metadata for the referenced value. For an ObjC witness, this is /// the ObjC class. const Metadata *Type; }; static_assert(sizeof(MagicMirrorData) == sizeof(ValueBuffer), "MagicMirrorData doesn't exactly fill a ValueBuffer"); /// A magic implementation of Mirror that can^Wwill be able to look at runtime /// metadata to walk an arbitrary object. /// /// This type is layout-compatible with a Swift existential /// container for the Mirror protocol. class MagicMirror { public: // The data for the mirror. MagicMirrorData Data; // The existential header. const Metadata *Self; const MirrorWitnessTable *MirrorWitness; MagicMirror() = default; /// Build a new MagicMirror for type T by taking ownership of the referenced /// value. MagicMirror(OpaqueValue *value, const Metadata *T, bool take); /// Build a new MagicMirror for type T, sharing ownership with an existing /// heap object, which is retained. MagicMirror(HeapObject *owner, const OpaqueValue *value, const Metadata *T); }; static_assert(alignof(MagicMirror) == alignof(Mirror), "MagicMirror layout does not match existential container"); static_assert(sizeof(MagicMirror) == sizeof(Mirror), "MagicMirror layout does not match existential container"); static_assert(offsetof(MagicMirror, Data) == offsetof(OpaqueExistentialContainer, Buffer), "MagicMirror layout does not match existential container"); static_assert(offsetof(MagicMirror, Self) == offsetof(OpaqueExistentialContainer, Type), "MagicMirror layout does not match existential container"); static_assert(offsetof(MagicMirror, MirrorWitness) == offsetof(Mirror, MirrorWitness), "MagicMirror layout does not match existential container"); // -- Build an Any from an arbitrary value unowned-referenced by a mirror. extern "C" Any swift_MagicMirrorData_value(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { Any result; result.Type = type; type->vw_initializeBufferWithCopy(&result.Buffer, const_cast(value)); swift_release(owner); return result; } extern "C" const Metadata *swift_MagicMirrorData_valueType(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { auto r = type->vw_typeOf(const_cast(value)); swift_release(owner); return r; } extern "C" Any swift_MagicMirrorData_objcValue(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { Any result; id object = *reinterpret_cast(value); auto isa = reinterpret_cast(object_getClass(object)); result.Type = swift_getObjCClassMetadata(isa); *reinterpret_cast(&result.Buffer) = [object retain]; swift_release(owner); return result; } extern "C" const Metadata *swift_MagicMirrorData_objcValueType(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { id object = *reinterpret_cast(value); auto isa = reinterpret_cast(object_getClass(object)); swift_release(owner); return swift_getObjCClassMetadata(isa); } // -- Tuple destructuring. extern "C" intptr_t swift_TupleMirror_count(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { auto Tuple = static_cast(type); swift_release(owner); return Tuple->NumElements; } extern "C" StringMirrorTuple swift_TupleMirror_subscript(intptr_t i, HeapObject *owner, const OpaqueValue *value, const Metadata *type) { StringMirrorTuple result; auto Tuple = static_cast(type); if (i < 0 || (size_t)i > Tuple->NumElements) swift::crash("Swift mirror subscript bounds check failure"); // The name is the stringized element number '.0'. char buf[32]; snprintf(buf, 31, ".%zd", i); buf[31] = 0; result.first = String(buf, strlen(buf)); // Get a Mirror for the nth element. auto &elt = Tuple->getElements()[i]; auto bytes = reinterpret_cast(value); auto eltData = reinterpret_cast(bytes + elt.Offset); result.second = swift_unsafeReflectAny(owner, eltData, elt.Type); return result; } // -- Struct destructuring. extern "C" intptr_t swift_StructMirror_count(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { auto Struct = static_cast(type); swift_release(owner); return Struct->Description->Struct.NumFields; } extern "C" StringMirrorTuple swift_StructMirror_subscript(intptr_t i, HeapObject *owner, const OpaqueValue *value, const Metadata *type) { StringMirrorTuple result; auto Struct = static_cast(type); if (i < 0 || (size_t)i > Struct->Description->Struct.NumFields) swift::crash("Swift mirror subscript bounds check failure"); // Load the type and offset from their respective vectors. auto fieldType = Struct->getFieldTypes()[i]; auto fieldOffset = Struct->getFieldOffsets()[i]; auto bytes = reinterpret_cast(value); auto fieldData = reinterpret_cast(bytes + fieldOffset); // Get the field name from the doubly-null-terminated list. const char *fieldName = Struct->Description->Struct.FieldNames; for (size_t j = 0; j < (size_t)i; ++j) { while (*fieldName++); } result.first = String(fieldName); result.second = swift_unsafeReflectAny(owner, fieldData, fieldType); return result; } // -- Class destructuring. static bool classHasSuperclass(const ClassMetadata *c) { // A class does not have a superclass if its ObjC superclass is the // "SwiftObject" root class. return c->SuperClass && (Class)c->SuperClass != NSClassFromString(@"SwiftObject"); } static Mirror getMirrorForSuperclass(const ClassMetadata *sup, HeapObject *owner, const OpaqueValue *value, const Metadata *type); extern "C" intptr_t swift_ClassMirror_count(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { auto Clas = static_cast(type); swift_release(owner); auto count = Clas->getDescription()->Class.NumFields; // If the class has a superclass, the superclass instance is treated as the // first child. if (classHasSuperclass(Clas)) count += 1; return count; } extern "C" StringMirrorTuple swift_ClassMirror_subscript(intptr_t i, HeapObject *owner, const OpaqueValue *value, const Metadata *type) { StringMirrorTuple result; auto Clas = static_cast(type); if (classHasSuperclass(Clas)) { // If the class has a superclass, the superclass instance is treated as the // first child. if (i == 0) { // FIXME: Put superclass name here result.first = String("super"); result.second = getMirrorForSuperclass(Clas->SuperClass, owner, value, type); return result; } --i; } if (i < 0 || (size_t)i > Clas->getDescription()->Class.NumFields) swift::crash("Swift mirror subscript bounds check failure"); // Load the type and offset from their respective vectors. auto fieldType = Clas->getFieldTypes()[i]; auto fieldOffset = Clas->getFieldOffsets()[i]; auto bytes = *reinterpret_cast(value); auto fieldData = reinterpret_cast(bytes + fieldOffset); // Get the field name from the doubly-null-terminated list. const char *fieldName = Clas->getDescription()->Class.FieldNames; for (size_t j = 0; j < (size_t)i; ++j) { while (*fieldName++); } result.first = String(fieldName); result.second = swift_unsafeReflectAny(owner, fieldData, fieldType); return result; } // -- Mirror witnesses for ObjC classes. extern "C" const FullMetadata _TMdSb; // Bool extern "C" const FullMetadata _TMdSi; // Int extern "C" const FullMetadata _TMdSu; // UInt extern "C" const FullMetadata _TMdSf; // Float extern "C" const FullMetadata _TMdSd; // Double extern "C" const FullMetadata _TMdVSs4Int8; extern "C" const FullMetadata _TMdVSs5Int16; extern "C" const FullMetadata _TMdVSs5Int32; extern "C" const FullMetadata _TMdVSs5Int64; extern "C" const FullMetadata _TMdVSs5UInt8; extern "C" const FullMetadata _TMdVSs6UInt16; extern "C" const FullMetadata _TMdVSs6UInt32; extern "C" const FullMetadata _TMdVSs6UInt64; // Set to 1 to enable reflection of objc ivars. #define REFLECT_OBJC_IVARS 0 /// Map an ObjC type encoding string to a Swift type metadata object. /// #if REFLECT_OBJC_IVARS static const Metadata *getMetadataForEncoding(const char *encoding) { switch (*encoding) { case 'c': // char return &_TMdVSs4Int8; case 's': // short return &_TMdVSs5Int16; case 'i': // int return &_TMdVSs5Int32; case 'l': // long return &_TMdSi; case 'q': // long long return &_TMdVSs5Int64; case 'C': // unsigned char return &_TMdVSs5UInt8; case 'S': // unsigned short return &_TMdVSs6UInt16; case 'I': // unsigned int return &_TMdVSs6UInt32; case 'L': // unsigned long return &_TMdSu; case 'Q': // unsigned long long return &_TMdVSs6UInt64; case 'B': // _Bool return &_TMdSb; case '@': { // Class // TODO: Better metadata? const OpaqueMetadata *M = &_TMdBO; return &M->base; } default: // TODO // Return 'void' as the type of fields we don't understand. return &_TMdT_; } } #endif extern "C" intptr_t swift_ObjCMirror_count(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { #if REFLECT_OBJC_IVARS auto isa = (Class)type; unsigned count; // Don't reflect ivars of classes that lie about their layout. if (objcClassLiesAboutLayout(isa)) { count = 0; } else { // Copying the ivar list just to free it is lame, but we have // nowhere to save it. Ivar *ivars = class_copyIvarList(isa, &count); free(ivars); } // The superobject counts as a child. if (class_getSuperclass(isa)) count += 1; swift_release(owner); return count; #else // ObjC makes no guarantees about the state of ivars, so we can't safely // introspect them in the general case. return 0; #endif } static Mirror ObjC_getMirrorForSuperclass(Class sup, HeapObject *owner, const OpaqueValue *value, const Metadata *type); extern "C" StringMirrorTuple swift_ObjCMirror_subscript(intptr_t i, HeapObject *owner, const OpaqueValue *value, const Metadata *type) { #if REFLECT_OBJC_IVARS id object = *reinterpret_cast(value); auto isa = (Class)type; // If there's a superclass, it becomes the first child. if (auto sup = class_getSuperclass(isa)) { if (i == 0) { StringMirrorTuple result; const char *supName = class_getName(sup); result.first = String(supName, strlen(supName)); result.second = ObjC_getMirrorForSuperclass(sup, owner, value, type); return result; } --i; } // Copying the ivar list just to free it is lame, but we have // no room to save it. unsigned count; Ivar *ivars; // Don't reflect ivars of classes that lie about their layout. if (objcClassLiesAboutLayout(isa)) { count = 0; ivars = nullptr; } else { // Copying the ivar list just to free it is lame, but we have // nowhere to save it. ivars = class_copyIvarList(isa, &count); } if (i < 0 || (uintptr_t)i >= (uintptr_t)count) swift::crash("Swift mirror subscript bounds check failure"); const char *name = ivar_getName(ivars[i]); ptrdiff_t offset = ivar_getOffset(ivars[i]); const char *typeEncoding = ivar_getTypeEncoding(ivars[i]); free(ivars); const OpaqueValue *ivar = reinterpret_cast( reinterpret_cast(object) + offset); const Metadata *ivarType = getMetadataForEncoding(typeEncoding); StringMirrorTuple result; result.first = String(name, strlen(name)); result.second = swift_unsafeReflectAny(owner, ivar, ivarType); return result; #else // ObjC makes no guarantees about the state of ivars, so we can't safely // introspect them in the general case. abort(); #endif } extern "C" OptionalQuickLookObject swift_ObjCMirror_quickLookObject(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { OptionalQuickLookObject result; memset(&result, 0, sizeof(result)); id object = [*reinterpret_cast(value) retain]; swift_release(owner); if ([object respondsToSelector:@selector(debugQuickLookObject)]) object = [object debugQuickLookObject]; // NSNumbers quick-look as integers or doubles, depending on type. if ([object isKindOfClass:[NSNumber class]]) { NSNumber *n = object; switch ([n objCType][0]) { case 'd': // double case 'f': // float result.payload.Float = [n doubleValue]; result.payload.Kind = QuickLookObject::Tag::Float; break; case 'Q': // unsigned long long result.payload.UInt = [n unsignedLongLongValue]; result.payload.Kind = QuickLookObject::Tag::UInt; break; // FIXME: decimals? default: result.payload.Int = [n longLongValue]; result.payload.Kind = QuickLookObject::Tag::Int; break; } result.optional.isNone = false; return result; } // Various other framework types are used for rich representations. /// Store an ObjC reference into an Any. auto setAnyToObject = [](Any &any, id obj) { any.Type = swift_getObjCClassMetadata( reinterpret_cast(object_getClass(obj))); *reinterpret_cast(&any.Buffer) = [obj retain]; }; if ([object isKindOfClass:NSClassFromString(@"NSAttributedString")]) { setAnyToObject(result.payload.Any, object); result.payload.Kind = QuickLookObject::Tag::AttributedString; result.optional.isNone = false; return result; } else if ([object isKindOfClass:NSClassFromString(@"NSImage")] || [object isKindOfClass:NSClassFromString(@"UIImage")] || [object isKindOfClass:NSClassFromString(@"NSImageView")] || [object isKindOfClass:NSClassFromString(@"UIImageView")] || [object isKindOfClass:NSClassFromString(@"CIImage")] || [object isKindOfClass:NSClassFromString(@"NSBitmapImageRep")]) { setAnyToObject(result.payload.Any, object); result.payload.Kind = QuickLookObject::Tag::Image; result.optional.isNone = false; return result; } else if ([object isKindOfClass:NSClassFromString(@"NSColor")] || [object isKindOfClass:NSClassFromString(@"UIColor")]) { setAnyToObject(result.payload.Any, object); result.payload.Kind = QuickLookObject::Tag::Color; result.optional.isNone = false; return result; } else if ([object isKindOfClass:NSClassFromString(@"NSBezierPath")] || [object isKindOfClass:NSClassFromString(@"UIBezierPath")]) { setAnyToObject(result.payload.Any, object); result.payload.Kind = QuickLookObject::Tag::BezierPath; result.optional.isNone = false; return result; } // Return none if we didn't get a suitable object. result.optional.isNone = true; return result; } // -- MagicMirror implementation. // Addresses of the type metadata and Mirror witness tables for the primitive // mirrors. extern "C" const FullMetadata _TMdVSs13_OpaqueMirror; extern "C" const MirrorWitnessTable _TWPVSs13_OpaqueMirrorSs6Mirror; extern "C" const FullMetadata _TMdVSs12_TupleMirror; extern "C" const MirrorWitnessTable _TWPVSs12_TupleMirrorSs6Mirror; extern "C" const FullMetadata _TMdVSs13_StructMirror; extern "C" const MirrorWitnessTable _TWPVSs13_StructMirrorSs6Mirror; extern "C" const FullMetadata _TMdVSs12_ClassMirror; extern "C" const MirrorWitnessTable _TWPVSs12_ClassMirrorSs6Mirror; extern "C" const FullMetadata _TMdVSs17_ClassSuperMirror; extern "C" const MirrorWitnessTable _TWPVSs17_ClassSuperMirrorSs6Mirror; // These type metadata objects are kept in swiftFoundation because they rely // on string bridging being installed. static const Metadata *getObjCMirrorMetadata() { static const Metadata *metadata = nullptr; if (!metadata) metadata = reinterpret_cast*>( dlsym(RTLD_DEFAULT, "_TMdV10Foundation11_ObjCMirror")); assert(metadata); return metadata; } static const MirrorWitnessTable *getObjCMirrorWitness() { static const MirrorWitnessTable *witness = nullptr; if (!witness) witness = reinterpret_cast( dlsym(RTLD_DEFAULT, "_TWPV10Foundation11_ObjCMirrorSs6Mirror")); assert(witness); return witness; } static const Metadata *getObjCSuperMirrorMetadata() { static const Metadata *metadata = nullptr; if (!metadata) metadata = reinterpret_cast*>( dlsym(RTLD_DEFAULT, "_TMdV10Foundation16_ObjCSuperMirror")); assert(metadata); return metadata; } static const MirrorWitnessTable *getObjCSuperMirrorWitness() { static const MirrorWitnessTable *witness = nullptr; if (!witness) witness = reinterpret_cast( dlsym(RTLD_DEFAULT, "_TWPV10Foundation16_ObjCSuperMirrorSs6Mirror")); assert(witness); return witness; } static Mirror getMirrorForSuperclass(const ClassMetadata *sup, HeapObject *owner, const OpaqueValue *value, const Metadata *type) { // If the superclass is natively ObjC, cut over to the ObjC mirror // implementation. if (!sup->isTypeMetadata()) return ObjC_getMirrorForSuperclass((Class)sup, owner, value, type); Mirror resultBuf; MagicMirror *result = ::new (&resultBuf) MagicMirror; result->Self = &_TMdVSs17_ClassSuperMirror; result->MirrorWitness = &_TWPVSs17_ClassSuperMirrorSs6Mirror; result->Data.Owner = owner; result->Data.Type = sup; result->Data.Value = value; return resultBuf; } static Mirror ObjC_getMirrorForSuperclass(Class sup, HeapObject *owner, const OpaqueValue *value, const Metadata *type) { Mirror resultBuf; MagicMirror *result = ::new (&resultBuf) MagicMirror; result->Self = getObjCSuperMirrorMetadata(); result->MirrorWitness = getObjCSuperMirrorWitness(); result->Data.Owner = owner; result->Data.Type = reinterpret_cast(sup); result->Data.Value = value; return resultBuf; } // (type being mirrored, mirror type, mirror witness) using MirrorTriple = std::tuple; static MirrorTriple getImplementationForClass(const OpaqueValue *Value) { // Get the runtime type of the object. id obj = *reinterpret_cast(Value); auto isa = reinterpret_cast(object_getClass(obj)); // If this is a pure ObjC class, reflect it using ObjC's runtime facilities. if (!isa->isTypeMetadata()) return {isa, getObjCMirrorMetadata(), getObjCMirrorWitness()}; // Otherwise, use the native Swift facilities. return {isa, &_TMdVSs12_ClassMirror, &_TWPVSs12_ClassMirrorSs6Mirror}; } /// Get the magic mirror witnesses appropriate to a particular type. static MirrorTriple getImplementationForType(const Metadata *T, const OpaqueValue *Value) { switch (T->getKind()) { case MetadataKind::Tuple: return {T, &_TMdVSs12_TupleMirror, &_TWPVSs12_TupleMirrorSs6Mirror}; case MetadataKind::Struct: return {T, &_TMdVSs13_StructMirror, &_TWPVSs13_StructMirrorSs6Mirror}; case MetadataKind::ObjCClassWrapper: case MetadataKind::ForeignClass: case MetadataKind::Class: { return getImplementationForClass(Value); } case MetadataKind::Opaque: { // If this is the Builtin.UnknownObject type, use the dynamic type of the // object reference. if (T == &_TMdBO.base) { return getImplementationForClass(Value); } // If this is the Builtin.NativeObject type, and the heap object is a // class instance, use the dynamic type of the object reference. if (T == &_TMdBo.base) { const HeapObject *obj = *reinterpret_cast(Value); if (obj->metadata->getKind() == MetadataKind::Class) return getImplementationForClass(Value); } SWIFT_FALLTHROUGH; } /// TODO: Implement specialized mirror witnesses for all kinds. case MetadataKind::Enum: case MetadataKind::Function: case MetadataKind::Existential: case MetadataKind::ExistentialMetatype: case MetadataKind::Metatype: return {T, &_TMdVSs13_OpaqueMirror, &_TWPVSs13_OpaqueMirrorSs6Mirror}; // Types can't have these kinds. case MetadataKind::PolyFunction: case MetadataKind::HeapLocalVariable: case MetadataKind::HeapArray: swift::crash("Swift mirror lookup failure"); } } /// MagicMirror ownership-taking whole-value constructor. MagicMirror::MagicMirror(OpaqueValue *value, const Metadata *T, bool take) { // Put value types into a box so we can take stable interior pointers. // TODO: Specialize behavior here. If the value is a swift-refcounted class // we don't need to put it in a box to point into it. BoxPair box = swift_allocBox(T); if (take) T->vw_initializeWithTake(box.value, value); else T->vw_initializeWithCopy(box.value, value); std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.value); Data = {box.heapObject, box.value, T}; } /// MagicMirror ownership-sharing subvalue constructor. MagicMirror::MagicMirror(HeapObject *owner, const OpaqueValue *value, const Metadata *T) { std::tie(T, Self, MirrorWitness) = getImplementationForType(T, value); Data = {owner, value, T}; } static std::tuple getReflectableConformance(const Metadata *T, const OpaqueValue *Value) { // If the value is an existential container, look through it to reflect the // contained value. switch (T->getKind()) { case MetadataKind::Tuple: case MetadataKind::Struct: case MetadataKind::ForeignClass: case MetadataKind::ObjCClassWrapper: case MetadataKind::Class: case MetadataKind::Opaque: case MetadataKind::Enum: case MetadataKind::Function: case MetadataKind::Metatype: break; case MetadataKind::Existential: { auto existential = static_cast(T); // If the existential happens to include the Reflectable protocol, use // the witness table from the container. unsigned wtOffset = 0; for (unsigned i = 0; i < existential->Protocols.NumProtocols; ++i) { if (existential->Protocols[i] == &_TMpSs11Reflectable) { return { reinterpret_cast( existential->getWitnessTable(Value, wtOffset)), existential->getDynamicType(Value), existential->projectValue(Value) }; } if (existential->Protocols[i]->Flags.needsWitnessTable()) ++wtOffset; } // Otherwise, unwrap the existential container and do a runtime lookup on // its contained value as usual. T = existential->getDynamicType(Value); Value = existential->projectValue(Value); break; } case MetadataKind::ExistentialMetatype: // TODO: Should look through existential metatypes too, but it doesn't // really matter yet since we don't have any special mirror behavior for // concrete metatypes yet. break; // Types can't have these kinds. case MetadataKind::PolyFunction: case MetadataKind::HeapLocalVariable: case MetadataKind::HeapArray: swift::crash("Swift mirror lookup failure"); } return { reinterpret_cast( swift_conformsToProtocol(T, &_TMpSs11Reflectable, nullptr)), T, Value }; } } // end anonymous namespace /// func reflect(x: T) -> Mirror /// /// Produce a mirror for any value. If the value's type conforms to Reflectable, /// invoke its getMirror() method; otherwise, fall back to an implementation /// in the runtime that structurally reflects values of any type. /// /// This function consumes 'value', following Swift's +1 convention for in /// arguments. Mirror swift::swift_reflectAny(OpaqueValue *value, const Metadata *T) { const ReflectableWitnessTable *witness; const Metadata *mirrorType; const OpaqueValue *cMirrorValue; std::tie(witness, mirrorType, cMirrorValue) = getReflectableConformance(T, value); OpaqueValue *mirrorValue = const_cast(cMirrorValue); // Use the Reflectable conformance if the object has one. if (witness) { auto result = witness->getMirror(mirrorValue, mirrorType); // 'self' of witnesses is passed at +0, so we still need to consume the // value. T->vw_destroy(value); return result; } // Otherwise, fall back to MagicMirror. Mirror result; // Take the value, unless we projected a subvalue from it. We don't want to // deal with partial value deinitialization. bool take = mirrorValue == value; ::new (&result) MagicMirror(mirrorValue, mirrorType, take); // Destroy the whole original value if we couldn't take it. if (!take) T->vw_destroy(value); return result; } /// Produce a mirror for any value, like swift_reflectAny, but do not consume /// the value, so we can produce a mirror for a subobject of a value already /// owned by a mirror. Mirror swift::swift_unsafeReflectAny(HeapObject *owner, const OpaqueValue *value, const Metadata *T) { const ReflectableWitnessTable *witness; const Metadata *mirrorType; const OpaqueValue *mirrorValue; std::tie(witness, mirrorType, mirrorValue) = getReflectableConformance(T, value); // Use the Reflectable conformance if the object has one. if (witness) { return witness->getMirror(const_cast(mirrorValue), mirrorType); } // Otherwise, fall back to MagicMirror. Mirror result; ::new (&result) MagicMirror(owner, mirrorValue, mirrorType); return result; }