//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "swift/Runtime/Reflection.h" #include "swift/Runtime/Casting.h" #include "swift/Runtime/Config.h" #include "swift/Runtime/HeapObject.h" #include "swift/Runtime/Metadata.h" #include "swift/Runtime/Enum.h" #include "swift/Runtime/Unreachable.h" #include "swift/Demangling/Demangle.h" #include "swift/Runtime/Debug.h" #include "swift/Runtime/Portability.h" #include "Private.h" #include "WeakReference.h" #include "llvm/Support/Compiler.h" #include #include #include #include #include #include #if SWIFT_OBJC_INTEROP #include "swift/Runtime/ObjCBridge.h" #include #include #include #endif using namespace swift; #if SWIFT_OBJC_INTEROP // Declare the debugQuickLookObject selector. @interface DeclareSelectors - (id)debugQuickLookObject; @end @class SwiftObject; #endif namespace { /// The layout of Any. using Any = OpaqueExistentialContainer; // Swift assumes Any is returned in memory. // Use AnyReturn to guarantee that even on architectures // where Any would be returned in registers. struct AnyReturn { Any any; AnyReturn(Any a) : any(a) { } operator Any() { return any; } ~AnyReturn() { } }; struct MagicMirrorData; struct String; SWIFT_CC(swift) 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)) {} #if SWIFT_OBJC_INTEROP explicit String(NSString *s) // FIXME: Use the usual NSString bridging entry point. : String([s UTF8String]) {} #endif }; /// A Mirror witness table for use by MagicMirror. struct MirrorWitnessTable; // 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 use 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. // We intentionally use a non-POD return type with these entry points to give // them an indirect return ABI for compatibility with Swift. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreturn-type-c-linkage" SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE AnyReturn swift_MagicMirrorData_value(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { Any result; result.Type = type; auto *opaqueValueAddr = type->allocateBoxForExistentialIn(&result.Buffer); type->vw_initializeWithCopy(opaqueValueAddr, const_cast(value)); return AnyReturn(result); } SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE const Metadata *swift_MagicMirrorData_valueType(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { return swift_getDynamicType(const_cast(value), type, /*existential metatype*/ true); } #if SWIFT_OBJC_INTEROP SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE AnyReturn swift_MagicMirrorData_objcValue(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { Any result; void *object = *reinterpret_cast(value); auto isa = _swift_getClass(object); result.Type = swift_getObjCClassMetadata(isa); swift_unknownRetain(object); *reinterpret_cast(&result.Buffer) = object; return AnyReturn(result); } #endif #pragma clang diagnostic pop SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE const char *swift_OpaqueSummary(const Metadata *T) { switch (T->getKind()) { case MetadataKind::Class: case MetadataKind::Struct: case MetadataKind::Enum: case MetadataKind::Optional: case MetadataKind::Metatype: return nullptr; case MetadataKind::Opaque: return "(Opaque Value)"; case MetadataKind::Tuple: return "(Tuple)"; case MetadataKind::Function: return "(Function)"; case MetadataKind::Existential: return "(Existential)"; case MetadataKind::ObjCClassWrapper: return "(Objective-C Class Wrapper)"; case MetadataKind::ExistentialMetatype: return "(Existential Metatype)"; case MetadataKind::ForeignClass: return "(Foreign Class)"; case MetadataKind::HeapLocalVariable: return "(Heap Local Variable)"; case MetadataKind::HeapGenericLocalVariable: return "(Heap Generic Local Variable)"; case MetadataKind::ErrorObject: return "(ErrorType Object)"; } swift_runtime_unreachable("Unhandled MetadataKind in switch."); } SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE void swift_MagicMirrorData_summary(const Metadata *T, String *result) { switch (T->getKind()) { case MetadataKind::Class: new (result) String("(Class)"); break; case MetadataKind::Struct: new (result) String("(Struct)"); break; case MetadataKind::Enum: case MetadataKind::Optional: new (result) String("(Enum Value)"); break; case MetadataKind::Opaque: new (result) String("(Opaque Value)"); break; case MetadataKind::Tuple: new (result) String("(Tuple)"); break; case MetadataKind::Function: new (result) String("(Function)"); break; case MetadataKind::Existential: new (result) String("(Existential)"); break; case MetadataKind::Metatype: new (result) String("(Metatype)"); break; case MetadataKind::ObjCClassWrapper: new (result) String("(Objective-C Class Wrapper)"); break; case MetadataKind::ExistentialMetatype: new (result) String("(ExistentialMetatype)"); break; case MetadataKind::ForeignClass: new (result) String("(Foreign Class)"); break; case MetadataKind::HeapLocalVariable: new (result) String("(Heap Local Variable)"); break; case MetadataKind::HeapGenericLocalVariable: new (result) String("(Heap Generic Local Variable)"); break; case MetadataKind::ErrorObject: new (result) String("(Error Object)"); break; } } SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE const Metadata *swift_MagicMirrorData_objcValueType(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { void *object = *reinterpret_cast(value); auto isa = _swift_getClass(object); return swift_getObjCClassMetadata(isa); } static std::tuple unwrapExistential(const Metadata *T, const OpaqueValue *Value) { // If the value is an existential container, look through it to reflect the // contained value. // 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. while (T->getKind() == MetadataKind::Existential) { auto existential = static_cast(T); // Unwrap the existential container. T = existential->getDynamicType(Value); Value = existential->projectValue(Value); // Existential containers can end up nested in some cases due to generic // abstraction barriers. Repeat in case we have a nested existential. } return std::make_tuple(T, Value); } /// 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. /// /// \param owner passed at +1, consumed. /// \param value passed unowned. static Mirror reflect(HeapObject *owner, const OpaqueValue *value, const Metadata *T) { const Metadata *mirrorType; const OpaqueValue *mirrorValue; std::tie(mirrorType, mirrorValue) = unwrapExistential(T, value); // Use MagicMirror. // Consumes 'owner'. Mirror result; ::new (&result) MagicMirror(owner, mirrorValue, mirrorType); return result; } // -- Tuple destructuring. SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE intptr_t swift_TupleMirror_count(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { auto Tuple = static_cast(type); swift_release(owner); return Tuple->NumElements; } /// \param owner passed at +1, consumed. /// \param value passed unowned. SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE void swift_TupleMirror_subscript(String *outString, Mirror *outMirror, intptr_t i, HeapObject *owner, const OpaqueValue *value, const Metadata *type) { auto Tuple = static_cast(type); if (i < 0 || (size_t)i > Tuple->NumElements) swift::crash("Swift mirror subscript bounds check failure"); // Determine whether there is a label. bool hasLabel = false; if (const char *labels = Tuple->Labels) { const char *space = strchr(labels, ' '); for (intptr_t j = 0; j != i && space; ++j) { labels = space + 1; space = strchr(labels, ' '); } // If we have a label, create it. if (labels && space && labels != space) { new (outString) String(labels, space - labels); hasLabel = true; } } if (!hasLabel) { // The name is the stringized element number '.0'. char buf[32]; snprintf(buf, sizeof(buf), ".%zd", i); new (outString) String(buf, strlen(buf)); } // Get a Mirror for the nth element. auto &elt = Tuple->getElement(i); auto bytes = reinterpret_cast(value); auto eltData = reinterpret_cast(bytes + elt.Offset); // 'owner' is consumed by this call. new (outMirror) Mirror(reflect(owner, eltData, elt.Type)); } // Get a field name from a doubly-null-terminated list. static const char *getFieldName(const char *fieldNames, size_t i) { const char *fieldName = fieldNames; for (size_t j = 0; j < i; ++j) { size_t len = strlen(fieldName); assert(len != 0); fieldName += len + 1; } return fieldName; } static bool loadSpecialReferenceStorage(HeapObject *owner, OpaqueValue *fieldData, const FieldType fieldType, Mirror *outMirror) { // isWeak() implies a reference type via Sema. if (!fieldType.isWeak()) return false; auto type = fieldType.getType(); assert(type->getKind() == MetadataKind::Optional); auto weakField = reinterpret_cast(fieldData); auto strongValue = swift_unknownWeakLoadStrong(weakField); // Now that we have a strong reference, we need to create a temporary buffer // from which to copy the whole value, which might be a native class-bound // existential, which means we also need to copy n witness tables, for // however many protocols are in the protocol composition. For example, if we // are copying a: // weak var myWeakProperty : (Protocol1 & Protocol2)? // then we need to copy three values: // - the instance // - the witness table for Protocol1 // - the witness table for Protocol2 auto weakContainer = reinterpret_cast(fieldData); // Create a temporary existential where we can put the strong reference. // The allocateBuffer value witness requires a ValueBuffer to own the // allocated storage. ValueBuffer temporaryBuffer; auto temporaryValue = reinterpret_cast( type->allocateBufferIn(&temporaryBuffer)); // Now copy the entire value out of the parent, which will include the // witness tables. temporaryValue->Value = strongValue; auto valueWitnessesSize = type->getValueWitnesses()->getSize() - sizeof(WeakClassExistentialContainer); memcpy(temporaryValue->getWitnessTables(), weakContainer->getWitnessTables(), valueWitnessesSize); // This MagicMirror constructor creates a box to hold the loaded reference // value, which becomes the new owner for the value. new (outMirror) MagicMirror(reinterpret_cast(temporaryValue), type, /*take*/ true); type->deallocateBufferIn(&temporaryBuffer); // swift_StructMirror_subscript and swift_ClassMirror_subscript // requires that the owner be consumed. Since we have the new heap box as the // owner now, we need to release the old owner to maintain the contract. if (owner->metadata->isAnyClass()) swift_unknownRelease(owner); else swift_release(owner); return true; } // -- Struct destructuring. SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE 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; } SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE void swift_StructMirror_subscript(String *outString, Mirror *outMirror, intptr_t i, HeapObject *owner, OpaqueValue *value, const Metadata *type) { 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); new (outString) String(getFieldName(Struct->Description->Struct.FieldNames, i)); // 'owner' is consumed by this call. assert(!fieldType.isIndirect() && "indirect struct fields not implemented"); if (loadSpecialReferenceStorage(owner, fieldData, fieldType, outMirror)) return; new (outMirror) Mirror(reflect(owner, fieldData, fieldType.getType())); } // -- Enum destructuring. static bool isEnumReflectable(const Metadata *type) { const auto Enum = static_cast(type); const auto &Description = Enum->Description->Enum; // No metadata for C and @objc enums yet if (Description.CaseNames == nullptr) return false; return true; } static void getEnumMirrorInfo(const OpaqueValue *value, const Metadata *type, unsigned *tagPtr, const Metadata **payloadTypePtr, bool *indirectPtr) { const auto Enum = static_cast(type); const auto &Description = Enum->Description->Enum; unsigned payloadCases = Description.getNumPayloadCases(); // 'tag' is in the range [-ElementsWithPayload..ElementsWithNoPayload-1]. int tag = type->vw_getEnumTag(value); // Convert resilient tag index to fragile tag index. tag += payloadCases; const Metadata *payloadType = nullptr; bool indirect = false; if (static_cast(tag) < payloadCases) { auto payload = Description.GetCaseTypes(type)[tag]; payloadType = payload.getType(); indirect = payload.isIndirect(); } if (tagPtr) *tagPtr = tag; if (payloadTypePtr) *payloadTypePtr = payloadType; if (indirectPtr) *indirectPtr = indirect; } SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE const char *swift_EnumMirror_caseName(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { if (!isEnumReflectable(type)) { swift_release(owner); return nullptr; } const auto Enum = static_cast(type); const auto &Description = Enum->Description->Enum; unsigned tag; getEnumMirrorInfo(value, type, &tag, nullptr, nullptr); swift_release(owner); return getFieldName(Description.CaseNames, tag); } SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE const char *swift_EnumCaseName(OpaqueValue *value, const Metadata *type) { // Build a magic mirror. Unconditionally destroy the value at the end. const Metadata *mirrorType; const OpaqueValue *cMirrorValue; std::tie(mirrorType, cMirrorValue) = unwrapExistential(type, value); OpaqueValue *mirrorValue = const_cast(cMirrorValue); Mirror mirror; bool take = mirrorValue == value; ::new (&mirror) MagicMirror(mirrorValue, mirrorType, take); MagicMirror *theMirror = reinterpret_cast(&mirror); MagicMirrorData data = theMirror->Data; const char *result = swift_EnumMirror_caseName(data.Owner, data.Value, data.Type); return result; } SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE intptr_t swift_EnumMirror_count(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { if (!isEnumReflectable(type)) { swift_release(owner); return 0; } const Metadata *payloadType; getEnumMirrorInfo(value, type, nullptr, &payloadType, nullptr); swift_release(owner); return (payloadType != nullptr) ? 1 : 0; } SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE void swift_EnumMirror_subscript(String *outString, Mirror *outMirror, intptr_t i, HeapObject *owner, const OpaqueValue *value, const Metadata *type) { const auto Enum = static_cast(type); const auto &Description = Enum->Description->Enum; unsigned tag; const Metadata *payloadType; bool indirect; getEnumMirrorInfo(value, type, &tag, &payloadType, &indirect); // Copy the enum payload into a box const Metadata *boxType = (indirect ? &METADATA_SYM(Bo).base : payloadType); BoxPair pair = swift_allocBox(boxType); type->vw_destructiveProjectEnumData(const_cast(value)); boxType->vw_initializeWithCopy(pair.second, const_cast(value)); type->vw_destructiveInjectEnumTag(const_cast(value), (int) (tag - Description.getNumPayloadCases())); swift_release(owner); owner = pair.first; value = pair.second; // If the payload is indirect, we need to jump through the box to get it. if (indirect) { owner = *reinterpret_cast(value); value = swift_projectBox(const_cast(owner)); swift_retain(owner); swift_release(pair.first); } new (outString) String(getFieldName(Description.CaseNames, tag)); new (outMirror) Mirror(reflect(owner, value, payloadType)); } // -- Class destructuring. static Mirror getMirrorForSuperclass(const ClassMetadata *sup, HeapObject *owner, const OpaqueValue *value, const Metadata *type); SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE 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; } /// \param owner passed at +1, consumed. /// \param value passed unowned. SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE void swift_ClassMirror_subscript(String *outString, Mirror *outMirror, intptr_t i, HeapObject *owner, OpaqueValue *value, const Metadata *type) { 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 new (outString) String("super"); new (outMirror) Mirror( getMirrorForSuperclass(Clas->SuperClass, owner, value, type)); return; } --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]; assert(!fieldType.isIndirect() && "class indirect properties not implemented"); // FIXME: If the class has ObjC heritage, get the field offset using the ObjC // metadata, because we don't update the field offsets in the face of // resilient base classes. uintptr_t fieldOffset; if (usesNativeSwiftReferenceCounting(Clas)) { fieldOffset = Clas->getFieldOffsets()[i]; } else { #if SWIFT_OBJC_INTEROP Ivar *ivars = class_copyIvarList((Class)Clas, nullptr); fieldOffset = ivar_getOffset(ivars[i]); free(ivars); #else swift::crash("Object appears to be Objective-C, but no runtime."); #endif } auto bytes = *reinterpret_cast(value); auto fieldData = reinterpret_cast(bytes + fieldOffset); new (outString) String(getFieldName(Clas->getDescription()->Class.FieldNames, i)); if (loadSpecialReferenceStorage(owner, fieldData, fieldType, outMirror)) return; // 'owner' is consumed by this call. new (outMirror) Mirror(reflect(owner, fieldData, fieldType.getType())); } // -- Mirror witnesses for ObjC classes. #if SWIFT_OBJC_INTEROP extern "C" const Metadata METADATA_SYM(Sb); // Bool extern "C" const Metadata METADATA_SYM(Si); // Int extern "C" const Metadata METADATA_SYM(Su); // UInt extern "C" const Metadata METADATA_SYM(Sf); // Float extern "C" const Metadata METADATA_SYM(Sd); // Double extern "C" const Metadata STRUCT_METADATA_SYM(s4Int8); extern "C" const Metadata STRUCT_METADATA_SYM(s5Int16); extern "C" const Metadata STRUCT_METADATA_SYM(s5Int32); extern "C" const Metadata STRUCT_METADATA_SYM(s5Int64); extern "C" const Metadata STRUCT_METADATA_SYM(s5UInt8); extern "C" const Metadata STRUCT_METADATA_SYM(s6UInt16); extern "C" const Metadata STRUCT_METADATA_SYM(s6UInt32); extern "C" const Metadata STRUCT_METADATA_SYM(s6UInt64); // 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 &STRUCT_METADATA_SYM(s4Int8); case 's': // short return &STRUCT_METADATA_SYM(s5Int16); case 'i': // int return &STRUCT_METADATA_SYM(s5Int32); case 'l': // long return &METADATA_SYM(Si); case 'q': // long long return &STRUCT_METADATA_SYM(s5Int64); case 'C': // unsigned char return &STRUCT_METADATA_SYM(s5UInt8); case 'S': // unsigned short return &STRUCT_METADATA_SYM(s6UInt16); case 'I': // unsigned int return &STRUCT_METADATA_SYM(s6UInt32); case 'L': // unsigned long return &METADATA_SYM(Su); case 'Q': // unsigned long long return &STRUCT_METADATA_SYM(s6UInt64); case 'B': // _Bool return &METADATA_SYM(Sb); case '@': { // Class // TODO: Better metadata? const OpaqueMetadata *M = &METADATA_SYM(BO); return &M->base; } default: // TODO // Return 'void' as the type of fields we don't understand. return &METADATA_SYM(EMPTY_TUPLE_MANGLING); } } #endif /// \param owner passed at +1, consumed. /// \param value passed unowned. SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE intptr_t swift_ObjCMirror_count(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { auto isa = (Class)type; unsigned count = 0; #if REFLECT_OBJC_IVARS // 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); } #else // ObjC makes no guarantees about the state of ivars, so we can't safely // introspect them in the general case. // The superobject counts as a child. if (_swift_getSuperclass((const ClassMetadata*) isa)) count += 1; swift_release(owner); return count; #endif } static Mirror ObjC_getMirrorForSuperclass(Class sup, HeapObject *owner, const OpaqueValue *value, const Metadata *type); SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE void swift_ObjCMirror_subscript(String *outString, Mirror *outMirror, intptr_t i, HeapObject *owner, const OpaqueValue *value, const Metadata *type) { #if REFLECT_OBJC_IVARS id object = *reinterpret_cast(value); #endif auto isa = (Class)type; // If there's a superclass, it becomes the first child. if (auto sup = (Class) _swift_getSuperclass((const ClassMetadata*) isa)) { if (i == 0) { const char *supName = class_getName(sup); new (outString) String(supName, strlen(supName)); new (outMirror) Mirror( ObjC_getMirrorForSuperclass(sup, owner, value, type)); return; } --i; } #if REFLECT_OBJC_IVARS // 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); new (outString) String(name, strlen(name)); // 'owner' is consumed by this call. new (outMirror) Mirror(reflect(owner, ivar, ivarType)); #else // ObjC makes no guarantees about the state of ivars, so we can't safely // introspect them in the general case. abort(); #endif } SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE id swift_ClassMirror_quickLookObject(HeapObject *owner, const OpaqueValue *value, const Metadata *type) { id object = [*reinterpret_cast(value) retain]; swift_release(owner); if ([object respondsToSelector:@selector(debugQuickLookObject)]) { id quickLookObject = [object debugQuickLookObject]; [quickLookObject retain]; [object release]; return quickLookObject; } return object; } #endif // -- MagicMirror implementation. #define MIRROR_CONFORMANCE_SYM(Mirror, Subst) \ MANGLE_SYM(Mirror##Vs01_##Subst##0sWP) #define OBJC_MIRROR_CONFORMANCE_SYM() \ MANGLE_SYM(s11_ObjCMirrorVs7_MirrorsWP) // Addresses of the type metadata and Mirror witness tables for the primitive // mirrors. typedef const Metadata *(*MetadataFn)(); extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s13_OpaqueMirror)(); static constexpr auto &OpaqueMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s13_OpaqueMirror); extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s13_OpaqueMirror, B); static constexpr auto &OpaqueMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s13_OpaqueMirror, B); extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s12_TupleMirror)(); static constexpr auto &TupleMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s12_TupleMirror); extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s12_TupleMirror, B); static constexpr auto &TupleMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s12_TupleMirror, B); extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s13_StructMirror)(); static constexpr auto &StructMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s13_StructMirror); extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s13_StructMirror, B); static constexpr auto &StructMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s13_StructMirror, B); extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s11_EnumMirror)(); static constexpr auto &EnumMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s11_EnumMirror); extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s11_EnumMirror, B); static constexpr auto &EnumMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s11_EnumMirror, B); extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s12_ClassMirror)(); static constexpr auto &ClassMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s12_ClassMirror); extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s12_ClassMirror, B); static constexpr auto &ClassMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s12_ClassMirror, B); extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s17_ClassSuperMirror)(); static constexpr auto &ClassSuperMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s17_ClassSuperMirror); extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s17_ClassSuperMirror, C); static constexpr auto &ClassSuperMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s17_ClassSuperMirror, C); extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s15_MetatypeMirror)(); static constexpr auto &MetatypeMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s15_MetatypeMirror); extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s15_MetatypeMirror, B); static constexpr auto &MetatypeMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s15_MetatypeMirror, B); #if SWIFT_OBJC_INTEROP extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s11_ObjCMirror)(); static constexpr auto &ObjCMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s11_ObjCMirror); extern "C" const MirrorWitnessTable OBJC_MIRROR_CONFORMANCE_SYM(); static constexpr auto &ObjCMirrorWitnessTable = OBJC_MIRROR_CONFORMANCE_SYM(); extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s16_ObjCSuperMirror)(); static constexpr auto &ObjCSuperMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s16_ObjCSuperMirror); extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s16_ObjCSuperMirror, C); static constexpr auto &ObjCSuperMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s16_ObjCSuperMirror, C); #endif /// \param owner passed at +1, consumed. /// \param value passed unowned. static Mirror getMirrorForSuperclass(const ClassMetadata *sup, HeapObject *owner, const OpaqueValue *value, const Metadata *type) { #if SWIFT_OBJC_INTEROP // If the superclass is natively ObjC, cut over to the ObjC mirror // implementation. if (!sup->isTypeMetadata()) return ObjC_getMirrorForSuperclass((Class)sup, owner, value, type); #endif Mirror resultBuf; MagicMirror *result = ::new (&resultBuf) MagicMirror; result->Self = ClassSuperMirrorMetadata(); result->MirrorWitness = &ClassSuperMirrorWitnessTable; result->Data.Owner = owner; result->Data.Type = sup; result->Data.Value = value; return resultBuf; } #if SWIFT_OBJC_INTEROP /// \param owner passed at +1, consumed. /// \param value passed unowned. static Mirror ObjC_getMirrorForSuperclass(Class sup, HeapObject *owner, const OpaqueValue *value, const Metadata *type) { Mirror resultBuf; MagicMirror *result = ::new (&resultBuf) MagicMirror; result->Self = ObjCSuperMirrorMetadata(); result->MirrorWitness = &ObjCSuperMirrorWitnessTable; result->Data.Owner = owner; result->Data.Type = reinterpret_cast(sup); result->Data.Value = value; return resultBuf; } #endif // (type being mirrored, mirror type, mirror witness) using MirrorTriple = std::tuple; static MirrorTriple getImplementationForClass(const OpaqueValue *Value) { // Get the runtime type of the object. const void *obj = *reinterpret_cast(Value); auto isa = _swift_getClass(obj); // Look through artificial subclasses. while (isa->isTypeMetadata() && isa->isArtificialSubclass()) { isa = isa->SuperClass; } #if SWIFT_OBJC_INTEROP // If this is a pure ObjC class, reflect it using ObjC's runtime facilities. if (!isa->isTypeMetadata()) return {isa, ObjCMirrorMetadata(), &ObjCMirrorWitnessTable}; #endif // Otherwise, use the native Swift facilities. return std::make_tuple( isa, ClassMirrorMetadata(), &ClassMirrorWitnessTable); } /// 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 std::make_tuple( T, TupleMirrorMetadata(), &TupleMirrorWitnessTable); case MetadataKind::Struct: return std::make_tuple( T, StructMirrorMetadata(), &StructMirrorWitnessTable); case MetadataKind::Enum: case MetadataKind::Optional: return std::make_tuple( T, EnumMirrorMetadata(), &EnumMirrorWitnessTable); case MetadataKind::ObjCClassWrapper: case MetadataKind::ForeignClass: case MetadataKind::Class: { return getImplementationForClass(Value); } case MetadataKind::Metatype: case MetadataKind::ExistentialMetatype: { return std::make_tuple(T, MetatypeMirrorMetadata(), &MetatypeMirrorWitnessTable); } case MetadataKind::Opaque: { #if SWIFT_OBJC_INTEROP // If this is the Builtin.UnknownObject type, use the dynamic type of the // object reference. if (T == &METADATA_SYM(BO).base) { return getImplementationForClass(Value); } #endif // 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 == &METADATA_SYM(Bo).base) { const HeapObject *obj = *reinterpret_cast(Value); if (obj->metadata->getKind() == MetadataKind::Class) return getImplementationForClass(Value); } LLVM_FALLTHROUGH; } /// TODO: Implement specialized mirror witnesses for all kinds. case MetadataKind::Function: case MetadataKind::Existential: return std::make_tuple( T, OpaqueMirrorMetadata(), &OpaqueMirrorWitnessTable); // Types can't have these kinds. case MetadataKind::HeapLocalVariable: case MetadataKind::HeapGenericLocalVariable: case MetadataKind::ErrorObject: swift::crash("Swift mirror lookup failure"); } swift_runtime_unreachable("Unhandled MetadataKind in switch."); } /// MagicMirror ownership-taking whole-value constructor. /// /// \param owner passed at +1, consumed. 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.second, value); else T->vw_initializeWithCopy(box.second, value); std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.second); Data = {box.first, box.second, T}; } /// MagicMirror ownership-sharing subvalue constructor. /// /// \param owner passed at +1, consumed. MagicMirror::MagicMirror(HeapObject *owner, const OpaqueValue *value, const Metadata *T) { std::tie(T, Self, MirrorWitness) = getImplementationForType(T, value); Data = {owner, value, T}; } } // end anonymous namespace /// func reflect(x: T) -> Mirror /// /// Produce a mirror for any value. The runtime produces a mirror that /// structurally reflects values of any type. /// /// This function consumes 'value', following Swift's +1 convention for "in" /// arguments. SWIFT_CC(swift) MirrorReturn swift::swift_reflectAny(OpaqueValue *value, const Metadata *T) { const Metadata *mirrorType; const OpaqueValue *cMirrorValue; std::tie(mirrorType, cMirrorValue) = unwrapExistential(T, value); OpaqueValue *mirrorValue = const_cast(cMirrorValue); // Use 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 MirrorReturn(result); } // NB: This function is not used directly in the Swift codebase, but is // exported for Xcode support and is used by the sanitizers. Please coordinate // before changing. // /// Demangles a Swift symbol name. /// /// \param mangledName is the symbol name that needs to be demangled. /// \param mangledNameLength is the length of the string that should be /// demangled. /// \param outputBuffer is the user provided buffer where the demangled name /// will be placed. If nullptr, a new buffer will be malloced. In that case, /// the user of this API is responsible for freeing the returned buffer. /// \param outputBufferSize is the size of the output buffer. If the demangled /// name does not fit into the outputBuffer, the output will be truncated and /// the size will be updated, indicating how large the buffer should be. /// \param flags can be used to select the demangling style. TODO: We should //// define what these will be. /// \returns the demangled name. Returns nullptr if the input String is not a /// Swift mangled name. SWIFT_RUNTIME_EXPORT char *swift_demangle(const char *mangledName, size_t mangledNameLength, char *outputBuffer, size_t *outputBufferSize, uint32_t flags) { if (flags != 0) { swift::fatalError(0, "Only 'flags' value of '0' is currently supported."); } if (outputBuffer != nullptr && outputBufferSize == nullptr) { swift::fatalError(0, "'outputBuffer' is passed but the size is 'nullptr'."); } // Check if we are dealing with Swift mangled name, otherwise, don't try // to demangle and send indication to the user. if (mangledName[0] != '_' || mangledName[1] != 'T') { return nullptr; } // Demangle the name. auto options = Demangle::DemangleOptions(); options.DisplayDebuggerGeneratedModule = false; auto result = Demangle::demangleSymbolAsString(mangledName, mangledNameLength, options); // If the output buffer is not provided, malloc memory ourselves. if (outputBuffer == nullptr || *outputBufferSize == 0) { return strdup(result.c_str()); } // Indicate a failure if the result does not fit and will be truncated // and set the required outputBufferSize. if (*outputBufferSize < result.length() + 1) { *outputBufferSize = result.length() + 1; } // Copy into the provided buffer. _swift_strlcpy(outputBuffer, result.c_str(), *outputBufferSize); return outputBuffer; }