//===--- Metadata.h - Swift Language ABI Metadata Support -------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// // // Swift ABI describing metadata. // //===----------------------------------------------------------------------===// #ifndef SWIFT_ABI_METADATA_H #define SWIFT_ABI_METADATA_H #include #include #include #include #include #include #include "llvm/ADT/ArrayRef.h" #include "swift/Strings.h" #include "swift/Runtime/Config.h" #include "swift/Runtime/Once.h" #include "swift/ABI/GenericContext.h" #include "swift/ABI/MetadataRef.h" #include "swift/ABI/MetadataValues.h" #include "swift/ABI/System.h" #include "swift/ABI/TargetLayout.h" #include "swift/ABI/TrailingObjects.h" #include "swift/ABI/ValueWitnessTable.h" #include "swift/Basic/Malloc.h" #include "swift/Basic/FlaggedPointer.h" #include "swift/Basic/RelativePointer.h" #include "swift/Demangling/Demangle.h" #include "swift/Demangling/ManglingMacros.h" #include "swift/Basic/Unreachable.h" #include "swift/shims/HeapObject.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Casting.h" namespace swift { template struct TargetGenericMetadataInstantiationCache; template struct TargetAnyClassMetadata; template struct TargetAnyClassMetadataObjCInterop; template struct TargetClassMetadata; template struct TargetStructMetadata; template struct TargetOpaqueMetadata; template struct TargetValueMetadata; template struct TargetForeignClassMetadata; template struct TargetForeignReferenceTypeMetadata; template struct swift_ptrauth_struct_context_descriptor(ContextDescriptor) TargetContextDescriptor; template class swift_ptrauth_struct_context_descriptor(TypeContextDescriptor) TargetTypeContextDescriptor; template class swift_ptrauth_struct_context_descriptor(ClassDescriptor) TargetClassDescriptor; template class swift_ptrauth_struct_context_descriptor(ValueTypeDescriptor) TargetValueTypeDescriptor; template class swift_ptrauth_struct_context_descriptor(EnumDescriptor) TargetEnumDescriptor; template class swift_ptrauth_struct_context_descriptor(StructDescriptor) TargetStructDescriptor; template struct TargetGenericMetadataPattern; template struct TargetProtocolConformanceDescriptor; struct HeapObject; class WeakReference; struct UnownedReference; using HeapObjectDestroyer = SWIFT_CC(swift) void(SWIFT_CONTEXT HeapObject *); /// The result of requesting type metadata. Generally the return value of /// a function. /// /// For performance and ABI matching across Swift/C++, functions returning /// this type must use SWIFT_CC so that the components are returned as separate /// values. struct MetadataResponse { /// The requested metadata. const Metadata *Value; /// The current state of the metadata returned. Always use this /// instead of trying to inspect the metadata directly to see if it /// satisfies the request. An incomplete metadata may be getting /// initialized concurrently. But this can generally be ignored if /// the metadata request was for abstract metadata or if the request /// is blocking. MetadataState State; }; /// A dependency on the metadata progress of other type, indicating that /// initialization of a metadata cannot progress until another metadata /// reaches a particular state. /// /// For performance, functions returning this type should use SWIFT_CC so /// that the components are returned as separate values. struct MetadataDependency { /// Either null, indicating that initialization was successful, or /// a metadata on which initialization depends for further progress. const Metadata *Value; /// The state that Metadata needs to be in before initialization /// can continue. MetadataState Requirement; MetadataDependency() : Value(nullptr) {} MetadataDependency(const Metadata *metadata, MetadataState requirement) : Value(metadata), Requirement(requirement) {} explicit operator bool() const { return Value != nullptr; } bool operator==(MetadataDependency other) const { assert(Value && other.Value); return Value == other.Value && Requirement == other.Requirement; } }; /// Prefix of a metadata header, containing a pointer to the /// type layout string. template struct TargetTypeMetadataLayoutPrefix { TargetSignedPointer layoutString; }; /// The header before a metadata object which appears on all type /// metadata. Note that heap metadata are not necessarily type /// metadata, even for objects of a heap type: for example, objects of /// Objective-C type possess a form of heap metadata (an Objective-C /// Class pointer), but this metadata lacks the type metadata header. /// This case can be distinguished using the isTypeMetadata() flag /// on ClassMetadata. template struct TargetTypeMetadataHeaderBase { /// A pointer to the value-witnesses for this type. This is only /// present for type metadata. TargetPointer> ValueWitnesses; }; template struct TargetTypeMetadataHeader : TargetTypeMetadataLayoutPrefix, TargetTypeMetadataHeaderBase { TargetTypeMetadataHeader() = default; constexpr TargetTypeMetadataHeader( const TargetTypeMetadataLayoutPrefix &layout, const TargetTypeMetadataHeaderBase &header) : TargetTypeMetadataLayoutPrefix(layout), TargetTypeMetadataHeaderBase(header) {} }; using TypeMetadataHeader = TargetTypeMetadataHeader; /// A "full" metadata pointer is simply an adjusted address point on a /// metadata object; it points to the beginning of the metadata's /// allocation, rather than to the canonical address point of the /// metadata object. template struct FullMetadata : T::HeaderType, T { typedef typename T::HeaderType HeaderType; FullMetadata() = default; constexpr FullMetadata(const HeaderType &header, const T &metadata) : HeaderType(header), T(metadata) {} template constexpr FullMetadata(const HeaderType &header, Args &&...metadataArgs) : HeaderType(header), T(std::forward(metadataArgs)...) {} }; /// Given a canonical metadata pointer, produce the adjusted metadata pointer. template static inline FullMetadata *asFullMetadata(T *metadata) { return (FullMetadata*) (((typename T::HeaderType*) metadata) - 1); } template static inline const FullMetadata *asFullMetadata(const T *metadata) { return asFullMetadata(const_cast(metadata)); } // std::result_of is busted in Xcode 5. This is a simplified reimplementation // that isn't SFINAE-safe. namespace { template struct _ResultOf; template struct _ResultOf { using type = R; }; } using TypeContextDescriptor = TargetTypeContextDescriptor; template