//===--- 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 #include #include #include #include "llvm/ADT/ArrayRef.h" #include "swift/Strings.h" #include "swift/Runtime/Config.h" #include "swift/ABI/MetadataValues.h" #include "swift/ABI/System.h" #include "swift/ABI/TrailingObjects.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/Runtime/Unreachable.h" #include "../../../stdlib/public/SwiftShims/HeapObject.h" #if SWIFT_OBJC_INTEROP #include #endif #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Casting.h" namespace swift { template struct RuntimeTarget; template <> struct RuntimeTarget<4> { using StoredPointer = uint32_t; // To avoid implicit conversions from StoredSignedPointer to StoredPointer. using StoredSignedPointer = struct { uint32_t SignedValue; }; using StoredSize = uint32_t; using StoredPointerDifference = int32_t; static constexpr size_t PointerSize = 4; }; template <> struct RuntimeTarget<8> { using StoredPointer = uint64_t; // To avoid implicit conversions from StoredSignedPointer to StoredPointer. using StoredSignedPointer = struct { uint64_t SignedValue; }; using StoredSize = uint64_t; using StoredPointerDifference = int64_t; static constexpr size_t PointerSize = 8; }; namespace reflection { class FieldDescriptor; } /// In-process native runtime target. /// /// For interactions in the runtime, this should be the equivalent of working /// with a plain old pointer type. struct InProcess { static constexpr size_t PointerSize = sizeof(uintptr_t); using StoredPointer = uintptr_t; using StoredSignedPointer = uintptr_t; using StoredSize = size_t; using StoredPointerDifference = ptrdiff_t; static_assert(sizeof(StoredSize) == sizeof(StoredPointerDifference), "target uses differently-sized size_t and ptrdiff_t"); template using Pointer = T*; template using SignedPointer = T; template using FarRelativeDirectPointer = FarRelativeDirectPointer; template using RelativeIndirectablePointer = RelativeIndirectablePointer; template using RelativeDirectPointer = RelativeDirectPointer; }; /// Represents a pointer in another address space. /// /// This type should not have * or -> operators -- you must as a memory reader /// to read the data at the stored address on your behalf. template struct ExternalPointer { using StoredPointer = typename Runtime::StoredPointer; StoredPointer PointerValue; }; /// An external process's runtime target, which may be a different architecture. template struct External { using StoredPointer = typename Runtime::StoredPointer; using StoredSignedPointer = typename Runtime::StoredSignedPointer; using StoredSize = typename Runtime::StoredSize; using StoredPointerDifference = typename Runtime::StoredPointerDifference; static constexpr size_t PointerSize = Runtime::PointerSize; const StoredPointer PointerValue; template using Pointer = StoredPointer; template using SignedPointer = StoredSignedPointer; template using FarRelativeDirectPointer = StoredPointer; template using RelativeIndirectablePointer = int32_t; template using RelativeDirectPointer = int32_t; }; /// Template for branching on native pointer types versus external ones template class Pointee> using TargetMetadataPointer = typename Runtime::template Pointer>; template class Pointee> using ConstTargetMetadataPointer = typename Runtime::template Pointer>; template using TargetPointer = typename Runtime::template Pointer; template using TargetSignedPointer = typename Runtime::template SignedPointer; template using ConstTargetPointer = typename Runtime::template Pointer; template class Pointee, bool Nullable = true> using ConstTargetFarRelativeDirectPointer = typename Runtime::template FarRelativeDirectPointer, Nullable>; template using TargetRelativeDirectPointer = typename Runtime::template RelativeDirectPointer; template using TargetRelativeIndirectablePointer = typename Runtime::template RelativeIndirectablePointer; struct HeapObject; class WeakReference; struct UnownedReference; template struct TargetMetadata; using Metadata = TargetMetadata; /// 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; } }; template struct TargetProtocolConformanceDescriptor; /// Storage for an arbitrary value. In C/C++ terms, this is an /// 'object', because it is rooted in memory. /// /// The context dictates what type is actually stored in this object, /// and so this type is intentionally incomplete. /// /// An object can be in one of two states: /// - An uninitialized object has a completely unspecified state. /// - An initialized object holds a valid value of the type. struct OpaqueValue; /// A fixed-size buffer for local values. It is capable of owning /// (possibly in side-allocated memory) the storage necessary /// to hold a value of an arbitrary type. Because it is fixed-size, /// it can be allocated in places that must be agnostic to the /// actual type: for example, within objects of existential type, /// or for local variables in generic functions. /// /// The context dictates its type, which ultimately means providing /// access to a value witness table by which the value can be /// accessed and manipulated. /// /// A buffer can directly store three pointers and is pointer-aligned. /// Three pointers is a sweet spot for Swift, because it means we can /// store a structure containing a pointer, a size, and an owning /// object, which is a common pattern in code due to ARC. In a GC /// environment, this could be reduced to two pointers without much loss. /// /// A buffer can be in one of three states: /// - An unallocated buffer has a completely unspecified state. /// - An allocated buffer has been initialized so that it /// owns uninitialized value storage for the stored type. /// - An initialized buffer is an allocated buffer whose value /// storage has been initialized. template struct TargetValueBuffer { TargetPointer PrivateData[NumWords_ValueBuffer]; }; using ValueBuffer = TargetValueBuffer; /// Can a value with the given size and alignment be allocated inline? constexpr inline bool canBeInline(bool isBitwiseTakable, size_t size, size_t alignment) { return isBitwiseTakable && size <= sizeof(ValueBuffer) && alignment <= alignof(ValueBuffer); } template constexpr inline bool canBeInline(bool isBitwiseTakable) { return canBeInline(isBitwiseTakable, sizeof(T), alignof(T)); } template struct TargetValueWitnessTable; using ValueWitnessTable = TargetValueWitnessTable; template class TargetValueWitnessTypes; using ValueWitnessTypes = TargetValueWitnessTypes; template class TargetValueWitnessTypes { public: using StoredPointer = typename Runtime::StoredPointer; // Note that, for now, we aren't strict about 'const'. #define WANT_ALL_VALUE_WITNESSES #define DATA_VALUE_WITNESS(lowerId, upperId, type) #define FUNCTION_VALUE_WITNESS(lowerId, upperId, returnType, paramTypes) \ typedef returnType (*lowerId ## Unsigned) paramTypes; \ typedef TargetSignedPointer lowerId; #define MUTABLE_VALUE_TYPE TargetPointer #define IMMUTABLE_VALUE_TYPE ConstTargetPointer #define MUTABLE_BUFFER_TYPE TargetPointer #define IMMUTABLE_BUFFER_TYPE ConstTargetPointer #define TYPE_TYPE ConstTargetPointer #define SIZE_TYPE StoredSize #define INT_TYPE int #define UINT_TYPE unsigned #define VOID_TYPE void #include "swift/ABI/ValueWitness.def" // Handle the data witnesses explicitly so we can use more specific // types for the flags enums. typedef size_t size; typedef size_t stride; typedef ValueWitnessFlags flags; typedef uint32_t extraInhabitantCount; }; struct TypeLayout; /// A value-witness table. A value witness table is built around /// the requirements of some specific type. The information in /// a value-witness table is intended to be sufficient to lay out /// and manipulate values of an arbitrary type. template struct TargetValueWitnessTable { // For the meaning of all of these witnesses, consult the comments // on their associated typedefs, above. #define WANT_ONLY_REQUIRED_VALUE_WITNESSES #define VALUE_WITNESS(LOWER_ID, UPPER_ID) \ typename TargetValueWitnessTypes::LOWER_ID LOWER_ID; #define FUNCTION_VALUE_WITNESS(LOWER_ID, UPPER_ID, RET, PARAMS) \ typename TargetValueWitnessTypes::LOWER_ID LOWER_ID; #include "swift/ABI/ValueWitness.def" using StoredSize = typename Runtime::StoredSize; /// Is the external type layout of this type incomplete? bool isIncomplete() const { return flags.isIncomplete(); } /// Would values of a type with the given layout requirements be /// allocated inline? static bool isValueInline(bool isBitwiseTakable, StoredSize size, StoredSize alignment) { return (isBitwiseTakable && size <= sizeof(TargetValueBuffer) && alignment <= alignof(TargetValueBuffer)); } /// Are values of this type allocated inline? bool isValueInline() const { return flags.isInlineStorage(); } /// Is this type POD? bool isPOD() const { return flags.isPOD(); } /// Is this type bitwise-takable? bool isBitwiseTakable() const { return flags.isBitwiseTakable(); } /// Return the size of this type. Unlike in C, this has not been /// padded up to the alignment; that value is maintained as /// 'stride'. StoredSize getSize() const { return size; } /// Return the stride of this type. This is the size rounded up to /// be a multiple of the alignment. StoredSize getStride() const { return stride; } /// Return the alignment required by this type, in bytes. StoredSize getAlignment() const { return flags.getAlignment(); } /// The alignment mask of this type. An offset may be rounded up to /// the required alignment by adding this mask and masking by its /// bit-negation. /// /// For example, if the type needs to be 8-byte aligned, the value /// of this witness is 0x7. StoredSize getAlignmentMask() const { return flags.getAlignmentMask(); } /// The number of extra inhabitants, that is, bit patterns that do not form /// valid values of the type, in this type's binary representation. unsigned getNumExtraInhabitants() const { return extraInhabitantCount; } /// Assert that this value witness table is an enum value witness table /// and return it as such. /// /// This has an awful name because it's supposed to be internal to /// this file. Code outside this file should use LLVM's cast/dyn_cast. /// We don't want to use those here because we need to avoid accidentally /// introducing ABI dependencies on LLVM structures. const struct EnumValueWitnessTable *_asEVWT() const; /// Get the type layout record within this value witness table. const TypeLayout *getTypeLayout() const { return reinterpret_cast(&size); } /// Check whether this metadata is complete. bool checkIsComplete() const; /// "Publish" the layout of this type to other threads. All other stores /// to the value witness table (including its extended header) should have /// happened before this is called. void publishLayout(const TypeLayout &layout); }; /// 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 TargetTypeMetadataHeader { /// A pointer to the value-witnesses for this type. This is only /// present for type metadata. TargetPointer ValueWitnesses; }; 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) {} }; /// 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; }; } template struct TargetGenericMetadataInstantiationCache; template struct TargetAnyClassMetadata; template struct TargetClassMetadata; template struct TargetStructMetadata; template struct TargetOpaqueMetadata; template struct TargetValueMetadata; template struct TargetForeignClassMetadata; template struct TargetContextDescriptor; template class TargetTypeContextDescriptor; template class TargetClassDescriptor; template class TargetValueTypeDescriptor; template class TargetEnumDescriptor; template class TargetStructDescriptor; template struct TargetGenericMetadataPattern; // FIXME: https://bugs.swift.org/browse/SR-1155 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Winvalid-offsetof" /// Bounds for metadata objects. template struct TargetMetadataBounds { using StoredSize = typename Runtime::StoredSize; /// The negative extent of the metadata, in words. uint32_t NegativeSizeInWords; /// The positive extent of the metadata, in words. uint32_t PositiveSizeInWords; /// Return the total size of the metadata in bytes, including both /// negatively- and positively-offset members. StoredSize getTotalSizeInBytes() const { return (StoredSize(NegativeSizeInWords) + StoredSize(PositiveSizeInWords)) * sizeof(void*); } /// Return the offset of the address point of the metadata from its /// start, in bytes. StoredSize getAddressPointInBytes() const { return StoredSize(NegativeSizeInWords) * sizeof(void*); } }; using MetadataBounds = TargetMetadataBounds; /// The common structure of all type metadata. template struct TargetMetadata { using StoredPointer = typename Runtime::StoredPointer; /// The basic header type. typedef TargetTypeMetadataHeader HeaderType; constexpr TargetMetadata() : Kind(static_cast(MetadataKind::Class)) {} constexpr TargetMetadata(MetadataKind Kind) : Kind(static_cast(Kind)) {} #if SWIFT_OBJC_INTEROP protected: constexpr TargetMetadata(TargetAnyClassMetadata *isa) : Kind(reinterpret_cast(isa)) {} #endif private: /// The kind. Only valid for non-class metadata; getKind() must be used to get /// the kind value. StoredPointer Kind; public: /// Get the metadata kind. MetadataKind getKind() const { return getEnumeratedMetadataKind(Kind); } /// Set the metadata kind. void setKind(MetadataKind kind) { Kind = static_cast(kind); } #if SWIFT_OBJC_INTEROP protected: const TargetAnyClassMetadata *getClassISA() const { return reinterpret_cast *>(Kind); } void setClassISA(const TargetAnyClassMetadata *isa) { Kind = reinterpret_cast(isa); } #endif public: /// Is this a class object--the metadata record for a Swift class (which also /// serves as the class object), or the class object for an ObjC class (which /// is not metadata)? bool isClassObject() const { return static_cast(getKind()) == MetadataKind::Class; } /// Does the given metadata kind represent metadata for some kind of class? static bool isAnyKindOfClass(MetadataKind k) { switch (k) { case MetadataKind::Class: case MetadataKind::ObjCClassWrapper: case MetadataKind::ForeignClass: return true; default: return false; } } /// Is this metadata for an existential type? bool isAnyExistentialType() const { switch (getKind()) { case MetadataKind::ExistentialMetatype: case MetadataKind::Existential: return true; default: return false; } } /// Is this either type metadata or a class object for any kind of class? bool isAnyClass() const { return isAnyKindOfClass(getKind()); } const ValueWitnessTable *getValueWitnesses() const { return asFullMetadata(this)->ValueWitnesses; } const TypeLayout *getTypeLayout() const { return getValueWitnesses()->getTypeLayout(); } void setValueWitnesses(const ValueWitnessTable *table) { asFullMetadata(this)->ValueWitnesses = table; } // Define forwarders for value witnesses. These invoke this metadata's value // witness table with itself as the 'self' parameter. #define WANT_ONLY_REQUIRED_VALUE_WITNESSES #define FUNCTION_VALUE_WITNESS(WITNESS, UPPER, RET_TYPE, PARAM_TYPES) \ template \ _ResultOf::type \ vw_##WITNESS(A &&...args) const { \ return getValueWitnesses()->WITNESS(std::forward(args)..., this); \ } #define DATA_VALUE_WITNESS(LOWER, UPPER, TYPE) #include "swift/ABI/ValueWitness.def" unsigned vw_getEnumTag(const OpaqueValue *value) const { return getValueWitnesses()->_asEVWT()->getEnumTag(const_cast(value), this); } void vw_destructiveProjectEnumData(OpaqueValue *value) const { getValueWitnesses()->_asEVWT()->destructiveProjectEnumData(value, this); } void vw_destructiveInjectEnumTag(OpaqueValue *value, unsigned tag) const { getValueWitnesses()->_asEVWT()->destructiveInjectEnumTag(value, tag, this); } size_t vw_size() const { return getValueWitnesses()->getSize(); } size_t vw_alignment() const { return getValueWitnesses()->getAlignment(); } size_t vw_stride() const { return getValueWitnesses()->getStride(); } unsigned vw_getNumExtraInhabitants() const { return getValueWitnesses()->getNumExtraInhabitants(); } /// Allocate an out-of-line buffer if values of this type don't fit in the /// ValueBuffer. /// NOTE: This is not a box for copy-on-write existentials. OpaqueValue *allocateBufferIn(ValueBuffer *buffer) const; /// Get the address of the memory previously allocated in the ValueBuffer. /// NOTE: This is not a box for copy-on-write existentials. OpaqueValue *projectBufferFrom(ValueBuffer *buffer) const; /// Deallocate an out-of-line buffer stored in 'buffer' if values of this type /// are not stored inline in the ValueBuffer. void deallocateBufferIn(ValueBuffer *buffer) const; // Allocate an out-of-line buffer box (reference counted) if values of this // type don't fit in the ValueBuffer. // NOTE: This *is* a box for copy-on-write existentials. OpaqueValue *allocateBoxForExistentialIn(ValueBuffer *Buffer) const; // Deallocate an out-of-line buffer box if one is present. void deallocateBoxForExistentialIn(ValueBuffer *Buffer) const; /// Get the nominal type descriptor if this metadata describes a nominal type, /// or return null if it does not. ConstTargetMetadataPointer getTypeContextDescriptor() const { switch (getKind()) { case MetadataKind::Class: { const auto cls = static_cast *>(this); if (!cls->isTypeMetadata()) return nullptr; if (cls->isArtificialSubclass()) return nullptr; return cls->getDescription(); } case MetadataKind::Struct: case MetadataKind::Enum: case MetadataKind::Optional: return static_cast *>(this) ->Description; case MetadataKind::ForeignClass: return static_cast *>(this) ->Description; default: return nullptr; } } /// Get the class object for this type if it has one, or return null if the /// type is not a class (or not a class with a class object). const TargetClassMetadata *getClassObject() const; /// Retrieve the generic arguments of this type, if it has any. ConstTargetMetadataPointer const * getGenericArgs() const { auto description = getTypeContextDescriptor(); if (!description) return nullptr; auto generics = description->getGenericContext(); if (!generics) return nullptr; auto asWords = reinterpret_cast< ConstTargetMetadataPointer const *>(this); return asWords + description->getGenericArgumentOffset(); } bool satisfiesClassConstraint() const; bool isCanonicalStaticallySpecializedGenericMetadata() const; #if SWIFT_OBJC_INTEROP /// Get the ObjC class object for this type if it has one, or return null if /// the type is not a class (or not a class with a class object). /// This is allowed for InProcess values only. template typename std::enable_if::value, Class>::type getObjCClassObject() const { return reinterpret_cast( const_cast*>( getClassObject())); } #endif #ifndef NDEBUG LLVM_ATTRIBUTE_DEPRECATED(void dump() const, "Only meant for use in the debugger"); #endif protected: friend struct TargetOpaqueMetadata; /// Metadata should not be publicly copied or moved. constexpr TargetMetadata(const TargetMetadata &) = default; TargetMetadata &operator=(const TargetMetadata &) = default; constexpr TargetMetadata(TargetMetadata &&) = default; TargetMetadata &operator=(TargetMetadata &&) = default; }; /// The common structure of opaque metadata. Adds nothing. template struct TargetOpaqueMetadata { typedef TargetTypeMetadataHeader HeaderType; // We have to represent this as a member so we can list-initialize it. TargetMetadata base; }; using HeapObjectDestroyer = SWIFT_CC(swift) void(SWIFT_CONTEXT HeapObject *); /// The prefix on a heap metadata. template struct TargetHeapMetadataHeaderPrefix { /// Destroy the object, returning the allocated size of the object /// or 0 if the object shouldn't be deallocated. TargetSignedPointer destroy; }; using HeapMetadataHeaderPrefix = TargetHeapMetadataHeaderPrefix; /// The header present on all heap metadata. template struct TargetHeapMetadataHeader : TargetHeapMetadataHeaderPrefix, TargetTypeMetadataHeader { constexpr TargetHeapMetadataHeader( const TargetHeapMetadataHeaderPrefix &heapPrefix, const TargetTypeMetadataHeader &typePrefix) : TargetHeapMetadataHeaderPrefix(heapPrefix), TargetTypeMetadataHeader(typePrefix) {} }; using HeapMetadataHeader = TargetHeapMetadataHeader; /// The common structure of all metadata for heap-allocated types. A /// pointer to one of these can be retrieved by loading the 'isa' /// field of any heap object, whether it was managed by Swift or by /// Objective-C. However, when loading from an Objective-C object, /// this metadata may not have the heap-metadata header, and it may /// not be the Swift type metadata for the object's dynamic type. template struct TargetHeapMetadata : TargetMetadata { using HeaderType = TargetHeapMetadataHeader; TargetHeapMetadata() = default; constexpr TargetHeapMetadata(MetadataKind kind) : TargetMetadata(kind) {} #if SWIFT_OBJC_INTEROP constexpr TargetHeapMetadata(TargetAnyClassMetadata *isa) : TargetMetadata(isa) {} #endif }; using HeapMetadata = TargetHeapMetadata; /// An opaque descriptor describing a class or protocol method. References to /// these descriptors appear in the method override table of a class context /// descriptor, or a resilient witness table pattern, respectively. /// /// Clients should not assume anything about the contents of this descriptor /// other than it having 4 byte alignment. template struct TargetMethodDescriptor { /// Flags describing the method. MethodDescriptorFlags Flags; /// The method implementation. TargetRelativeDirectPointer Impl; // TODO: add method types or anything else needed for reflection. }; using MethodDescriptor = TargetMethodDescriptor; /// Header for a class vtable descriptor. This is a variable-sized /// structure that describes how to find and parse a vtable /// within the type metadata for a class. template struct TargetVTableDescriptorHeader { using StoredPointer = typename Runtime::StoredPointer; private: /// The offset of the vtable for this class in its metadata, if any, /// in words. /// /// If this class has a resilient superclass, this offset is relative to the /// the start of the immediate class's metadata. Otherwise, it is relative /// to the metadata address point. uint32_t VTableOffset; public: /// The number of vtable entries. This is the number of MethodDescriptor /// records following the vtable header in the class's nominal type /// descriptor, which is equal to the number of words this subclass's vtable /// entries occupy in instantiated class metadata. uint32_t VTableSize; uint32_t getVTableOffset(const TargetClassDescriptor *description) const { if (description->hasResilientSuperclass()) { auto bounds = description->getMetadataBounds(); return (bounds.ImmediateMembersOffset / sizeof(StoredPointer) + VTableOffset); } return VTableOffset; } }; template struct TargetContextDescriptor; template class Context = TargetContextDescriptor> using TargetSignedContextPointer = TargetSignedPointer * __ptrauth_swift_type_descriptor>; template class Context = TargetContextDescriptor> using TargetRelativeContextPointer = RelativeIndirectablePointer, /*nullable*/ true, int32_t, TargetSignedContextPointer>; using RelativeContextPointer = TargetRelativeContextPointer; template class Context = TargetContextDescriptor> using RelativeContextPointerIntPair = RelativeIndirectablePointerIntPair, IntTy, /*nullable*/ true, int32_t, TargetSignedContextPointer>; template struct TargetMethodDescriptor; template using TargetRelativeMethodDescriptorPointer = RelativeIndirectablePointer, /*nullable*/ true>; using RelativeMethodDescriptorPointer = TargetRelativeMethodDescriptorPointer; template struct TargetProtocolRequirement; template using TargetRelativeProtocolRequirementPointer = RelativeIndirectablePointer, /*nullable*/ true>; using RelativeProtocolRequirementPointer = TargetRelativeProtocolRequirementPointer; /// An entry in the method override table, referencing a method from one of our /// ancestor classes, together with an implementation. template struct TargetMethodOverrideDescriptor { /// The class containing the base method. TargetRelativeContextPointer Class; /// The base method. TargetRelativeMethodDescriptorPointer Method; /// The implementation of the override. TargetRelativeDirectPointer Impl; }; /// Header for a class vtable override descriptor. This is a variable-sized /// structure that provides implementations for overrides of methods defined /// in superclasses. template struct TargetOverrideTableHeader { /// The number of MethodOverrideDescriptor records following the vtable /// override header in the class's nominal type descriptor. uint32_t NumEntries; }; /// The bounds of a class metadata object. /// /// This type is a currency type and is not part of the ABI. /// See TargetStoredClassMetadataBounds for the type of the class /// metadata bounds variable. template struct TargetClassMetadataBounds : TargetMetadataBounds { using StoredPointer = typename Runtime::StoredPointer; using StoredSize = typename Runtime::StoredSize; using StoredPointerDifference = typename Runtime::StoredPointerDifference; using TargetMetadataBounds::NegativeSizeInWords; using TargetMetadataBounds::PositiveSizeInWords; /// The offset from the address point of the metadata to the immediate /// members. StoredPointerDifference ImmediateMembersOffset; constexpr TargetClassMetadataBounds() = default; constexpr TargetClassMetadataBounds( StoredPointerDifference immediateMembersOffset, uint32_t negativeSizeInWords, uint32_t positiveSizeInWords) : TargetMetadataBounds{negativeSizeInWords, positiveSizeInWords}, ImmediateMembersOffset(immediateMembersOffset) {} /// Return the basic bounds of all Swift class metadata. /// The immediate members offset will not be meaningful. static constexpr TargetClassMetadataBounds forSwiftRootClass() { using Metadata = FullMetadata>; return forAddressPointAndSize(sizeof(typename Metadata::HeaderType), sizeof(Metadata)); } /// Return the bounds of a Swift class metadata with the given address /// point and size (both in bytes). /// The immediate members offset will not be meaningful. static constexpr TargetClassMetadataBounds forAddressPointAndSize(StoredSize addressPoint, StoredSize totalSize) { return { // Immediate offset in bytes. StoredPointerDifference(totalSize - addressPoint), // Negative size in words. uint32_t(addressPoint / sizeof(StoredPointer)), // Positive size in words. uint32_t((totalSize - addressPoint) / sizeof(StoredPointer)) }; } /// Adjust these bounds for a subclass with the given immediate-members /// section. void adjustForSubclass(bool areImmediateMembersNegative, uint32_t numImmediateMembers) { if (areImmediateMembersNegative) { NegativeSizeInWords += numImmediateMembers; ImmediateMembersOffset = -StoredPointerDifference(NegativeSizeInWords) * sizeof(StoredPointer); } else { ImmediateMembersOffset = PositiveSizeInWords * sizeof(StoredPointer); PositiveSizeInWords += numImmediateMembers; } } }; using ClassMetadataBounds = TargetClassMetadataBounds; /// The portion of a class metadata object that is compatible with /// all classes, even non-Swift ones. template struct TargetAnyClassMetadata : public TargetHeapMetadata { using StoredPointer = typename Runtime::StoredPointer; using StoredSize = typename Runtime::StoredSize; #if SWIFT_OBJC_INTEROP constexpr TargetAnyClassMetadata(TargetAnyClassMetadata *isa, TargetClassMetadata *superclass) : TargetHeapMetadata(isa), Superclass(superclass), CacheData{nullptr, nullptr}, Data(SWIFT_CLASS_IS_SWIFT_MASK) {} #endif constexpr TargetAnyClassMetadata(TargetClassMetadata *superclass) : TargetHeapMetadata(MetadataKind::Class), Superclass(superclass), CacheData{nullptr, nullptr}, Data(SWIFT_CLASS_IS_SWIFT_MASK) {} #if SWIFT_OBJC_INTEROP // Allow setting the metadata kind to a class ISA on class metadata. using TargetMetadata::getClassISA; using TargetMetadata::setClassISA; #endif // Note that ObjC classes does not have a metadata header. /// The metadata for the superclass. This is null for the root class. ConstTargetMetadataPointer Superclass; // TODO: remove the CacheData and Data fields in non-ObjC-interop builds. /// The cache data is used for certain dynamic lookups; it is owned /// by the runtime and generally needs to interoperate with /// Objective-C's use. TargetPointer CacheData[2]; /// The data pointer is used for out-of-line metadata and is /// generally opaque, except that the compiler sets the low bit in /// order to indicate that this is a Swift metatype and therefore /// that the type metadata header is present. StoredSize Data; static constexpr StoredPointer offsetToData() { return offsetof(TargetAnyClassMetadata, Data); } /// Is this object a valid swift type metadata? That is, can it be /// safely downcast to ClassMetadata? bool isTypeMetadata() const { return (Data & SWIFT_CLASS_IS_SWIFT_MASK); } /// A different perspective on the same bit bool isPureObjC() const { return !isTypeMetadata(); } }; using AnyClassMetadata = TargetAnyClassMetadata; using ClassIVarDestroyer = SWIFT_CC(swift) void(SWIFT_CONTEXT HeapObject *); /// The structure of all class metadata. This structure is embedded /// directly within the class's heap metadata structure and therefore /// cannot be extended without an ABI break. /// /// Note that the layout of this type is compatible with the layout of /// an Objective-C class. template struct TargetClassMetadata : public TargetAnyClassMetadata { using StoredPointer = typename Runtime::StoredPointer; using StoredSize = typename Runtime::StoredSize; TargetClassMetadata() = default; constexpr TargetClassMetadata(const TargetAnyClassMetadata &base, ClassFlags flags, ClassIVarDestroyer *ivarDestroyer, StoredPointer size, StoredPointer addressPoint, StoredPointer alignMask, StoredPointer classSize, StoredPointer classAddressPoint) : TargetAnyClassMetadata(base), Flags(flags), InstanceAddressPoint(addressPoint), InstanceSize(size), InstanceAlignMask(alignMask), Reserved(0), ClassSize(classSize), ClassAddressPoint(classAddressPoint), Description(nullptr), IVarDestroyer(ivarDestroyer) {} // The remaining fields are valid only when isTypeMetadata(). // The Objective-C runtime knows the offsets to some of these fields. // Be careful when accessing them. /// Swift-specific class flags. ClassFlags Flags; /// The address point of instances of this type. uint32_t InstanceAddressPoint; /// The required size of instances of this type. /// 'InstanceAddressPoint' bytes go before the address point; /// 'InstanceSize - InstanceAddressPoint' bytes go after it. uint32_t InstanceSize; /// The alignment mask of the address point of instances of this type. uint16_t InstanceAlignMask; /// Reserved for runtime use. uint16_t Reserved; /// The total size of the class object, including prefix and suffix /// extents. uint32_t ClassSize; /// The offset of the address point within the class object. uint32_t ClassAddressPoint; // Description is by far the most likely field for a client to try // to access directly, so we force access to go through accessors. private: /// An out-of-line Swift-specific description of the type, or null /// if this is an artificial subclass. We currently provide no /// supported mechanism for making a non-artificial subclass /// dynamically. TargetSignedPointer * __ptrauth_swift_type_descriptor> Description; public: /// A function for destroying instance variables, used to clean up after an /// early return from a constructor. If null, no clean up will be performed /// and all ivars must be trivial. TargetSignedPointer IVarDestroyer; // After this come the class members, laid out as follows: // - class members for the superclass (recursively) // - metadata reference for the parent, if applicable // - generic parameters for this class // - class variables (if we choose to support these) // - "tabulated" virtual methods using TargetAnyClassMetadata::isTypeMetadata; ConstTargetMetadataPointer getDescription() const { assert(isTypeMetadata()); return Description; } typename Runtime::StoredSignedPointer getDescriptionAsSignedPointer() const { assert(isTypeMetadata()); return Description; } void setDescription(const TargetClassDescriptor *description) { Description = description; } /// Is this class an artificial subclass, such as one dynamically /// created for various dynamic purposes like KVO? bool isArtificialSubclass() const { assert(isTypeMetadata()); return Description == nullptr; } void setArtificialSubclass() { assert(isTypeMetadata()); Description = nullptr; } ClassFlags getFlags() const { assert(isTypeMetadata()); return Flags; } void setFlags(ClassFlags flags) { assert(isTypeMetadata()); Flags = flags; } StoredSize getInstanceSize() const { assert(isTypeMetadata()); return InstanceSize; } void setInstanceSize(StoredSize size) { assert(isTypeMetadata()); InstanceSize = size; } StoredPointer getInstanceAddressPoint() const { assert(isTypeMetadata()); return InstanceAddressPoint; } void setInstanceAddressPoint(StoredSize size) { assert(isTypeMetadata()); InstanceAddressPoint = size; } StoredPointer getInstanceAlignMask() const { assert(isTypeMetadata()); return InstanceAlignMask; } void setInstanceAlignMask(StoredSize mask) { assert(isTypeMetadata()); InstanceAlignMask = mask; } StoredPointer getClassSize() const { assert(isTypeMetadata()); return ClassSize; } void setClassSize(StoredSize size) { assert(isTypeMetadata()); ClassSize = size; } StoredPointer getClassAddressPoint() const { assert(isTypeMetadata()); return ClassAddressPoint; } void setClassAddressPoint(StoredSize offset) { assert(isTypeMetadata()); ClassAddressPoint = offset; } uint16_t getRuntimeReservedData() const { assert(isTypeMetadata()); return Reserved; } void setRuntimeReservedData(uint16_t data) { assert(isTypeMetadata()); Reserved = data; } /// Get a pointer to the field offset vector, if present, or null. const StoredPointer *getFieldOffsets() const { assert(isTypeMetadata()); auto offset = getDescription()->getFieldOffsetVectorOffset(); if (offset == 0) return nullptr; auto asWords = reinterpret_cast(this); return reinterpret_cast(asWords + offset); } uint32_t getSizeInWords() const { assert(isTypeMetadata()); uint32_t size = getClassSize() - getClassAddressPoint(); assert(size % sizeof(StoredPointer) == 0); return size / sizeof(StoredPointer); } /// Given that this class is serving as the superclass of a Swift class, /// return its bounds as metadata. /// /// Note that the ImmediateMembersOffset member will not be meaningful. TargetClassMetadataBounds getClassBoundsAsSwiftSuperclass() const { using Bounds = TargetClassMetadataBounds; auto rootBounds = Bounds::forSwiftRootClass(); // If the class is not type metadata, just use the root-class bounds. if (!isTypeMetadata()) return rootBounds; // Otherwise, pull out the bounds from the metadata. auto bounds = Bounds::forAddressPointAndSize(getClassAddressPoint(), getClassSize()); // Round the bounds up to the required dimensions. if (bounds.NegativeSizeInWords < rootBounds.NegativeSizeInWords) bounds.NegativeSizeInWords = rootBounds.NegativeSizeInWords; if (bounds.PositiveSizeInWords < rootBounds.PositiveSizeInWords) bounds.PositiveSizeInWords = rootBounds.PositiveSizeInWords; return bounds; } /// Given a statically-emitted metadata template, this sets the correct /// "is Swift" bit for the current runtime. Depending on the deployment /// target a binary was compiled for, statically emitted metadata templates /// may have a different bit set from the one that this runtime canonically /// considers the "is Swift" bit. void setAsTypeMetadata() { // If the wrong "is Swift" bit is set, set the correct one. // // Note that the only time we should see the "new" bit set while // expecting the "old" one is when running a binary built for a // new OS on an old OS, which is not supported, however we do // have tests that exercise this scenario. auto otherSwiftBit = (3ULL - SWIFT_CLASS_IS_SWIFT_MASK); assert(otherSwiftBit == 1ULL || otherSwiftBit == 2ULL); if ((this->Data & 3) == otherSwiftBit) { this->Data ^= 3; } // Otherwise there should be nothing to do, since only the old "is // Swift" bit is used for backward-deployed runtimes. assert(isTypeMetadata()); } bool isCanonicalStaticallySpecializedGenericMetadata() const { auto *description = getDescription(); if (!description->isGeneric()) return false; return this->Flags & ClassFlags::IsCanonicalStaticSpecialization; } static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::Class; } }; using ClassMetadata = TargetClassMetadata; /// The structure of metadata for heap-allocated local variables. /// This is non-type metadata. template struct TargetHeapLocalVariableMetadata : public TargetHeapMetadata { using StoredPointer = typename Runtime::StoredPointer; uint32_t OffsetToFirstCapture; TargetPointer CaptureDescription; static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::HeapLocalVariable; } constexpr TargetHeapLocalVariableMetadata() : TargetHeapMetadata(MetadataKind::HeapLocalVariable), OffsetToFirstCapture(0), CaptureDescription(nullptr) {} }; using HeapLocalVariableMetadata = TargetHeapLocalVariableMetadata; /// The structure of wrapper metadata for Objective-C classes. This /// is used as a type metadata pointer when the actual class isn't /// Swift-compiled. template struct TargetObjCClassWrapperMetadata : public TargetMetadata { ConstTargetMetadataPointer Class; static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::ObjCClassWrapper; } }; using ObjCClassWrapperMetadata = TargetObjCClassWrapperMetadata; /// The structure of metadata for foreign types where the source /// language doesn't provide any sort of more interesting metadata for /// us to use. template struct TargetForeignTypeMetadata : public TargetMetadata { }; using ForeignTypeMetadata = TargetForeignTypeMetadata; /// The structure of metadata objects for foreign class types. /// A foreign class is a foreign type with reference semantics and /// Swift-supported reference counting. Generally this requires /// special logic in the importer. /// /// We assume for now that foreign classes are entirely opaque /// to Swift introspection. template struct TargetForeignClassMetadata : public TargetForeignTypeMetadata { using StoredPointer = typename Runtime::StoredPointer; /// An out-of-line description of the type. TargetSignedPointer * __ptrauth_swift_type_descriptor> Description; /// The superclass of the foreign class, if any. ConstTargetMetadataPointer Superclass; /// Reserved space. For now, this should be zero-initialized. /// If this is used for anything in the future, at least some of these /// first bits should be flags. StoredPointer Reserved[1]; ConstTargetMetadataPointer getDescription() const { return Description; } typename Runtime::StoredSignedPointer getDescriptionAsSignedPointer() const { return Description; } static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::ForeignClass; } }; using ForeignClassMetadata = TargetForeignClassMetadata; /// The common structure of metadata for structs and enums. template struct TargetValueMetadata : public TargetMetadata { using StoredPointer = typename Runtime::StoredPointer; TargetValueMetadata(MetadataKind Kind, const TargetTypeContextDescriptor *description) : TargetMetadata(Kind), Description(description) {} /// An out-of-line description of the type. TargetSignedPointer * __ptrauth_swift_type_descriptor> Description; static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::Struct || metadata->getKind() == MetadataKind::Enum || metadata->getKind() == MetadataKind::Optional; } ConstTargetMetadataPointer getDescription() const { return Description; } typename Runtime::StoredSignedPointer getDescriptionAsSignedPointer() const { return Description; } }; using ValueMetadata = TargetValueMetadata; /// The structure of type metadata for structs. template struct TargetStructMetadata : public TargetValueMetadata { using StoredPointer = typename Runtime::StoredPointer; using TargetValueMetadata::TargetValueMetadata; const TargetStructDescriptor *getDescription() const { return llvm::cast>(this->Description); } // The first trailing field of struct metadata is always the generic // argument array. /// Get a pointer to the field offset vector, if present, or null. const uint32_t *getFieldOffsets() const { auto offset = getDescription()->FieldOffsetVectorOffset; if (offset == 0) return nullptr; auto asWords = reinterpret_cast(this); return reinterpret_cast(asWords + offset); } bool isCanonicalStaticallySpecializedGenericMetadata() const { auto *description = getDescription(); if (!description->isGeneric()) return false; auto *trailingFlags = getTrailingFlags(); if (trailingFlags == nullptr) return false; return trailingFlags->isCanonicalStaticSpecialization(); } const MetadataTrailingFlags *getTrailingFlags() const { auto description = getDescription(); auto flags = description->getFullGenericContextHeader() .DefaultInstantiationPattern->PatternFlags; if (!flags.hasTrailingFlags()) return nullptr; auto fieldOffset = description->FieldOffsetVectorOffset; auto offset = fieldOffset + // Pad to the nearest pointer. ((description->NumFields * sizeof(uint32_t) + sizeof(void *) - 1) / sizeof(void *)); auto asWords = reinterpret_cast(this); return reinterpret_cast(asWords + offset); } static constexpr int32_t getGenericArgumentOffset() { return sizeof(TargetStructMetadata) / sizeof(StoredPointer); } static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::Struct; } }; using StructMetadata = TargetStructMetadata; /// The structure of type metadata for enums. template struct TargetEnumMetadata : public TargetValueMetadata { using StoredPointer = typename Runtime::StoredPointer; using StoredSize = typename Runtime::StoredSize; using TargetValueMetadata::TargetValueMetadata; const TargetEnumDescriptor *getDescription() const { return llvm::cast>(this->Description); } // The first trailing field of enum metadata is always the generic // argument array. /// True if the metadata records the size of the payload area. bool hasPayloadSize() const { return getDescription()->hasPayloadSizeOffset(); } /// Retrieve the size of the payload area. /// /// `hasPayloadSize` must be true for this to be valid. StoredSize getPayloadSize() const { assert(hasPayloadSize()); auto offset = getDescription()->getPayloadSizeOffset(); const StoredSize *asWords = reinterpret_cast(this); asWords += offset; return *asWords; } StoredSize &getPayloadSize() { assert(hasPayloadSize()); auto offset = getDescription()->getPayloadSizeOffset(); StoredSize *asWords = reinterpret_cast(this); asWords += offset; return *asWords; } bool isCanonicalStaticallySpecializedGenericMetadata() const { auto *description = getDescription(); if (!description->isGeneric()) return false; auto *trailingFlags = getTrailingFlags(); if (trailingFlags == nullptr) return false; return trailingFlags->isCanonicalStaticSpecialization(); } const MetadataTrailingFlags *getTrailingFlags() const { auto description = getDescription(); auto flags = description->getFullGenericContextHeader() .DefaultInstantiationPattern->PatternFlags; if (!flags.hasTrailingFlags()) return nullptr; auto offset = getGenericArgumentOffset() + description->getFullGenericContextHeader().Base.getNumArguments() + (hasPayloadSize() ? 1 : 0); auto asWords = reinterpret_cast(this); return reinterpret_cast(asWords + offset); } static constexpr int32_t getGenericArgumentOffset() { return sizeof(TargetEnumMetadata) / sizeof(StoredPointer); } static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::Enum || metadata->getKind() == MetadataKind::Optional; } }; using EnumMetadata = TargetEnumMetadata; /// The structure of function type metadata. template struct TargetFunctionTypeMetadata : public TargetMetadata { using StoredSize = typename Runtime::StoredSize; using Parameter = ConstTargetMetadataPointer; TargetFunctionTypeFlags Flags; /// The type metadata for the result type. ConstTargetMetadataPointer ResultType; Parameter *getParameters() { return reinterpret_cast(this + 1); } const Parameter *getParameters() const { return reinterpret_cast(this + 1); } Parameter getParameter(unsigned index) const { assert(index < getNumParameters()); return getParameters()[index]; } ParameterFlags getParameterFlags(unsigned index) const { assert(index < getNumParameters()); auto flags = hasParameterFlags() ? getParameterFlags()[index] : 0; return ParameterFlags::fromIntValue(flags); } StoredSize getNumParameters() const { return Flags.getNumParameters(); } FunctionMetadataConvention getConvention() const { return Flags.getConvention(); } bool throws() const { return Flags.throws(); } bool hasParameterFlags() const { return Flags.hasParameterFlags(); } bool isEscaping() const { return Flags.isEscaping(); } static constexpr StoredSize OffsetToFlags = sizeof(TargetMetadata); static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::Function; } uint32_t *getParameterFlags() { return reinterpret_cast(getParameters() + getNumParameters()); } const uint32_t *getParameterFlags() const { return reinterpret_cast(getParameters() + getNumParameters()); } }; using FunctionTypeMetadata = TargetFunctionTypeMetadata; /// The structure of metadata for metatypes. template struct TargetMetatypeMetadata : public TargetMetadata { /// The type metadata for the element. ConstTargetMetadataPointer InstanceType; static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::Metatype; } }; using MetatypeMetadata = TargetMetatypeMetadata; /// The structure of tuple type metadata. template struct TargetTupleTypeMetadata : public TargetMetadata { using StoredSize = typename Runtime::StoredSize; TargetTupleTypeMetadata() = default; constexpr TargetTupleTypeMetadata(const TargetMetadata &base, uint32_t numElements, TargetPointer labels) : TargetMetadata(base), NumElements(numElements), Labels(labels) {} /// The number of elements. StoredSize NumElements; /// The labels string; see swift_getTupleTypeMetadata. TargetPointer Labels; struct Element { /// The type of the element. ConstTargetMetadataPointer Type; /// The offset of the tuple element within the tuple. #if __APPLE__ StoredSize Offset; #else uint32_t Offset; #endif OpaqueValue *findIn(OpaqueValue *tuple) const { return (OpaqueValue*) (((char*) tuple) + Offset); } const TypeLayout *getTypeLayout() const { return Type->getTypeLayout(); } }; static_assert(sizeof(Element) == sizeof(StoredSize) * 2, "element size should be two words"); Element *getElements() { return reinterpret_cast(this + 1); } const Element *getElements() const { return reinterpret_cast(this + 1); } const Element &getElement(unsigned i) const { return getElements()[i]; } Element &getElement(unsigned i) { return getElements()[i]; } static constexpr StoredSize getOffsetToNumElements(); static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::Tuple; } }; using TupleTypeMetadata = TargetTupleTypeMetadata; template constexpr inline auto TargetTupleTypeMetadata::getOffsetToNumElements() -> StoredSize { return offsetof(TargetTupleTypeMetadata, NumElements); } template struct TargetProtocolDescriptor; #if SWIFT_OBJC_INTEROP /// Layout of a small prefix of an Objective-C protocol, used only to /// directly extract the name of the protocol. template struct TargetObjCProtocolPrefix { /// Unused by the Swift runtime. TargetPointer _ObjC_Isa; /// The mangled name of the protocol. TargetPointer Name; }; #endif /// A reference to a protocol within the runtime, which may be either /// a Swift protocol or (when Objective-C interoperability is enabled) an /// Objective-C protocol. /// /// This type always contains a single target pointer, whose lowest bit is /// used to distinguish between a Swift protocol referent and an Objective-C /// protocol referent. template class TargetProtocolDescriptorRef { using StoredPointer = typename Runtime::StoredPointer; using ProtocolDescriptorPointer = ConstTargetMetadataPointer; enum : StoredPointer { // The bit used to indicate whether this is an Objective-C protocol. IsObjCBit = 0x1U, }; /// A direct pointer to a protocol descriptor for either an Objective-C /// protocol (if the low bit is set) or a Swift protocol (if the low bit /// is clear). StoredPointer storage; public: constexpr TargetProtocolDescriptorRef(StoredPointer storage) : storage(storage) { } constexpr TargetProtocolDescriptorRef() : storage() { } TargetProtocolDescriptorRef( ProtocolDescriptorPointer protocol, ProtocolDispatchStrategy dispatchStrategy) { #if SWIFT_OBJC_INTEROP storage = reinterpret_cast(protocol) | (dispatchStrategy == ProtocolDispatchStrategy::ObjC ? IsObjCBit : 0); #else assert(dispatchStrategy == ProtocolDispatchStrategy::Swift); storage = reinterpret_cast(protocol); #endif } const static TargetProtocolDescriptorRef forSwift( ProtocolDescriptorPointer protocol) { return TargetProtocolDescriptorRef{ reinterpret_cast(protocol)}; } #if SWIFT_OBJC_INTEROP constexpr static TargetProtocolDescriptorRef forObjC(Protocol *objcProtocol) { return TargetProtocolDescriptorRef{ reinterpret_cast(objcProtocol) | IsObjCBit}; } #endif explicit constexpr operator bool() const { return storage != 0; } /// The name of the protocol. TargetPointer getName() const { #if SWIFT_OBJC_INTEROP if (isObjC()) { return reinterpret_cast *>( getObjCProtocol())->Name; } #endif return getSwiftProtocol()->Name; } /// Determine what kind of protocol this is, Swift or Objective-C. ProtocolDispatchStrategy getDispatchStrategy() const { #if SWIFT_OBJC_INTEROP if (isObjC()) { return ProtocolDispatchStrategy::ObjC; } #endif return ProtocolDispatchStrategy::Swift; } /// Determine whether this protocol has a 'class' constraint. ProtocolClassConstraint getClassConstraint() const { #if SWIFT_OBJC_INTEROP if (isObjC()) { return ProtocolClassConstraint::Class; } #endif return getSwiftProtocol()->getProtocolContextDescriptorFlags() .getClassConstraint(); } /// Determine whether this protocol needs a witness table. bool needsWitnessTable() const { #if SWIFT_OBJC_INTEROP if (isObjC()) { return false; } #endif return true; } SpecialProtocol getSpecialProtocol() const { #if SWIFT_OBJC_INTEROP if (isObjC()) { return SpecialProtocol::None; } #endif return getSwiftProtocol()->getProtocolContextDescriptorFlags() .getSpecialProtocol(); } /// Retrieve the Swift protocol descriptor. ProtocolDescriptorPointer getSwiftProtocol() const { #if SWIFT_OBJC_INTEROP assert(!isObjC()); #endif // NOTE: we explicitly use a C-style cast here because cl objects to the // reinterpret_cast from a uintptr_t type to an unsigned type which the // Pointer type may be depending on the instantiation. Using the C-style // cast gives us a single path irrespective of the template type parameters. return (ProtocolDescriptorPointer)(storage & ~IsObjCBit); } /// Retrieve the raw stored pointer and discriminator bit. constexpr StoredPointer getRawData() const { return storage; } #if SWIFT_OBJC_INTEROP /// Whether this references an Objective-C protocol. bool isObjC() const { return (storage & IsObjCBit) != 0; } /// Retrieve the Objective-C protocol. TargetPointer getObjCProtocol() const { assert(isObjC()); return reinterpret_cast >( storage & ~IsObjCBit); } #endif }; using ProtocolDescriptorRef = TargetProtocolDescriptorRef; /// A protocol requirement descriptor. This describes a single protocol /// requirement in a protocol descriptor. The index of the requirement in /// the descriptor determines the offset of the witness in a witness table /// for this protocol. template struct TargetProtocolRequirement { ProtocolRequirementFlags Flags; // TODO: name, type /// The optional default implementation of the protocol. RelativeDirectPointer DefaultImplementation; }; using ProtocolRequirement = TargetProtocolRequirement; template struct TargetProtocolDescriptor; using ProtocolDescriptor = TargetProtocolDescriptor; /// A witness table for a protocol. /// /// With the exception of the initial protocol conformance descriptor, /// the layout of a witness table is dependent on the protocol being /// represented. template class TargetWitnessTable { /// The protocol conformance descriptor from which this witness table /// was generated. ConstTargetMetadataPointer Description; public: const TargetProtocolConformanceDescriptor *getDescription() const { return Description; } }; using WitnessTable = TargetWitnessTable; template using TargetWitnessTablePointer = ConstTargetMetadataPointer; using WitnessTablePointer = TargetWitnessTablePointer; using AssociatedWitnessTableAccessFunction = SWIFT_CC(swift) WitnessTable *(const Metadata *associatedType, const Metadata *self, const WitnessTable *selfConformance); /// The possible physical representations of existential types. enum class ExistentialTypeRepresentation { /// The type uses an opaque existential representation. Opaque, /// The type uses a class existential representation. Class, /// The type uses the Error boxed existential representation. Error, }; /// The structure of existential type metadata. template struct TargetExistentialTypeMetadata : TargetMetadata, swift::ABI::TrailingObjects< TargetExistentialTypeMetadata, ConstTargetMetadataPointer, TargetProtocolDescriptorRef> { private: using ProtocolDescriptorRef = TargetProtocolDescriptorRef; using MetadataPointer = ConstTargetMetadataPointer; using TrailingObjects = swift::ABI::TrailingObjects< TargetExistentialTypeMetadata, MetadataPointer, ProtocolDescriptorRef>; friend TrailingObjects; template using OverloadToken = typename TrailingObjects::template OverloadToken; size_t numTrailingObjects(OverloadToken) const { return NumProtocols; } size_t numTrailingObjects(OverloadToken) const { return Flags.hasSuperclassConstraint() ? 1 : 0; } public: using StoredPointer = typename Runtime::StoredPointer; /// The number of witness tables and class-constrained-ness of the type. ExistentialTypeFlags Flags; /// The number of protocols. uint32_t NumProtocols; constexpr TargetExistentialTypeMetadata() : TargetMetadata(MetadataKind::Existential), Flags(ExistentialTypeFlags()), NumProtocols(0) {} explicit constexpr TargetExistentialTypeMetadata(ExistentialTypeFlags Flags) : TargetMetadata(MetadataKind::Existential), Flags(Flags), NumProtocols(0) {} /// Get the representation form this existential type uses. ExistentialTypeRepresentation getRepresentation() const; /// True if it's valid to take ownership of the value in the existential /// container if we own the container. bool mayTakeValue(const OpaqueValue *container) const; /// Clean up an existential container whose value is uninitialized. void deinitExistentialContainer(OpaqueValue *container) const; /// Project the value pointer from an existential container of the type /// described by this metadata. const OpaqueValue *projectValue(const OpaqueValue *container) const; OpaqueValue *projectValue(OpaqueValue *container) const { return const_cast(projectValue((const OpaqueValue*)container)); } /// Get the dynamic type from an existential container of the type described /// by this metadata. const TargetMetadata * getDynamicType(const OpaqueValue *container) const; /// Get a witness table from an existential container of the type described /// by this metadata. const TargetWitnessTable * getWitnessTable( const OpaqueValue *container, unsigned i) const; /// Return true iff all the protocol constraints are @objc. bool isObjC() const { return isClassBounded() && Flags.getNumWitnessTables() == 0; } bool isClassBounded() const { return Flags.getClassConstraint() == ProtocolClassConstraint::Class; } /// Retrieve the set of protocols required by the existential. ArrayRef getProtocols() const { return { this->template getTrailingObjects(), NumProtocols }; } MetadataPointer getSuperclassConstraint() const { if (!Flags.hasSuperclassConstraint()) return MetadataPointer(); return this->template getTrailingObjects()[0]; } /// Retrieve the set of protocols required by the existential. MutableArrayRef getMutableProtocols() { return { this->template getTrailingObjects(), NumProtocols }; } /// Set the superclass. void setSuperclassConstraint(MetadataPointer superclass) { assert(Flags.hasSuperclassConstraint()); assert(superclass != nullptr); this->template getTrailingObjects()[0] = superclass; } static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::Existential; } }; using ExistentialTypeMetadata = TargetExistentialTypeMetadata; /// The basic layout of an existential metatype type. template struct TargetExistentialMetatypeContainer { ConstTargetMetadataPointer Value; TargetWitnessTablePointer *getWitnessTables() { return reinterpret_cast *>(this + 1); } TargetWitnessTablePointer const *getWitnessTables() const { return reinterpret_cast const *>(this+1); } void copyTypeInto(TargetExistentialMetatypeContainer *dest, unsigned numTables) const { for (unsigned i = 0; i != numTables; ++i) dest->getWitnessTables()[i] = getWitnessTables()[i]; } }; using ExistentialMetatypeContainer = TargetExistentialMetatypeContainer; /// The structure of metadata for existential metatypes. template struct TargetExistentialMetatypeMetadata : public TargetMetadata { /// The type metadata for the element. ConstTargetMetadataPointer InstanceType; /// The number of witness tables and class-constrained-ness of the /// underlying type. ExistentialTypeFlags Flags; static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::ExistentialMetatype; } /// Return true iff all the protocol constraints are @objc. bool isObjC() const { return isClassBounded() && Flags.getNumWitnessTables() == 0; } bool isClassBounded() const { return Flags.getClassConstraint() == ProtocolClassConstraint::Class; } }; using ExistentialMetatypeMetadata = TargetExistentialMetatypeMetadata; /// Heap metadata for a box, which may have been generated statically by the /// compiler or by the runtime. template struct TargetBoxHeapMetadata : public TargetHeapMetadata { /// The offset from the beginning of a box to its value. unsigned Offset; constexpr TargetBoxHeapMetadata(MetadataKind kind, unsigned offset) : TargetHeapMetadata(kind), Offset(offset) {} }; using BoxHeapMetadata = TargetBoxHeapMetadata; /// Heap metadata for runtime-instantiated generic boxes. template struct TargetGenericBoxHeapMetadata : public TargetBoxHeapMetadata { using super = TargetBoxHeapMetadata; using super::Offset; /// The type inside the box. ConstTargetMetadataPointer BoxedType; constexpr TargetGenericBoxHeapMetadata(MetadataKind kind, unsigned offset, ConstTargetMetadataPointer boxedType) : TargetBoxHeapMetadata(kind, offset), BoxedType(boxedType) {} static unsigned getHeaderOffset(const Metadata *boxedType) { // Round up the header size to alignment. unsigned alignMask = boxedType->getValueWitnesses()->getAlignmentMask(); return (sizeof(HeapObject) + alignMask) & ~alignMask; } /// Project the value out of a box of this type. OpaqueValue *project(HeapObject *box) const { auto bytes = reinterpret_cast(box); return reinterpret_cast(bytes + Offset); } /// Get the allocation size of this box. unsigned getAllocSize() const { return Offset + BoxedType->getValueWitnesses()->getSize(); } /// Get the allocation alignment of this box. unsigned getAllocAlignMask() const { // Heap allocations are at least pointer aligned. return BoxedType->getValueWitnesses()->getAlignmentMask() | (alignof(void*) - 1); } static bool classof(const TargetMetadata *metadata) { return metadata->getKind() == MetadataKind::HeapGenericLocalVariable; } }; using GenericBoxHeapMetadata = TargetGenericBoxHeapMetadata; /// The control structure of a generic or resilient protocol /// conformance witness. /// /// Resilient conformances must use a pattern where new requirements /// with default implementations can be added and the order of existing /// requirements can be changed. /// /// This is accomplished by emitting an order-independent series of /// relative pointer pairs, consisting of a protocol requirement together /// with a witness. The requirement is identified by an indirectable relative /// pointer to the protocol requirement descriptor. template struct TargetResilientWitness { TargetRelativeProtocolRequirementPointer Requirement; RelativeDirectPointer Witness; }; using ResilientWitness = TargetResilientWitness; template struct TargetResilientWitnessTable final : public swift::ABI::TrailingObjects< TargetResilientWitnessTable, TargetResilientWitness> { uint32_t NumWitnesses; using TrailingObjects = swift::ABI::TrailingObjects< TargetResilientWitnessTable, TargetResilientWitness>; friend TrailingObjects; template using OverloadToken = typename TrailingObjects::template OverloadToken; size_t numTrailingObjects( OverloadToken>) const { return NumWitnesses; } llvm::ArrayRef> getWitnesses() const { return {this->template getTrailingObjects>(), NumWitnesses}; } const TargetResilientWitness & getWitness(unsigned i) const { return getWitnesses()[i]; } }; using ResilientWitnessTable = TargetResilientWitnessTable; /// The control structure of a generic or resilient protocol /// conformance, which is embedded in the protocol conformance descriptor. /// /// Witness tables need to be instantiated at runtime in these cases: /// - For a generic conforming type, associated type requirements might be /// dependent on the conforming type. /// - For a type conforming to a resilient protocol, the runtime size of /// the witness table is not known because default requirements can be /// added resiliently. /// /// One per conformance. template struct TargetGenericWitnessTable { /// The size of the witness table in words. This amount is copied from /// the witness table template into the instantiated witness table. uint16_t WitnessTableSizeInWords; /// The amount of private storage to allocate before the address point, /// in words. This memory is zeroed out in the instantiated witness table /// template. /// /// The low bit is used to indicate whether this witness table is known /// to require instantiation. uint16_t WitnessTablePrivateSizeInWordsAndRequiresInstantiation; /// The instantiation function, which is called after the template is copied. RelativeDirectPointer *instantiatedTable, const TargetMetadata *type, const void * const *instantiationArgs), /*nullable*/ true> Instantiator; using PrivateDataType = void *[swift::NumGenericMetadataPrivateDataWords]; /// Private data for the instantiator. Out-of-line so that the rest /// of this structure can be constant. RelativeDirectPointer PrivateData; uint16_t getWitnessTablePrivateSizeInWords() const { return WitnessTablePrivateSizeInWordsAndRequiresInstantiation >> 1; } /// This bit doesn't really mean anything. Currently, the compiler always /// sets it when emitting a generic witness table. uint16_t requiresInstantiation() const { return WitnessTablePrivateSizeInWordsAndRequiresInstantiation & 0x01; } }; using GenericWitnessTable = TargetGenericWitnessTable; /// The structure of a type metadata record. /// /// This contains enough static information to recover type metadata from a /// name. template struct TargetTypeMetadataRecord { private: union { /// A direct reference to a nominal type descriptor. RelativeDirectPointerIntPair, TypeReferenceKind> DirectNominalTypeDescriptor; /// An indirect reference to a nominal type descriptor. RelativeDirectPointerIntPair * __ptrauth_swift_type_descriptor>, TypeReferenceKind> IndirectNominalTypeDescriptor; // We only allow a subset of the TypeReferenceKinds here. // Should we just acknowledge that this is a different enum? }; public: TypeReferenceKind getTypeKind() const { return DirectNominalTypeDescriptor.getInt(); } const TargetContextDescriptor * getContextDescriptor() const { switch (getTypeKind()) { case TypeReferenceKind::DirectTypeDescriptor: return DirectNominalTypeDescriptor.getPointer(); case TypeReferenceKind::IndirectTypeDescriptor: return *IndirectNominalTypeDescriptor.getPointer(); // These types (and any others we might add to TypeReferenceKind // in the future) are just never used in these lists. case TypeReferenceKind::DirectObjCClassName: case TypeReferenceKind::IndirectObjCClass: return nullptr; } return nullptr; } }; using TypeMetadataRecord = TargetTypeMetadataRecord; /// The structure of a protocol reference record. template struct TargetProtocolRecord { /// The protocol referenced. /// /// The remaining low bit is reserved for future use. RelativeContextPointerIntPair Protocol; }; using ProtocolRecord = TargetProtocolRecord; template class TargetGenericRequirementDescriptor; /// A relative pointer to a protocol descriptor, which provides the relative- /// pointer equivalent to \c TargetProtocolDescriptorRef. template class RelativeTargetProtocolDescriptorPointer { union { /// Relative pointer to a Swift protocol descriptor. /// The \c bool value will be false to indicate that the protocol /// is a Swift protocol, or true to indicate that this references /// an Objective-C protocol. RelativeContextPointerIntPair swiftPointer; #if SWIFT_OBJC_INTEROP /// Relative pointer to an ObjC protocol descriptor. /// The \c bool value will be false to indicate that the protocol /// is a Swift protocol, or true to indicate that this references /// an Objective-C protocol. RelativeIndirectablePointerIntPair objcPointer; #endif }; #if SWIFT_OBJC_INTEROP bool isObjC() const { return objcPointer.getInt(); } #endif public: /// Retrieve a reference to the protocol. TargetProtocolDescriptorRef getProtocol() const { #if SWIFT_OBJC_INTEROP if (isObjC()) { return TargetProtocolDescriptorRef::forObjC( const_cast(objcPointer.getPointer())); } #endif return TargetProtocolDescriptorRef::forSwift( reinterpret_cast>(swiftPointer.getPointer())); } operator TargetProtocolDescriptorRef() const { return getProtocol(); } }; /// A reference to a type. template struct TargetTypeReference { union { /// A direct reference to a TypeContextDescriptor or ProtocolDescriptor. RelativeDirectPointer> DirectTypeDescriptor; /// An indirect reference to a TypeContextDescriptor or ProtocolDescriptor. RelativeDirectPointer< TargetSignedPointer * __ptrauth_swift_type_descriptor>> IndirectTypeDescriptor; /// An indirect reference to an Objective-C class. RelativeDirectPointer< ConstTargetMetadataPointer> IndirectObjCClass; /// A direct reference to an Objective-C class name. RelativeDirectPointer DirectObjCClassName; }; const TargetContextDescriptor * getTypeDescriptor(TypeReferenceKind kind) const { switch (kind) { case TypeReferenceKind::DirectTypeDescriptor: return DirectTypeDescriptor; case TypeReferenceKind::IndirectTypeDescriptor: return *IndirectTypeDescriptor; case TypeReferenceKind::DirectObjCClassName: case TypeReferenceKind::IndirectObjCClass: return nullptr; } return nullptr; } #if SWIFT_OBJC_INTEROP /// If this type reference is one of the kinds that supports ObjC /// references, const TargetClassMetadata * getObjCClass(TypeReferenceKind kind) const; #endif const TargetClassMetadata * const * getIndirectObjCClass(TypeReferenceKind kind) const { assert(kind == TypeReferenceKind::IndirectObjCClass); return IndirectObjCClass.get(); } const char *getDirectObjCClassName(TypeReferenceKind kind) const { assert(kind == TypeReferenceKind::DirectObjCClassName); return DirectObjCClassName.get(); } }; using TypeReference = TargetTypeReference; /// Header containing information about the resilient witnesses in a /// protocol conformance descriptor. template struct TargetResilientWitnessesHeader { uint32_t NumWitnesses; }; using ResilientWitnessesHeader = TargetResilientWitnessesHeader; /// The structure of a protocol conformance. /// /// This contains enough static information to recover the witness table for a /// type's conformance to a protocol. template struct TargetProtocolConformanceDescriptor final : public swift::ABI::TrailingObjects< TargetProtocolConformanceDescriptor, TargetRelativeContextPointer, TargetGenericRequirementDescriptor, TargetResilientWitnessesHeader, TargetResilientWitness, TargetGenericWitnessTable> { using TrailingObjects = swift::ABI::TrailingObjects< TargetProtocolConformanceDescriptor, TargetRelativeContextPointer, TargetGenericRequirementDescriptor, TargetResilientWitnessesHeader, TargetResilientWitness, TargetGenericWitnessTable>; friend TrailingObjects; template using OverloadToken = typename TrailingObjects::template OverloadToken; public: using GenericRequirementDescriptor = TargetGenericRequirementDescriptor; using ResilientWitnessesHeader = TargetResilientWitnessesHeader; using ResilientWitness = TargetResilientWitness; using GenericWitnessTable = TargetGenericWitnessTable; private: /// The protocol being conformed to. TargetRelativeContextPointer Protocol; // Some description of the type that conforms to the protocol. TargetTypeReference TypeRef; /// The witness table pattern, which may also serve as the witness table. RelativeDirectPointer> WitnessTablePattern; /// Various flags, including the kind of conformance. ConformanceFlags Flags; public: ConstTargetPointer> getProtocol() const { return Protocol; } TypeReferenceKind getTypeKind() const { return Flags.getTypeReferenceKind(); } const char *getDirectObjCClassName() const { return TypeRef.getDirectObjCClassName(getTypeKind()); } const TargetClassMetadata * const *getIndirectObjCClass() const { return TypeRef.getIndirectObjCClass(getTypeKind()); } const TargetContextDescriptor *getTypeDescriptor() const { return TypeRef.getTypeDescriptor(getTypeKind()); } TargetContextDescriptor * __ptrauth_swift_type_descriptor * _getTypeDescriptorLocation() const { if (getTypeKind() != TypeReferenceKind::IndirectTypeDescriptor) return nullptr; return TypeRef.IndirectTypeDescriptor.get(); } /// Retrieve the context of a retroactive conformance. const TargetContextDescriptor *getRetroactiveContext() const { if (!Flags.isRetroactive()) return nullptr; return this->template getTrailingObjects< TargetRelativeContextPointer>(); } /// Whether this conformance is non-unique because it has been synthesized /// for a foreign type. bool isSynthesizedNonUnique() const { return Flags.isSynthesizedNonUnique(); } /// Whether this conformance has any conditional requirements that need to /// be evaluated. bool hasConditionalRequirements() const { return Flags.getNumConditionalRequirements() > 0; } /// Retrieve the conditional requirements that must also be /// satisfied llvm::ArrayRef getConditionalRequirements() const { return {this->template getTrailingObjects(), Flags.getNumConditionalRequirements()}; } /// Get the directly-referenced witness table pattern, which may also /// serve as the witness table. const swift::TargetWitnessTable *getWitnessTablePattern() const { return WitnessTablePattern; } /// Get the canonical metadata for the type referenced by this record, or /// return null if the record references a generic or universal type. const TargetMetadata *getCanonicalTypeMetadata() const; /// Get the witness table for the specified type, realizing it if /// necessary, or return null if the conformance does not apply to the /// type. const swift::TargetWitnessTable * getWitnessTable(const TargetMetadata *type) const; /// Retrieve the resilient witnesses. ArrayRef getResilientWitnesses() const{ if (!Flags.hasResilientWitnesses()) return { }; return ArrayRef( this->template getTrailingObjects(), numTrailingObjects(OverloadToken())); } ConstTargetPointer getGenericWitnessTable() const { if (!Flags.hasGenericWitnessTable()) return nullptr; return this->template getTrailingObjects(); } #if !defined(NDEBUG) && SWIFT_OBJC_INTEROP void dump() const; #endif #ifndef NDEBUG /// Verify that the protocol descriptor obeys all invariants. /// /// We currently check that the descriptor: /// /// 1. Has a valid TypeReferenceKind. /// 2. Has a valid conformance kind. void verify() const; #endif private: size_t numTrailingObjects( OverloadToken>) const { return Flags.isRetroactive() ? 1 : 0; } size_t numTrailingObjects(OverloadToken) const { return Flags.getNumConditionalRequirements(); } size_t numTrailingObjects(OverloadToken) const { return Flags.hasResilientWitnesses() ? 1 : 0; } size_t numTrailingObjects(OverloadToken) const { return Flags.hasResilientWitnesses() ? this->template getTrailingObjects() ->NumWitnesses : 0; } size_t numTrailingObjects(OverloadToken) const { return Flags.hasGenericWitnessTable() ? 1 : 0; } }; using ProtocolConformanceDescriptor = TargetProtocolConformanceDescriptor; template using TargetProtocolConformanceRecord = RelativeDirectPointer, /*Nullable=*/false>; using ProtocolConformanceRecord = TargetProtocolConformanceRecord; template struct TargetGenericContext; template struct TargetModuleContextDescriptor; /// Base class for all context descriptors. template struct TargetContextDescriptor { /// Flags describing the context, including its kind and format version. ContextDescriptorFlags Flags; /// The parent context, or null if this is a top-level context. TargetRelativeContextPointer Parent; bool isGeneric() const { return Flags.isGeneric(); } bool isUnique() const { return Flags.isUnique(); } ContextDescriptorKind getKind() const { return Flags.getKind(); } /// Get the generic context information for this context, or null if the /// context is not generic. const TargetGenericContext *getGenericContext() const; /// Get the module context for this context. const TargetModuleContextDescriptor *getModuleContext() const; /// Is this context part of a C-imported module? bool isCImportedContext() const; unsigned getNumGenericParams() const { auto *genericContext = getGenericContext(); return genericContext ? genericContext->getGenericContextHeader().NumParams : 0; } #ifndef NDEBUG LLVM_ATTRIBUTE_DEPRECATED(void dump() const, "only for use in the debugger"); #endif private: TargetContextDescriptor(const TargetContextDescriptor &) = delete; TargetContextDescriptor(TargetContextDescriptor &&) = delete; TargetContextDescriptor &operator=(const TargetContextDescriptor &) = delete; TargetContextDescriptor &operator=(TargetContextDescriptor &&) = delete; }; using ContextDescriptor = TargetContextDescriptor; inline bool isCImportedModuleName(StringRef name) { // This does not include MANGLING_MODULE_CLANG_IMPORTER because that's // used only for synthesized declarations and not actual imported // declarations. return name == MANGLING_MODULE_OBJC; } /// Descriptor for a module context. template struct TargetModuleContextDescriptor final : TargetContextDescriptor { /// The module name. RelativeDirectPointer Name; /// Is this module a special C-imported module? bool isCImportedContext() const { return isCImportedModuleName(Name.get()); } static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::Module; } }; using ModuleContextDescriptor = TargetModuleContextDescriptor; template inline bool TargetContextDescriptor::isCImportedContext() const { return getModuleContext()->isCImportedContext(); } template inline const TargetModuleContextDescriptor * TargetContextDescriptor::getModuleContext() const { // All context chains should eventually find a module. for (auto cur = this; true; cur = cur->Parent.get()) { if (auto module = dyn_cast>(cur)) return module; } } template struct TargetGenericContextDescriptorHeader { uint16_t NumParams, NumRequirements, NumKeyArguments, NumExtraArguments; uint32_t getNumArguments() const { return NumKeyArguments + NumExtraArguments; } bool hasArguments() const { return getNumArguments() > 0; } }; using GenericContextDescriptorHeader = TargetGenericContextDescriptorHeader; template class TargetGenericRequirementDescriptor { public: GenericRequirementFlags Flags; /// The type that's constrained, described as a mangled name. RelativeDirectPointer Param; union { /// A mangled representation of the same-type or base class the param is /// constrained to. /// /// Only valid if the requirement has SameType or BaseClass kind. RelativeDirectPointer Type; /// The protocol the param is constrained to. /// /// Only valid if the requirement has Protocol kind. RelativeTargetProtocolDescriptorPointer Protocol; /// The conformance the param is constrained to use. /// /// Only valid if the requirement has SameConformance kind. RelativeIndirectablePointer, /*nullable*/ false> Conformance; /// The kind of layout constraint. /// /// Only valid if the requirement has Layout kind. GenericRequirementLayoutKind Layout; }; constexpr GenericRequirementFlags getFlags() const { return Flags; } constexpr GenericRequirementKind getKind() const { return getFlags().getKind(); } /// Retrieve the generic parameter that is the subject of this requirement, /// as a mangled type name. StringRef getParam() const { return swift::Demangle::makeSymbolicMangledNameStringRef(Param.get()); } /// Retrieve the protocol for a Protocol requirement. TargetProtocolDescriptorRef getProtocol() const { assert(getKind() == GenericRequirementKind::Protocol); return Protocol; } /// Retrieve the right-hand type for a SameType or BaseClass requirement. StringRef getMangledTypeName() const { assert(getKind() == GenericRequirementKind::SameType || getKind() == GenericRequirementKind::BaseClass); return swift::Demangle::makeSymbolicMangledNameStringRef(Type.get()); } /// Retrieve the protocol conformance record for a SameConformance /// requirement. const TargetProtocolConformanceDescriptor *getConformance() const { assert(getKind() == GenericRequirementKind::SameConformance); return Conformance; } /// Retrieve the layout constraint. GenericRequirementLayoutKind getLayout() const { assert(getKind() == GenericRequirementKind::Layout); return Layout; } /// Determine whether this generic requirement has a known kind. /// /// \returns \c false for any future generic requirement kinds. bool hasKnownKind() const { switch (getKind()) { case GenericRequirementKind::BaseClass: case GenericRequirementKind::Layout: case GenericRequirementKind::Protocol: case GenericRequirementKind::SameConformance: case GenericRequirementKind::SameType: return true; } return false; } }; using GenericRequirementDescriptor = TargetGenericRequirementDescriptor; template class TargetGenericEnvironment : public swift::ABI::TrailingObjects, uint16_t, GenericParamDescriptor, TargetGenericRequirementDescriptor> { using GenericRequirementDescriptor = TargetGenericRequirementDescriptor; using TrailingObjects = swift::ABI::TrailingObjects, uint16_t, GenericParamDescriptor, GenericRequirementDescriptor>; friend TrailingObjects; template using OverloadToken = typename TrailingObjects::template OverloadToken; size_t numTrailingObjects(OverloadToken) const { return Flags.getNumGenericParameterLevels(); } size_t numTrailingObjects(OverloadToken) const { return getGenericParameterCounts().back(); } size_t numTrailingObjects(OverloadToken) const { return Flags.getNumGenericRequirements(); } GenericEnvironmentFlags Flags; public: /// Retrieve the cumulative generic parameter counts at each level of genericity. ArrayRef getGenericParameterCounts() const { return ArrayRef(this->template getTrailingObjects(), Flags.getNumGenericParameterLevels()); } /// Retrieve the generic parameters descriptors. ArrayRef getGenericParameters() const { return ArrayRef( this->template getTrailingObjects(), getGenericParameterCounts().back()); } /// Retrieve the generic requirements. ArrayRef getGenericRequirements() const { return ArrayRef( this->template getTrailingObjects(), Flags.getNumGenericRequirements()); } }; /// CRTP class for a context descriptor that includes trailing generic /// context description. template class TargetGenericContextHeaderType = TargetGenericContextDescriptorHeader, typename... FollowingTrailingObjects> class TrailingGenericContextObjects; // This oddity with partial specialization is necessary to get // reasonable-looking code while also working around various kinds of // compiler bad behavior with injected class names. template class TargetSelf, template class TargetGenericContextHeaderType, typename... FollowingTrailingObjects> class TrailingGenericContextObjects, TargetGenericContextHeaderType, FollowingTrailingObjects...> : protected swift::ABI::TrailingObjects, TargetGenericContextHeaderType, GenericParamDescriptor, TargetGenericRequirementDescriptor, FollowingTrailingObjects...> { protected: using Self = TargetSelf; using GenericContextHeaderType = TargetGenericContextHeaderType; using GenericRequirementDescriptor = TargetGenericRequirementDescriptor; using TrailingObjects = swift::ABI::TrailingObjects; friend TrailingObjects; template using OverloadToken = typename TrailingObjects::template OverloadToken; const Self *asSelf() const { return static_cast(this); } public: using StoredSize = typename Runtime::StoredSize; using StoredPointer = typename Runtime::StoredPointer; const GenericContextHeaderType &getFullGenericContextHeader() const { assert(asSelf()->isGeneric()); return *this->template getTrailingObjects(); } const TargetGenericContextDescriptorHeader & getGenericContextHeader() const { /// HeaderType ought to be convertible to GenericContextDescriptorHeader. return getFullGenericContextHeader(); } const TargetGenericContext *getGenericContext() const { if (!asSelf()->isGeneric()) return nullptr; // The generic context header should always be immediately followed in // memory by trailing parameter and requirement descriptors. auto *header = reinterpret_cast(&getGenericContextHeader()); return reinterpret_cast *>( header - sizeof(TargetGenericContext)); } llvm::ArrayRef getGenericParams() const { if (!asSelf()->isGeneric()) return {}; return {this->template getTrailingObjects(), getGenericContextHeader().NumParams}; } llvm::ArrayRef getGenericRequirements() const { if (!asSelf()->isGeneric()) return {}; return {this->template getTrailingObjects(), getGenericContextHeader().NumRequirements}; } /// Return the amount of space that the generic arguments take up in /// metadata of this type. StoredSize getGenericArgumentsStorageSize() const { return StoredSize(getGenericContextHeader().getNumArguments()) * sizeof(StoredPointer); } protected: size_t numTrailingObjects(OverloadToken) const { return asSelf()->isGeneric() ? 1 : 0; } size_t numTrailingObjects(OverloadToken) const { return asSelf()->isGeneric() ? getGenericContextHeader().NumParams : 0; } size_t numTrailingObjects(OverloadToken) const { return asSelf()->isGeneric() ? getGenericContextHeader().NumRequirements : 0; } }; /// Reference to a generic context. template struct TargetGenericContext final : TrailingGenericContextObjects, TargetGenericContextDescriptorHeader> { // This struct is supposed to be empty, but TrailingObjects respects the // unique-address-per-object C++ rule, so even if this type is empty, the // trailing objects will come after one byte of padding. This dummy field // takes up space to make the offset of the trailing objects portable. unsigned _dummy; bool isGeneric() const { return true; } }; /// Descriptor for an extension context. template struct TargetExtensionContextDescriptor final : TargetContextDescriptor, TrailingGenericContextObjects> { private: using TrailingGenericContextObjects = swift::TrailingGenericContextObjects>; public: /// A mangling of the `Self` type context that the extension extends. /// The mangled name represents the type in the generic context encoded by /// this descriptor. For example, a nongeneric nominal type extension will /// encode the nominal type name. A generic nominal type extension will encode /// the instance of the type with any generic arguments bound. /// /// Note that the Parent of the extension will be the module context the /// extension is declared inside. RelativeDirectPointer ExtendedContext; using TrailingGenericContextObjects::getGenericContext; StringRef getMangledExtendedContext() const { return Demangle::makeSymbolicMangledNameStringRef(ExtendedContext.get()); } static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::Extension; } }; using ExtensionContextDescriptor = TargetExtensionContextDescriptor; template struct TargetMangledContextName { /// The mangled name of the context. TargetRelativeDirectPointer name; }; template struct TargetAnonymousContextDescriptor final : TargetContextDescriptor, TrailingGenericContextObjects, TargetGenericContextDescriptorHeader, TargetMangledContextName> { private: using TrailingGenericContextObjects = swift::TrailingGenericContextObjects, TargetGenericContextDescriptorHeader, TargetMangledContextName>; using TrailingObjects = typename TrailingGenericContextObjects::TrailingObjects; friend TrailingObjects; public: using MangledContextName = TargetMangledContextName; using TrailingGenericContextObjects::getGenericContext; using TrailingGenericContextObjects::getGenericContextHeader; using TrailingGenericContextObjects::getFullGenericContextHeader; using TrailingGenericContextObjects::getGenericParams; AnonymousContextDescriptorFlags getAnonymousContextDescriptorFlags() const { return AnonymousContextDescriptorFlags(this->Flags.getKindSpecificFlags()); } /// Whether this anonymous context descriptor contains a full mangled name, /// which can be used to match the anonymous type to its textual form. bool hasMangledName() const { return getAnonymousContextDescriptorFlags().hasMangledName(); } /// Retrieve the mangled name of this context, or NULL if it was not /// recorded in the metadata. ConstTargetPointer getMangledName() const { if (!hasMangledName()) return ConstTargetPointer(); return this->template getTrailingObjects()->name; } /// Retrieve a pointer to the mangled context name structure. const MangledContextName *getMangledContextName() const { if (!hasMangledName()) return nullptr; return this->template getTrailingObjects(); } private: template using OverloadToken = typename TrailingGenericContextObjects::template OverloadToken; using TrailingGenericContextObjects::numTrailingObjects; size_t numTrailingObjects(OverloadToken) const { return this->hasMangledNam() ? 1 : 0; } public: static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::Anonymous; } }; using AnonymousContextDescriptor = TargetAnonymousContextDescriptor; /// A protocol descriptor. /// /// Protocol descriptors contain information about the contents of a protocol: /// it's name, requirements, requirement signature, context, and so on. They /// are used both to identify a protocol and to reason about its contents. /// /// Only Swift protocols are defined by a protocol descriptor, whereas /// Objective-C (including protocols defined in Swift as @objc) use the /// Objective-C protocol layout. template struct TargetProtocolDescriptor final : TargetContextDescriptor, swift::ABI::TrailingObjects< TargetProtocolDescriptor, TargetGenericRequirementDescriptor, TargetProtocolRequirement> { private: using TrailingObjects = swift::ABI::TrailingObjects< TargetProtocolDescriptor, TargetGenericRequirementDescriptor, TargetProtocolRequirement>; friend TrailingObjects; template using OverloadToken = typename TrailingObjects::template OverloadToken; public: size_t numTrailingObjects( OverloadToken>) const { return NumRequirementsInSignature; } size_t numTrailingObjects( OverloadToken>) const { return NumRequirements; } /// The name of the protocol. TargetRelativeDirectPointer Name; /// The number of generic requirements in the requirement signature of the /// protocol. uint32_t NumRequirementsInSignature; /// The number of requirements in the protocol. /// If any requirements beyond MinimumWitnessTableSizeInWords are present /// in the witness table template, they will be not be overwritten with /// defaults. uint32_t NumRequirements; /// Associated type names, as a space-separated list in the same order /// as the requirements. RelativeDirectPointer AssociatedTypeNames; ProtocolContextDescriptorFlags getProtocolContextDescriptorFlags() const { return ProtocolContextDescriptorFlags(this->Flags.getKindSpecificFlags()); } /// Retrieve the requirements that make up the requirement signature of /// this protocol. llvm::ArrayRef> getRequirementSignature() const { return {this->template getTrailingObjects< TargetGenericRequirementDescriptor>(), NumRequirementsInSignature}; } /// Retrieve the requirements of this protocol. llvm::ArrayRef> getRequirements() const { return {this->template getTrailingObjects< TargetProtocolRequirement>(), NumRequirements}; } /// Retrieve the requirement base descriptor address. ConstTargetPointer> getRequirementBaseDescriptor() const { return getRequirements().data() - WitnessTableFirstRequirementOffset; } #ifndef NDEBUG LLVM_ATTRIBUTE_DEPRECATED(void dump() const, "only for use in the debugger"); #endif static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::Protocol; } }; /// The descriptor for an opaque type. template struct TargetOpaqueTypeDescriptor final : TargetContextDescriptor, TrailingGenericContextObjects, TargetGenericContextDescriptorHeader, RelativeDirectPointer> { private: using TrailingGenericContextObjects = swift::TrailingGenericContextObjects, TargetGenericContextDescriptorHeader, RelativeDirectPointer>; using TrailingObjects = typename TrailingGenericContextObjects::TrailingObjects; friend TrailingObjects; template using OverloadToken = typename TrailingObjects::template OverloadToken; public: using TrailingGenericContextObjects::getGenericContext; using TrailingGenericContextObjects::getGenericContextHeader; using TrailingGenericContextObjects::getFullGenericContextHeader; using TrailingGenericContextObjects::getGenericParams; // The kind-specific flags area is used to store the count of the generic // arguments for underlying type(s) encoded in the descriptor. unsigned getNumUnderlyingTypeArguments() const { return this->Flags.getKindSpecificFlags(); } using TrailingGenericContextObjects::numTrailingObjects; size_t numTrailingObjects(OverloadToken>) const { return getNumUnderlyingTypeArguments(); } const RelativeDirectPointer & getUnderlyingTypeArgumentMangledName(unsigned i) const { assert(i < getNumUnderlyingTypeArguments()); return (this ->template getTrailingObjects>())[i]; } StringRef getUnderlyingTypeArgument(unsigned i) const { assert(i < getNumUnderlyingTypeArguments()); const char *ptr = getUnderlyingTypeArgumentMangledName(i); return Demangle::makeSymbolicMangledNameStringRef(ptr); } static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::OpaqueType; } }; using OpaqueTypeDescriptor = TargetOpaqueTypeDescriptor; /// The instantiation cache for generic metadata. This must be guaranteed /// to zero-initialized before it is first accessed. Its contents are private /// to the runtime. template struct TargetGenericMetadataInstantiationCache { /// Data that the runtime can use for its own purposes. It is guaranteed /// to be zero-filled by the compiler. TargetPointer PrivateData[swift::NumGenericMetadataPrivateDataWords]; }; using GenericMetadataInstantiationCache = TargetGenericMetadataInstantiationCache; /// A function that instantiates metadata. This function is required /// to succeed. /// /// In general, the metadata returned by this function should have all the /// basic structure necessary to identify itself: that is, it must have a /// type descriptor and generic arguments. However, it does not need to be /// fully functional as type metadata; for example, it does not need to have /// a meaningful value witness table, v-table entries, or a superclass. /// /// Operations which may fail (due to e.g. recursive dependencies) but which /// must be performed in order to prepare the metadata object to be fully /// functional as type metadata should be delayed until the completion /// function. using MetadataInstantiator = Metadata *(const TargetTypeContextDescriptor *type, const void *arguments, const TargetGenericMetadataPattern *pattern); /// The opaque completion context of a metadata completion function. /// A completion function that needs to report a completion dependency /// can use this to figure out where it left off and thus avoid redundant /// work when re-invoked. It will be zero on first entry for a type, and /// the runtime is free to copy it to a different location between /// invocations. struct MetadataCompletionContext { void *Data[NumWords_MetadataCompletionContext]; }; /// A function which attempts to complete the given metadata. /// /// This function may fail due to a dependency on the completion of some /// other metadata object. It can indicate this by returning the metadata /// on which it depends. In this case, the function will be invoked again /// when the dependency is resolved. The function must be careful not to /// indicate a completion dependency on a type that has always been /// completed; the runtime cannot reliably distinguish this sort of /// programming failure from a race in which the dependent type was /// completed immediately after it was observed to be incomplete, and so /// the function will be repeatedly re-invoked. /// /// The function will never be called multiple times simultaneously, but /// it may be called many times as successive dependencies are resolved. /// If the function ever completes successfully (by returning null), it /// will not be called again for the same type. using MetadataCompleter = SWIFT_CC(swift) MetadataDependency(const Metadata *type, MetadataCompletionContext *context, const TargetGenericMetadataPattern *pattern); /// An instantiation pattern for type metadata. template struct TargetGenericMetadataPattern { /// The function to call to instantiate the template. TargetRelativeDirectPointer InstantiationFunction; /// The function to call to complete the instantiation. If this is null, /// the instantiation function must always generate complete metadata. TargetRelativeDirectPointer CompletionFunction; /// Flags describing the layout of this instantiation pattern. GenericMetadataPatternFlags PatternFlags; bool hasExtraDataPattern() const { return PatternFlags.hasExtraDataPattern(); } }; using GenericMetadataPattern = TargetGenericMetadataPattern; /// Part of a generic metadata instantiation pattern. template struct TargetGenericMetadataPartialPattern { /// A reference to the pattern. The pattern must always be at least /// word-aligned. TargetRelativeDirectPointer Pattern; /// The offset into the section into which to copy this pattern, in words. uint16_t OffsetInWords; /// The size of the pattern, in words. uint16_t SizeInWords; }; using GenericMetadataPartialPattern = TargetGenericMetadataPartialPattern; /// A base class for conveniently adding trailing fields to a /// generic metadata pattern. template class TargetGenericMetadataPatternTrailingObjects : protected swift::ABI::TrailingObjects, ExtraTrailingObjects...> { using TrailingObjects = swift::ABI::TrailingObjects, ExtraTrailingObjects...>; friend TrailingObjects; using GenericMetadataPartialPattern = TargetGenericMetadataPartialPattern; const Self *asSelf() const { return static_cast(this); } template using OverloadToken = typename TrailingObjects::template OverloadToken; public: /// Return the extra-data pattern. /// /// For class metadata, the existence of this pattern creates the need /// for extra data to be allocated in the metadata. The amount of extra /// data allocated is the sum of the offset and the size of this pattern. /// /// In value metadata, the size of the extra data section is passed to the /// allocation function; this is because it is currently not stored elsewhere /// and because the extra data is principally used for storing values that /// cannot be patterned anyway. /// /// In value metadata, this section is relative to the end of the /// metadata header (e.g. after the last members declared in StructMetadata). /// In class metadata, this section is relative to the end of the entire /// class metadata. /// /// See also: [pre-5.2-extra-data-zeroing] const GenericMetadataPartialPattern *getExtraDataPattern() const { assert(asSelf()->hasExtraDataPattern()); return this->template getTrailingObjects(); } protected: /// Return the class immediate-members pattern. const GenericMetadataPartialPattern *class_getImmediateMembersPattern() const{ assert(asSelf()->class_hasImmediateMembersPattern()); return this->template getTrailingObjects() + size_t(asSelf()->hasExtraDataPattern()); } size_t numTrailingObjects(OverloadToken) const{ return size_t(asSelf()->hasExtraDataPattern()) + size_t(asSelf()->class_hasImmediateMembersPattern()); } }; /// An instantiation pattern for generic class metadata. template struct TargetGenericClassMetadataPattern final : TargetGenericMetadataPattern, TargetGenericMetadataPatternTrailingObjects> { using TrailingObjects = TargetGenericMetadataPatternTrailingObjects>; friend TrailingObjects; using TargetGenericMetadataPattern::PatternFlags; /// The heap-destructor function. TargetRelativeDirectPointer Destroy; /// The ivar-destructor function. TargetRelativeDirectPointer IVarDestroyer; /// The class flags. ClassFlags Flags; // The following fields are only present in ObjC interop. /// The offset of the class RO-data within the extra data pattern, /// in words. uint16_t ClassRODataOffset; /// The offset of the metaclass object within the extra data pattern, /// in words. uint16_t MetaclassObjectOffset; /// The offset of the metaclass RO-data within the extra data pattern, /// in words. uint16_t MetaclassRODataOffset; uint16_t Reserved; bool hasImmediateMembersPattern() const { return PatternFlags.class_hasImmediateMembersPattern(); } const GenericMetadataPartialPattern *getImmediateMembersPattern() const{ return this->class_getImmediateMembersPattern(); } private: bool class_hasImmediateMembersPattern() const { return hasImmediateMembersPattern(); } }; using GenericClassMetadataPattern = TargetGenericClassMetadataPattern; /// An instantiation pattern for generic value metadata. template struct TargetGenericValueMetadataPattern final : TargetGenericMetadataPattern, TargetGenericMetadataPatternTrailingObjects> { using TrailingObjects = TargetGenericMetadataPatternTrailingObjects>; friend TrailingObjects; using TargetGenericMetadataPattern::PatternFlags; /// The value-witness table. Indirectable so that we can re-use tables /// from other libraries if that seems wise. TargetRelativeIndirectablePointer ValueWitnesses; const ValueWitnessTable *getValueWitnessesPattern() const { return ValueWitnesses.get(); } /// Return the metadata kind to use in the instantiation. MetadataKind getMetadataKind() const { return PatternFlags.value_getMetadataKind(); } private: bool class_hasImmediateMembersPattern() const { // It's important to not look at the flag because we use those // bits for other things. return false; } }; using GenericValueMetadataPattern = TargetGenericValueMetadataPattern; template struct TargetTypeGenericContextDescriptorHeader { /// The metadata instantiation cache. TargetRelativeDirectPointer> InstantiationCache; GenericMetadataInstantiationCache *getInstantiationCache() const { return InstantiationCache.get(); } /// The default instantiation pattern. TargetRelativeDirectPointer> DefaultInstantiationPattern; /// The base header. Must always be the final member. TargetGenericContextDescriptorHeader Base; operator const TargetGenericContextDescriptorHeader &() const { return Base; } }; using TypeGenericContextDescriptorHeader = TargetTypeGenericContextDescriptorHeader; /// Wrapper class for the pointer to a metadata access function that provides /// operator() overloads to call it with the right calling convention. class MetadataAccessFunction { MetadataResponse (*Function)(...); static_assert(NumDirectGenericTypeMetadataAccessFunctionArgs == 3, "Need to account for change in number of direct arguments"); public: explicit MetadataAccessFunction(MetadataResponse (*Function)(...)) : Function(Function) {} explicit operator bool() const { return Function != nullptr; } /// For debugging purposes only. explicit operator void*() const { return reinterpret_cast(Function); } /// Invoke with an array of arguments of dynamic size. MetadataResponse operator()(MetadataRequest request, llvm::ArrayRef args) const { switch (args.size()) { case 0: return operator()(request); case 1: return operator()(request, args[0]); case 2: return operator()(request, args[0], args[1]); case 3: return operator()(request, args[0], args[1], args[2]); default: return applyMany(request, args.data()); } } /// Invoke with exactly 0 arguments. MetadataResponse operator()(MetadataRequest request) const { using Fn0 = SWIFT_CC(swift) MetadataResponse(MetadataRequest request); return reinterpret_cast(Function)(request); } /// Invoke with exactly 1 argument. MetadataResponse operator()(MetadataRequest request, const void *arg0) const { using Fn1 = SWIFT_CC(swift) MetadataResponse(MetadataRequest request, const void *arg0); return reinterpret_cast(Function)(request, arg0); } /// Invoke with exactly 2 arguments. MetadataResponse operator()(MetadataRequest request, const void *arg0, const void *arg1) const { using Fn2 = SWIFT_CC(swift) MetadataResponse(MetadataRequest request, const void *arg0, const void *arg1); return reinterpret_cast(Function)(request, arg0, arg1); } /// Invoke with exactly 3 arguments. MetadataResponse operator()(MetadataRequest request, const void *arg0, const void *arg1, const void *arg2) const { using Fn3 = SWIFT_CC(swift) MetadataResponse(MetadataRequest request, const void *arg0, const void *arg1, const void *arg2); return reinterpret_cast(Function)(request, arg0, arg1, arg2); } /// Invoke with more than 3 arguments. template MetadataResponse operator()(MetadataRequest request, const void *arg0, const void *arg1, const void *arg2, Args... argN) const { const void *args[] = { arg0, arg1, arg2, argN... }; return applyMany(request, args); } private: /// In the more-than-max case, just pass all the arguments as an array. MetadataResponse applyMany(MetadataRequest request, const void * const *args) const { using FnN = SWIFT_CC(swift) MetadataResponse(MetadataRequest request, const void * const *args); return reinterpret_cast(Function)(request, args); } }; /// The control structure for performing non-trivial initialization of /// singleton foreign metadata. template struct TargetForeignMetadataInitialization { /// The completion function. The pattern will always be null. TargetRelativeDirectPointer CompletionFunction; }; /// The cache structure for non-trivial initialization of singleton value /// metadata. template struct TargetSingletonMetadataCache { /// The metadata pointer. Clients can do dependency-ordered loads /// from this, and if they see a non-zero value, it's a Complete /// metadata. std::atomic> Metadata; /// The private cache data. std::atomic> Private; }; using SingletonMetadataCache = TargetSingletonMetadataCache; template struct TargetResilientClassMetadataPattern; /// A function for allocating metadata for a resilient class, calculating /// the correct metadata size at runtime. using MetadataRelocator = Metadata *(const TargetTypeContextDescriptor *type, const TargetResilientClassMetadataPattern *pattern); /// An instantiation pattern for non-generic resilient class metadata. /// /// Used for classes with resilient ancestry, that is, where at least one /// ancestor is defined in a different resilience domain. /// /// The hasResilientSuperclass() flag in the class context descriptor is /// set in this case, and hasSingletonMetadataInitialization() must be /// set as well. /// /// The pattern is referenced from the SingletonMetadataInitialization /// record in the class context descriptor. template struct TargetResilientClassMetadataPattern { /// A function that allocates metadata with the correct size at runtime. /// /// If this is null, the runtime instead calls swift_relocateClassMetadata(), /// passing in the class descriptor and this pattern. TargetRelativeDirectPointer RelocationFunction; /// The heap-destructor function. TargetRelativeDirectPointer Destroy; /// The ivar-destructor function. TargetRelativeDirectPointer IVarDestroyer; /// The class flags. ClassFlags Flags; // The following fields are only present in ObjC interop. /// Our ClassROData. TargetRelativeDirectPointer Data; /// Our metaclass. TargetRelativeDirectPointer> Metaclass; }; using ResilientClassMetadataPattern = TargetResilientClassMetadataPattern; /// The control structure for performing non-trivial initialization of /// singleton value metadata, which is required when e.g. a non-generic /// value type has a resilient component type. template struct TargetSingletonMetadataInitialization { /// The initialization cache. Out-of-line because mutable. TargetRelativeDirectPointer> InitializationCache; union { /// The incomplete metadata, for structs, enums and classes without /// resilient ancestry. TargetRelativeDirectPointer> IncompleteMetadata; /// If the class descriptor's hasResilientSuperclass() flag is set, /// this field instead points at a pattern used to allocate and /// initialize metadata for this class, since it's size and contents /// is not known at compile time. TargetRelativeDirectPointer> ResilientPattern; }; /// The completion function. The pattern will always be null, even /// for a resilient class. TargetRelativeDirectPointer CompletionFunction; bool hasResilientClassPattern( const TargetTypeContextDescriptor *description) const { auto *classDescription = dyn_cast>(description); return (classDescription != nullptr && classDescription->hasResilientSuperclass()); } /// This method can only be called from the runtime itself. It is defined /// in Metadata.cpp. TargetMetadata *allocate( const TargetTypeContextDescriptor *description) const; }; template class TargetTypeContextDescriptor : public TargetContextDescriptor { public: /// The name of the type. TargetRelativeDirectPointer Name; /// A pointer to the metadata access function for this type. /// /// The function type here is a stand-in. You should use getAccessFunction() /// to wrap the function pointer in an accessor that uses the proper calling /// convention for a given number of arguments. TargetRelativeDirectPointer AccessFunctionPtr; /// A pointer to the field descriptor for the type, if any. TargetRelativeDirectPointer Fields; bool isReflectable() const { return (bool)Fields; } MetadataAccessFunction getAccessFunction() const { return MetadataAccessFunction(AccessFunctionPtr.get()); } TypeContextDescriptorFlags getTypeContextDescriptorFlags() const { return TypeContextDescriptorFlags(this->Flags.getKindSpecificFlags()); } /// Return the kind of metadata initialization required by this type. /// Note that this is only meaningful for non-generic types. TypeContextDescriptorFlags::MetadataInitializationKind getMetadataInitialization() const { return getTypeContextDescriptorFlags().getMetadataInitialization(); } /// Does this type have non-trivial "singleton" metadata initialization? /// /// The type of the initialization-control structure differs by subclass, /// so it doesn't appear here. bool hasSingletonMetadataInitialization() const { return getTypeContextDescriptorFlags().hasSingletonMetadataInitialization(); } /// Does this type have "foreign" metadata initialiation? bool hasForeignMetadataInitialization() const { return getTypeContextDescriptorFlags().hasForeignMetadataInitialization(); } /// Given that this type has foreign metadata initialization, return the /// control structure for it. const TargetForeignMetadataInitialization & getForeignMetadataInitialization() const; const TargetSingletonMetadataInitialization & getSingletonMetadataInitialization() const; const TargetTypeGenericContextDescriptorHeader & getFullGenericContextHeader() const; const TargetGenericContextDescriptorHeader & getGenericContextHeader() const { return getFullGenericContextHeader(); } llvm::ArrayRef getGenericParams() const; /// Return the offset of the start of generic arguments in the nominal /// type's metadata. The returned value is measured in sizeof(StoredPointer). int32_t getGenericArgumentOffset() const; /// Return the start of the generic arguments array in the nominal /// type's metadata. The returned value is measured in sizeof(StoredPointer). const TargetMetadata * const *getGenericArguments( const TargetMetadata *metadata) const { auto offset = getGenericArgumentOffset(); auto words = reinterpret_cast * const *>(metadata); return words + offset; } static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() >= ContextDescriptorKind::Type_First && cd->getKind() <= ContextDescriptorKind::Type_Last; } }; using TypeContextDescriptor = TargetTypeContextDescriptor; /// Storage for class metadata bounds. This is the variable returned /// by getAddrOfClassMetadataBounds in the compiler. /// /// This storage is initialized before the allocation of any metadata /// for the class to which it belongs. In classes without resilient /// superclasses, it is initialized statically with values derived /// during compilation. In classes with resilient superclasses, it /// is initialized dynamically, generally during the allocation of /// the first metadata of this class's type. If metadata for this /// class is available to you to use, you must have somehow synchronized /// with the thread which allocated the metadata, and therefore the /// complete initialization of this variable is also ordered before /// your access. That is why you can safely access this variable, /// and moreover access it without further atomic accesses. However, /// since this variable may be accessed in a way that is not dependency- /// ordered on the metadata pointer, it is important that you do a full /// synchronization and not just a dependency-ordered (consume) /// synchronization when sharing class metadata pointers between /// threads. (There are other reasons why this is true; for example, /// field offset variables are also accessed without dependency-ordering.) /// /// If you are accessing this storage without such a guarantee, you /// should be aware that it may be lazily initialized, and moreover /// it may be getting lazily initialized from another thread. To ensure /// correctness, the fields must be read in the correct order: the /// immediate-members offset is initialized last with a store-release, /// so it must be read first with a load-acquire, and if the result /// is non-zero then the rest of the variable is known to be valid. /// (No locking is required because racing initializations should always /// assign the same values to the storage.) template struct TargetStoredClassMetadataBounds { using StoredPointerDifference = typename Runtime::StoredPointerDifference; /// The offset to the immediate members. This value is in bytes so that /// clients don't have to sign-extend it. /// It is not necessary to use atomic-ordered loads when accessing this /// variable just to read the immediate-members offset when drilling to /// the immediate members of an already-allocated metadata object. /// The proper initialization of this variable is always ordered before /// any allocation of metadata for this class. std::atomic ImmediateMembersOffset; /// The positive and negative bounds of the class metadata. TargetMetadataBounds Bounds; /// Attempt to read the cached immediate-members offset. /// /// \return true if the read was successful, or false if the cache hasn't /// been filled yet bool tryGetImmediateMembersOffset(StoredPointerDifference &output) { output = ImmediateMembersOffset.load(std::memory_order_relaxed); return output != 0; } /// Attempt to read the full cached bounds. /// /// \return true if the read was successful, or false if the cache hasn't /// been filled yet bool tryGet(TargetClassMetadataBounds &output) { auto offset = ImmediateMembersOffset.load(std::memory_order_acquire); if (offset == 0) return false; output.ImmediateMembersOffset = offset; output.NegativeSizeInWords = Bounds.NegativeSizeInWords; output.PositiveSizeInWords = Bounds.PositiveSizeInWords; return true; } void initialize(TargetClassMetadataBounds value) { assert(value.ImmediateMembersOffset != 0 && "attempting to initialize metadata bounds cache to a zero state!"); Bounds.NegativeSizeInWords = value.NegativeSizeInWords; Bounds.PositiveSizeInWords = value.PositiveSizeInWords; ImmediateMembersOffset.store(value.ImmediateMembersOffset, std::memory_order_release); } }; using StoredClassMetadataBounds = TargetStoredClassMetadataBounds; template struct TargetResilientSuperclass { /// The superclass of this class. This pointer can be interpreted /// using the superclass reference kind stored in the type context /// descriptor flags. It is null if the class has no formal superclass. /// /// Note that SwiftObject, the implicit superclass of all Swift root /// classes when building with ObjC compatibility, does not appear here. TargetRelativeDirectPointer Superclass; }; /// A structure that stores a reference to an Objective-C class stub. /// /// This is not the class stub itself; it is part of a class context /// descriptor. template struct TargetObjCResilientClassStubInfo { /// A relative pointer to an Objective-C resilient class stub. /// /// We do not declare a struct type for class stubs since the Swift runtime /// does not need to interpret them. The class stub struct is part of /// the Objective-C ABI, and is laid out as follows: /// - isa pointer, always 1 /// - an update callback, of type 'Class (*)(Class *, objc_class_stub *)' /// /// Class stubs are used for two purposes: /// /// - Objective-C can reference class stubs when calling static methods. /// - Objective-C and Swift can reference class stubs when emitting /// categories (in Swift, extensions with @objc members). TargetRelativeDirectPointer Stub; }; template class TargetClassDescriptor final : public TargetTypeContextDescriptor, public TrailingGenericContextObjects, TargetTypeGenericContextDescriptorHeader, /*additional trailing objects:*/ TargetResilientSuperclass, TargetForeignMetadataInitialization, TargetSingletonMetadataInitialization, TargetVTableDescriptorHeader, TargetMethodDescriptor, TargetOverrideTableHeader, TargetMethodOverrideDescriptor, TargetObjCResilientClassStubInfo> { private: using TrailingGenericContextObjects = swift::TrailingGenericContextObjects, TargetTypeGenericContextDescriptorHeader, TargetResilientSuperclass, TargetForeignMetadataInitialization, TargetSingletonMetadataInitialization, TargetVTableDescriptorHeader, TargetMethodDescriptor, TargetOverrideTableHeader, TargetMethodOverrideDescriptor, TargetObjCResilientClassStubInfo>; using TrailingObjects = typename TrailingGenericContextObjects::TrailingObjects; friend TrailingObjects; public: using MethodDescriptor = TargetMethodDescriptor; using VTableDescriptorHeader = TargetVTableDescriptorHeader; using OverrideTableHeader = TargetOverrideTableHeader; using MethodOverrideDescriptor = TargetMethodOverrideDescriptor; using ResilientSuperclass = TargetResilientSuperclass; using ForeignMetadataInitialization = TargetForeignMetadataInitialization; using SingletonMetadataInitialization = TargetSingletonMetadataInitialization; using ObjCResilientClassStubInfo = TargetObjCResilientClassStubInfo; using StoredPointer = typename Runtime::StoredPointer; using StoredPointerDifference = typename Runtime::StoredPointerDifference; using StoredSize = typename Runtime::StoredSize; using TrailingGenericContextObjects::getGenericContext; using TrailingGenericContextObjects::getGenericContextHeader; using TrailingGenericContextObjects::getFullGenericContextHeader; using TrailingGenericContextObjects::getGenericParams; using TargetTypeContextDescriptor::getTypeContextDescriptorFlags; TypeReferenceKind getResilientSuperclassReferenceKind() const { return getTypeContextDescriptorFlags() .class_getResilientSuperclassReferenceKind(); } /// The type of the superclass, expressed as a mangled type name that can /// refer to the generic arguments of the subclass type. TargetRelativeDirectPointer SuperclassType; union { /// If this descriptor does not have a resilient superclass, this is the /// negative size of metadata objects of this class (in words). uint32_t MetadataNegativeSizeInWords; /// If this descriptor has a resilient superclass, this is a reference /// to a cache holding the metadata's extents. TargetRelativeDirectPointer> ResilientMetadataBounds; }; union { /// If this descriptor does not have a resilient superclass, this is the /// positive size of metadata objects of this class (in words). uint32_t MetadataPositiveSizeInWords; /// Otherwise, these flags are used to do things like indicating /// the presence of an Objective-C resilient class stub. ExtraClassDescriptorFlags ExtraClassFlags; }; /// The number of additional members added by this class to the class /// metadata. This data is opaque by default to the runtime, other than /// as exposed in other members; it's really just /// NumImmediateMembers * sizeof(void*) bytes of data. /// /// Whether those bytes are added before or after the address point /// depends on areImmediateMembersNegative(). uint32_t NumImmediateMembers; // ABI: could be uint16_t? StoredSize getImmediateMembersSize() const { return StoredSize(NumImmediateMembers) * sizeof(StoredPointer); } /// Are the immediate members of the class metadata allocated at negative /// offsets instead of positive? bool areImmediateMembersNegative() const { return getTypeContextDescriptorFlags().class_areImmediateMembersNegative(); } /// The number of stored properties in the class, not including its /// superclasses. If there is a field offset vector, this is its length. uint32_t NumFields; private: /// The offset of the field offset vector for this class's stored /// properties in its metadata, in words. 0 means there is no field offset /// vector. /// /// If this class has a resilient superclass, this offset is relative to /// the size of the resilient superclass metadata. Otherwise, it is /// absolute. uint32_t FieldOffsetVectorOffset; template using OverloadToken = typename TrailingGenericContextObjects::template OverloadToken; using TrailingGenericContextObjects::numTrailingObjects; size_t numTrailingObjects(OverloadToken) const { return this->hasResilientSuperclass() ? 1 : 0; } size_t numTrailingObjects(OverloadToken) const{ return this->hasForeignMetadataInitialization() ? 1 : 0; } size_t numTrailingObjects(OverloadToken) const{ return this->hasSingletonMetadataInitialization() ? 1 : 0; } size_t numTrailingObjects(OverloadToken) const { return hasVTable() ? 1 : 0; } size_t numTrailingObjects(OverloadToken) const { if (!hasVTable()) return 0; return getVTableDescriptor()->VTableSize; } size_t numTrailingObjects(OverloadToken) const { return hasOverrideTable() ? 1 : 0; } size_t numTrailingObjects(OverloadToken) const { if (!hasOverrideTable()) return 0; return getOverrideTable()->NumEntries; } size_t numTrailingObjects(OverloadToken) const { return hasObjCResilientClassStub() ? 1 : 0; } public: const TargetRelativeDirectPointer & getResilientSuperclass() const { assert(this->hasResilientSuperclass()); return this->template getTrailingObjects()->Superclass; } const ForeignMetadataInitialization &getForeignMetadataInitialization() const{ assert(this->hasForeignMetadataInitialization()); return *this->template getTrailingObjects(); } const SingletonMetadataInitialization &getSingletonMetadataInitialization() const{ assert(this->hasSingletonMetadataInitialization()); return *this->template getTrailingObjects(); } /// True if metadata records for this type have a field offset vector for /// its stored properties. bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; } unsigned getFieldOffsetVectorOffset() const { if (hasResilientSuperclass()) { auto bounds = getMetadataBounds(); return (bounds.ImmediateMembersOffset / sizeof(StoredPointer) + FieldOffsetVectorOffset); } return FieldOffsetVectorOffset; } bool hasVTable() const { return this->getTypeContextDescriptorFlags().class_hasVTable(); } bool hasOverrideTable() const { return this->getTypeContextDescriptorFlags().class_hasOverrideTable(); } bool hasResilientSuperclass() const { return this->getTypeContextDescriptorFlags().class_hasResilientSuperclass(); } const VTableDescriptorHeader *getVTableDescriptor() const { if (!hasVTable()) return nullptr; return this->template getTrailingObjects(); } llvm::ArrayRef getMethodDescriptors() const { if (!hasVTable()) return {}; return {this->template getTrailingObjects(), numTrailingObjects(OverloadToken{})}; } const OverrideTableHeader *getOverrideTable() const { if (!hasOverrideTable()) return nullptr; return this->template getTrailingObjects(); } llvm::ArrayRef getMethodOverrideDescriptors() const { if (!hasOverrideTable()) return {}; return {this->template getTrailingObjects(), numTrailingObjects(OverloadToken{})}; } /// Return the bounds of this class's metadata. TargetClassMetadataBounds getMetadataBounds() const { if (!hasResilientSuperclass()) return getNonResilientMetadataBounds(); // This lookup works by ADL and will intentionally fail for // non-InProcess instantiations. return getResilientMetadataBounds(this); } /// Given that this class is known to not have a resilient superclass /// return its metadata bounds. TargetClassMetadataBounds getNonResilientMetadataBounds() const { return { getNonResilientImmediateMembersOffset() * StoredPointerDifference(sizeof(void*)), MetadataNegativeSizeInWords, MetadataPositiveSizeInWords }; } /// Return the offset of the start of generic arguments in the nominal /// type's metadata. The returned value is measured in words. int32_t getGenericArgumentOffset() const { if (!hasResilientSuperclass()) return getNonResilientGenericArgumentOffset(); // This lookup works by ADL and will intentionally fail for // non-InProcess instantiations. return getResilientImmediateMembersOffset(this); } /// Given that this class is known to not have a resilient superclass, /// return the offset of its generic arguments in words. int32_t getNonResilientGenericArgumentOffset() const { return getNonResilientImmediateMembersOffset(); } /// Given that this class is known to not have a resilient superclass, /// return the offset of its immediate members in words. int32_t getNonResilientImmediateMembersOffset() const { assert(!hasResilientSuperclass()); return areImmediateMembersNegative() ? -int32_t(MetadataNegativeSizeInWords) : int32_t(MetadataPositiveSizeInWords - NumImmediateMembers); } void *getMethod(unsigned i) const { assert(hasVTable() && i < numTrailingObjects(OverloadToken{})); return getMethodDescriptors()[i].Impl.get(); } /// Whether this context descriptor references an Objective-C resilient /// class stub. See the above description of TargetObjCResilientClassStubInfo /// for details. bool hasObjCResilientClassStub() const { if (!hasResilientSuperclass()) return false; return ExtraClassFlags.hasObjCResilientClassStub(); } const void *getObjCResilientClassStub() const { if (!hasObjCResilientClassStub()) return nullptr; return this->template getTrailingObjects() ->Stub.get(); } static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::Class; } }; using ClassDescriptor = TargetClassDescriptor; template class TargetValueTypeDescriptor : public TargetTypeContextDescriptor { public: static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::Struct || cd->getKind() == ContextDescriptorKind::Enum; } }; using ValueTypeDescriptor = TargetValueTypeDescriptor; template class TargetStructDescriptor final : public TargetValueTypeDescriptor, public TrailingGenericContextObjects, TargetTypeGenericContextDescriptorHeader, /*additional trailing objects*/ TargetForeignMetadataInitialization, TargetSingletonMetadataInitialization> { public: using ForeignMetadataInitialization = TargetForeignMetadataInitialization; using SingletonMetadataInitialization = TargetSingletonMetadataInitialization; private: using TrailingGenericContextObjects = swift::TrailingGenericContextObjects, TargetTypeGenericContextDescriptorHeader, ForeignMetadataInitialization, SingletonMetadataInitialization>; using TrailingObjects = typename TrailingGenericContextObjects::TrailingObjects; friend TrailingObjects; template using OverloadToken = typename TrailingObjects::template OverloadToken; using TrailingGenericContextObjects::numTrailingObjects; size_t numTrailingObjects(OverloadToken) const{ return this->hasForeignMetadataInitialization() ? 1 : 0; } size_t numTrailingObjects(OverloadToken) const{ return this->hasSingletonMetadataInitialization() ? 1 : 0; } public: using TrailingGenericContextObjects::getGenericContext; using TrailingGenericContextObjects::getGenericContextHeader; using TrailingGenericContextObjects::getFullGenericContextHeader; using TrailingGenericContextObjects::getGenericParams; /// The number of stored properties in the struct. /// If there is a field offset vector, this is its length. uint32_t NumFields; /// The offset of the field offset vector for this struct's stored /// properties in its metadata, if any. 0 means there is no field offset /// vector. uint32_t FieldOffsetVectorOffset; /// True if metadata records for this type have a field offset vector for /// its stored properties. bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; } const ForeignMetadataInitialization &getForeignMetadataInitialization() const{ assert(this->hasForeignMetadataInitialization()); return *this->template getTrailingObjects(); } const SingletonMetadataInitialization &getSingletonMetadataInitialization() const{ assert(this->hasSingletonMetadataInitialization()); return *this->template getTrailingObjects(); } static constexpr int32_t getGenericArgumentOffset() { return TargetStructMetadata::getGenericArgumentOffset(); } static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::Struct; } }; using StructDescriptor = TargetStructDescriptor; template class TargetEnumDescriptor final : public TargetValueTypeDescriptor, public TrailingGenericContextObjects, TargetTypeGenericContextDescriptorHeader, /*additional trailing objects*/ TargetForeignMetadataInitialization, TargetSingletonMetadataInitialization> { public: using SingletonMetadataInitialization = TargetSingletonMetadataInitialization; using ForeignMetadataInitialization = TargetForeignMetadataInitialization; private: using TrailingGenericContextObjects = swift::TrailingGenericContextObjects, TargetTypeGenericContextDescriptorHeader, ForeignMetadataInitialization, SingletonMetadataInitialization>; using TrailingObjects = typename TrailingGenericContextObjects::TrailingObjects; friend TrailingObjects; template using OverloadToken = typename TrailingObjects::template OverloadToken; using TrailingGenericContextObjects::numTrailingObjects; size_t numTrailingObjects(OverloadToken) const{ return this->hasForeignMetadataInitialization() ? 1 : 0; } size_t numTrailingObjects(OverloadToken) const{ return this->hasSingletonMetadataInitialization() ? 1 : 0; } public: using TrailingGenericContextObjects::getGenericContext; using TrailingGenericContextObjects::getGenericContextHeader; using TrailingGenericContextObjects::getFullGenericContextHeader; using TrailingGenericContextObjects::getGenericParams; /// The number of non-empty cases in the enum are in the low 24 bits; /// the offset of the payload size in the metadata record in words, /// if any, is stored in the high 8 bits. uint32_t NumPayloadCasesAndPayloadSizeOffset; /// The number of empty cases in the enum. uint32_t NumEmptyCases; uint32_t getNumPayloadCases() const { return NumPayloadCasesAndPayloadSizeOffset & 0x00FFFFFFU; } uint32_t getNumEmptyCases() const { return NumEmptyCases; } uint32_t getNumCases() const { return getNumPayloadCases() + NumEmptyCases; } size_t getPayloadSizeOffset() const { return ((NumPayloadCasesAndPayloadSizeOffset & 0xFF000000U) >> 24); } bool hasPayloadSizeOffset() const { return getPayloadSizeOffset() != 0; } static constexpr int32_t getGenericArgumentOffset() { return TargetEnumMetadata::getGenericArgumentOffset(); } const ForeignMetadataInitialization &getForeignMetadataInitialization() const{ assert(this->hasForeignMetadataInitialization()); return *this->template getTrailingObjects(); } const SingletonMetadataInitialization &getSingletonMetadataInitialization() const{ assert(this->hasSingletonMetadataInitialization()); return *this->template getTrailingObjects(); } static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::Enum; } #ifndef NDEBUG LLVM_ATTRIBUTE_DEPRECATED(void dump() const, "Only meant for use in the debugger"); #endif }; using EnumDescriptor = TargetEnumDescriptor; template inline const TargetGenericContext * TargetContextDescriptor::getGenericContext() const { if (!isGeneric()) return nullptr; switch (getKind()) { case ContextDescriptorKind::Module: // Never generic. return nullptr; case ContextDescriptorKind::Extension: return llvm::cast>(this) ->getGenericContext(); case ContextDescriptorKind::Anonymous: return llvm::cast>(this) ->getGenericContext(); case ContextDescriptorKind::Class: return llvm::cast>(this) ->getGenericContext(); case ContextDescriptorKind::Enum: return llvm::cast>(this) ->getGenericContext(); case ContextDescriptorKind::Struct: return llvm::cast>(this) ->getGenericContext(); case ContextDescriptorKind::OpaqueType: return llvm::cast>(this) ->getGenericContext(); default: // We don't know about this kind of descriptor. return nullptr; } } template int32_t TargetTypeContextDescriptor::getGenericArgumentOffset() const { switch (this->getKind()) { case ContextDescriptorKind::Class: return llvm::cast>(this) ->getGenericArgumentOffset(); case ContextDescriptorKind::Enum: return llvm::cast>(this) ->getGenericArgumentOffset(); case ContextDescriptorKind::Struct: return llvm::cast>(this) ->getGenericArgumentOffset(); default: swift_runtime_unreachable("Not a type context descriptor."); } } template const TargetTypeGenericContextDescriptorHeader & TargetTypeContextDescriptor::getFullGenericContextHeader() const { switch (this->getKind()) { case ContextDescriptorKind::Class: return llvm::cast>(this) ->getFullGenericContextHeader(); case ContextDescriptorKind::Enum: return llvm::cast>(this) ->getFullGenericContextHeader(); case ContextDescriptorKind::Struct: return llvm::cast>(this) ->getFullGenericContextHeader(); default: swift_runtime_unreachable("Not a type context descriptor."); } } template llvm::ArrayRef TargetTypeContextDescriptor::getGenericParams() const { switch (this->getKind()) { case ContextDescriptorKind::Class: return llvm::cast>(this)->getGenericParams(); case ContextDescriptorKind::Enum: return llvm::cast>(this)->getGenericParams(); case ContextDescriptorKind::Struct: return llvm::cast>(this)->getGenericParams(); case ContextDescriptorKind::OpaqueType: return llvm::cast>(this)->getGenericParams(); default: swift_runtime_unreachable("Not a type context descriptor."); } } template const TargetForeignMetadataInitialization & TargetTypeContextDescriptor::getForeignMetadataInitialization() const { switch (this->getKind()) { case ContextDescriptorKind::Class: return llvm::cast>(this) ->getForeignMetadataInitialization(); case ContextDescriptorKind::Enum: return llvm::cast>(this) ->getForeignMetadataInitialization(); case ContextDescriptorKind::Struct: return llvm::cast>(this) ->getForeignMetadataInitialization(); default: swift_runtime_unreachable("Not a type context descriptor."); } } template inline const TargetSingletonMetadataInitialization & TargetTypeContextDescriptor::getSingletonMetadataInitialization() const { switch (this->getKind()) { case ContextDescriptorKind::Enum: return llvm::cast>(this) ->getSingletonMetadataInitialization(); case ContextDescriptorKind::Struct: return llvm::cast>(this) ->getSingletonMetadataInitialization(); case ContextDescriptorKind::Class: return llvm::cast>(this) ->getSingletonMetadataInitialization(); default: swift_runtime_unreachable("Not a enum, struct or class type descriptor."); } } /// An entry in the chain of dynamic replacement functions. struct DynamicReplacementChainEntry { void *implementationFunction; DynamicReplacementChainEntry *next; }; /// A record describing the root of dynamic replacements for a function. struct DynamicReplacementKey { RelativeDirectPointer root; uint32_t flags; uint16_t getExtraDiscriminator() const { return flags & 0x0000FFFF; } }; /// A record describing a dynamic function replacement. class DynamicReplacementDescriptor { RelativeIndirectablePointer< const DynamicReplacementKey, false, int32_t, TargetSignedPointer> replacedFunctionKey; RelativeDirectPointer replacementFunction; RelativeDirectPointer chainEntry; uint32_t flags; enum : uint32_t { EnableChainingMask = 0x1 }; public: /// Enable this replacement by changing the function's replacement chain's /// root entry. /// This replacement must be done while holding a global lock that guards this /// function's chain. Currently this is done by holding the /// \p DynamicReplacementLock. void enableReplacement() const; /// Disable this replacement by changing the function's replacement chain's /// root entry. /// This replacement must be done while holding a global lock that guards this /// function's chain. Currently this is done by holding the /// \p DynamicReplacementLock. void disableReplacement() const; uint32_t getFlags() const { return flags; } bool shouldChain() const { return (flags & EnableChainingMask); } }; /// A collection of dynamic replacement records. class DynamicReplacementScope : private swift::ABI::TrailingObjects { uint32_t flags; uint32_t numReplacements; using TrailingObjects = swift::ABI::TrailingObjects; friend TrailingObjects; ArrayRef getReplacementDescriptors() const { return {this->template getTrailingObjects(), numReplacements}; } public: void enable() const { for (auto &descriptor : getReplacementDescriptors()) { descriptor.enableReplacement(); } } void disable() const { for (auto &descriptor : getReplacementDescriptors()) { descriptor.disableReplacement(); } } uint32_t getFlags() { return flags; } }; } // end namespace swift #pragma clang diagnostic pop #endif // SWIFT_ABI_METADATA_H