//===--- 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 <atomic>
#include <iterator>
#include <string>
#include <type_traits>
#include <utility>
#include <string.h>
#include "llvm/ADT/ArrayRef.h"
#include "swift/Strings.h"
#include "swift/Runtime/Config.h"
#include "swift/Runtime/Once.h"
#include "swift/ABI/GenericContext.h"
#include "swift/ABI/MetadataRef.h"
#include "swift/ABI/MetadataValues.h"
#include "swift/ABI/System.h"
#include "swift/ABI/TargetLayout.h"
#include "swift/ABI/TrailingObjects.h"
#include "swift/ABI/ValueWitnessTable.h"
#include "swift/Basic/Malloc.h"
#include "swift/Basic/FlaggedPointer.h"
#include "swift/Basic/RelativePointer.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Demangling/ManglingMacros.h"
#include "swift/Basic/Unreachable.h"
#include "swift/shims/HeapObject.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Casting.h"

namespace swift {

template <typename Runtime> struct TargetGenericMetadataInstantiationCache;
template <typename Runtime> struct TargetAnyClassMetadata;
template <typename Runtime> struct TargetAnyClassMetadataObjCInterop;
template <typename Runtime, typename TargetAnyClassMetadataVariant>
struct TargetClassMetadata;
template <typename Runtime> struct TargetStructMetadata;
template <typename Runtime> struct TargetOpaqueMetadata;
template <typename Runtime> struct TargetValueMetadata;
template <typename Runtime> struct TargetForeignClassMetadata;
template <typename Runtime> struct TargetForeignReferenceTypeMetadata;
template <typename Runtime>
struct swift_ptrauth_struct_context_descriptor(ContextDescriptor)
    TargetContextDescriptor;
template <typename Runtime>
class swift_ptrauth_struct_context_descriptor(TypeContextDescriptor)
    TargetTypeContextDescriptor;
template <typename Runtime>
class swift_ptrauth_struct_context_descriptor(ClassDescriptor)
    TargetClassDescriptor;
template <typename Runtime>
class swift_ptrauth_struct_context_descriptor(ValueTypeDescriptor)
    TargetValueTypeDescriptor;
template <typename Runtime>
class swift_ptrauth_struct_context_descriptor(EnumDescriptor)
    TargetEnumDescriptor;
template <typename Runtime>
class swift_ptrauth_struct_context_descriptor(StructDescriptor)
    TargetStructDescriptor;
template <typename Runtime> struct TargetGenericMetadataPattern;
template <typename Runtime> struct TargetProtocolConformanceDescriptor;

struct HeapObject;
class WeakReference;
struct UnownedReference;

using HeapObjectDestroyer =
  SWIFT_CC(swift) void(SWIFT_CONTEXT HeapObject *);

/// The result of requesting type metadata.  Generally the return value of
/// a function.
///
/// For performance and ABI matching across Swift/C++, functions returning
/// this type must use SWIFT_CC so that the components are returned as separate
/// values.
struct MetadataResponse {
  /// The requested metadata.
  const Metadata *Value;

  /// The current state of the metadata returned.  Always use this
  /// instead of trying to inspect the metadata directly to see if it
  /// satisfies the request.  An incomplete metadata may be getting
  /// initialized concurrently.  But this can generally be ignored if
  /// the metadata request was for abstract metadata or if the request
  /// is blocking.
  MetadataState State;
};

/// A dependency on the metadata progress of other type, indicating that
/// initialization of a metadata cannot progress until another metadata
/// reaches a particular state.
///
/// For performance, functions returning this type should use SWIFT_CC so
/// that the components are returned as separate values.
struct MetadataDependency {
  /// Either null, indicating that initialization was successful, or
  /// a metadata on which initialization depends for further progress.
  const Metadata *Value;

  /// The state that Metadata needs to be in before initialization
  /// can continue.
  MetadataState Requirement;

  MetadataDependency() : Value(nullptr) {}
  MetadataDependency(const Metadata *metadata, MetadataState requirement)
    : Value(metadata), Requirement(requirement) {}

  explicit operator bool() const { return Value != nullptr; }

  bool operator==(MetadataDependency other) const {
    assert(Value && other.Value);
    return Value == other.Value &&
           Requirement == other.Requirement;
  }
};

/// Prefix of a metadata header, containing a pointer to the
/// type layout string.
template <typename Runtime>
struct TargetTypeMetadataLayoutPrefix {
    TargetSignedPointer<Runtime, const uint8_t *
                                      __ptrauth_swift_type_layout_string>
        layoutString;
};

/// The header before a metadata object which appears on all type
/// metadata.  Note that heap metadata are not necessarily type
/// metadata, even for objects of a heap type: for example, objects of
/// Objective-C type possess a form of heap metadata (an Objective-C
/// Class pointer), but this metadata lacks the type metadata header.
/// This case can be distinguished using the isTypeMetadata() flag
/// on ClassMetadata.
template <typename Runtime>
struct TargetTypeMetadataHeaderBase {
  /// A pointer to the value-witnesses for this type.  This is only
  /// present for type metadata.
  TargetPointer<Runtime, const TargetValueWitnessTable<Runtime>> ValueWitnesses;
};

template <typename Runtime>
struct TargetTypeMetadataHeader
    : TargetTypeMetadataLayoutPrefix<Runtime>,
      TargetTypeMetadataHeaderBase<Runtime> {

  TargetTypeMetadataHeader() = default;
  constexpr TargetTypeMetadataHeader(
    const TargetTypeMetadataLayoutPrefix<Runtime> &layout,
    const TargetTypeMetadataHeaderBase<Runtime> &header)
      : TargetTypeMetadataLayoutPrefix<Runtime>(layout),
        TargetTypeMetadataHeaderBase<Runtime>(header) {}
};

using TypeMetadataHeader = TargetTypeMetadataHeader<InProcess>;

/// 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 <class T> struct FullMetadata : T::HeaderType, T {
  typedef typename T::HeaderType HeaderType;

  FullMetadata() = default;
  constexpr FullMetadata(const HeaderType &header, const T &metadata)
    : HeaderType(header), T(metadata) {}

  template <class... Args>
  constexpr FullMetadata(const HeaderType &header, Args &&...metadataArgs)
    : HeaderType(header), T(std::forward<Args>(metadataArgs)...) {}
};

/// Given a canonical metadata pointer, produce the adjusted metadata pointer.
template <class T>
static inline FullMetadata<T> *asFullMetadata(T *metadata) {
  return (FullMetadata<T>*) (((typename T::HeaderType*) metadata) - 1);
}
template <class T>
static inline const FullMetadata<T> *asFullMetadata(const T *metadata) {
  return asFullMetadata(const_cast<T*>(metadata));
}

// std::result_of is busted in Xcode 5. This is a simplified reimplementation
// that isn't SFINAE-safe.
namespace {
  template<typename T> struct _ResultOf;
  
  template<typename R, typename...A>
  struct _ResultOf<R(*)(A...)> {
    using type = R;
  };
}

using TypeContextDescriptor = TargetTypeContextDescriptor<InProcess>;

template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalTypeContextDescriptor = TargetTypeContextDescriptor<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

// FIXME: https://github.com/apple/swift/issues/43763
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winvalid-offsetof"

/// Bounds for metadata objects.
template <typename Runtime>
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<InProcess>;

/// The common structure of all type metadata.
template <typename Runtime>
struct TargetMetadata {
  using StoredPointer = typename Runtime::StoredPointer;

  /// The basic header type.
  typedef TargetTypeMetadataHeader<Runtime> HeaderType;

  constexpr TargetMetadata()
    : Kind(static_cast<StoredPointer>(MetadataKind::Class)) {}
  constexpr TargetMetadata(MetadataKind Kind)
    : Kind(static_cast<StoredPointer>(Kind)) {}

#if SWIFT_OBJC_INTEROP
protected:
  constexpr TargetMetadata(TargetAnyClassMetadataObjCInterop<Runtime> *isa)
    : Kind(reinterpret_cast<StoredPointer>(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<StoredPointer>(kind);
  }

protected:
  const TargetAnyClassMetadata<Runtime> *getClassISA() const {
    return reinterpret_cast<const TargetAnyClassMetadata<Runtime> *>(Kind);
  }
  void setClassISA(const TargetAnyClassMetadata<Runtime> *isa) {
    Kind = reinterpret_cast<StoredPointer>(isa);
  }

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<MetadataKind>(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 uint8_t *getLayoutString() const {
    assert(hasLayoutString());
    // Classes should not have layout strings
    assert(!isAnyClass());
    return asFullMetadata(this)->layoutString;
  }

  const TargetValueWitnessTable<Runtime> *getValueWitnesses() const {
    return asFullMetadata(this)->ValueWitnesses;
  }

  const TypeLayout *getTypeLayout() const {
    return getValueWitnesses()->getTypeLayout();
  }

  void setValueWitnesses(const ValueWitnessTable *table) {
    asFullMetadata(this)->ValueWitnesses = table;
  }

  void setLayoutString(const uint8_t *layoutString) {
    if (isAnyClass()) {
      asFullMetadata(reinterpret_cast<TargetAnyClassMetadata<Runtime> *>(this))
          ->layoutString = layoutString;
    } else {
      asFullMetadata(this)->layoutString = layoutString;
    }
  }

  bool hasLayoutString() const {
    if (auto *contextDescriptor = getTypeContextDescriptor()) {
      return contextDescriptor->hasLayoutString();
    }

    return false;
  }
  
  // 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<typename...A>                                                 \
    _ResultOf<ValueWitnessTypes::WITNESS ## Unsigned>::type                            \
    vw_##WITNESS(A &&...args) const {                                      \
      return getValueWitnesses()->WITNESS(std::forward<A>(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<OpaqueValue*>(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<Runtime, TargetTypeContextDescriptor>
  getTypeContextDescriptor() const {
    switch (getKind()) {
    case MetadataKind::Class: {
      const auto cls =
        static_cast<const TargetClassMetadataType<Runtime> *>(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<const TargetValueMetadata<Runtime> *>(this)
          ->Description;
    case MetadataKind::ForeignClass:
      return static_cast<const TargetForeignClassMetadata<Runtime> *>(this)
          ->Description;
    case MetadataKind::ForeignReferenceType:
      return static_cast<const TargetForeignReferenceTypeMetadata<Runtime> *>(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 TargetClassMetadataType<Runtime> *
  getClassObject() const;

  /// Retrieve the generic arguments of this type, if it has any.
  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> const *
  getGenericArgs() const {
    auto description = getTypeContextDescriptor();
    if (!description)
      return nullptr;

    auto generics = description->getGenericContext();
    if (!generics)
      return nullptr;

    auto asWords = reinterpret_cast<
      ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> const *>(this);
    return asWords + description->getGenericArgumentOffset();
  }

  bool satisfiesClassConstraint() const;

  const TypeContextDescriptor *getDescription() const;

  bool isStaticallySpecializedGenericMetadata() 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 R = Runtime>
  typename std::enable_if<std::is_same<R, InProcess>::value, Class>::type
  getObjCClassObject() const {
    return reinterpret_cast<Class>(
        const_cast<TargetClassMetadata<
            InProcess, TargetAnyClassMetadataObjCInterop<InProcess>> *>(
            getClassObject()));
  }
#endif

#ifndef NDEBUG
  [[deprecated("Only meant for use in the debugger")]] void dump() const;
#endif

protected:
  friend struct TargetOpaqueMetadata<Runtime>;
  
  /// 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 <typename Runtime>
struct TargetOpaqueMetadata {
  typedef TargetTypeMetadataHeaderBase<Runtime> HeaderType;

  // We have to represent this as a member so we can list-initialize it.
  TargetMetadata<Runtime> base;
};

/// The prefix on a heap metadata.
template <typename Runtime>
struct TargetHeapMetadataHeaderPrefix {
  /// Destroy the object, returning the allocated size of the object
  /// or 0 if the object shouldn't be deallocated.
  TargetSignedPointer<Runtime, HeapObjectDestroyer *
                                   __ptrauth_swift_heap_object_destructor>
      destroy;
};
using HeapMetadataHeaderPrefix =
  TargetHeapMetadataHeaderPrefix<InProcess>;

/// The header present on all heap metadata.
template <typename Runtime>
struct TargetHeapMetadataHeader
    : TargetTypeMetadataLayoutPrefix<Runtime>,
      TargetHeapMetadataHeaderPrefix<Runtime>,
      TargetTypeMetadataHeaderBase<Runtime> {
  constexpr TargetHeapMetadataHeader(
      const TargetTypeMetadataLayoutPrefix<Runtime> &typeLayoutPrefix,
      const TargetHeapMetadataHeaderPrefix<Runtime> &heapPrefix,
      const TargetTypeMetadataHeaderBase<Runtime> &typePrefix)
    : TargetTypeMetadataLayoutPrefix<Runtime>(typeLayoutPrefix),
      TargetHeapMetadataHeaderPrefix<Runtime>(heapPrefix),
      TargetTypeMetadataHeaderBase<Runtime>(typePrefix) {}
};
using HeapMetadataHeader =
  TargetHeapMetadataHeader<InProcess>;

/// 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 <typename Runtime>
struct TargetHeapMetadata : TargetMetadata<Runtime> {
  using HeaderType = TargetHeapMetadataHeader<Runtime>;

  TargetHeapMetadata() = default;
  constexpr TargetHeapMetadata(MetadataKind kind)
    : TargetMetadata<Runtime>(kind) {}
  constexpr TargetHeapMetadata(TargetAnyClassMetadataObjCInterop<Runtime> *isa)
    : TargetMetadata<Runtime>(isa) {}

  HeapObjectDestroyer *getHeapObjectDestroyer() const {
    return asFullMetadata(this)->destroy;
  }

  void setHeapObjectDestroyer(HeapObjectDestroyer *destroy) {
    asFullMetadata(this)->destroy = destroy;
  }
};
using HeapMetadata = TargetHeapMetadata<InProcess>;

/// 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 <typename Runtime>
struct TargetMethodDescriptor {
  /// Flags describing the method.
  MethodDescriptorFlags Flags;

  /// The method implementation.
  union {
    TargetCompactFunctionPointer<Runtime, void> Impl;
    TargetRelativeDirectPointer<Runtime, void> AsyncImpl;
    TargetRelativeDirectPointer<Runtime, void> CoroImpl;
  };

  // TODO: add method types or anything else needed for reflection.

  void *getImpl() const {
    if (Flags.isAsync()) {
      return AsyncImpl.get();
    } else if (Flags.isCalleeAllocatedCoroutine()) {
      return CoroImpl.get();
    } else {
      return Impl.get();
    }
  }
};

using MethodDescriptor = TargetMethodDescriptor<InProcess>;

/// 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 <typename Runtime>
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<Runtime> *description) const {
    if (description->hasResilientSuperclass()) {
      auto bounds = description->getMetadataBounds();
      return (bounds.ImmediateMembersOffset / sizeof(StoredPointer)
              + VTableOffset);
    }

    return VTableOffset;
  }
};

template<typename Runtime> struct TargetMethodDescriptor;

template<typename Runtime>
using TargetRelativeMethodDescriptorPointer =
  RelativeIndirectablePointer<const TargetMethodDescriptor<Runtime>,
                              /*nullable*/ true>;

using RelativeMethodDescriptorPointer =
  TargetRelativeMethodDescriptorPointer<InProcess>;

template<typename Runtime> struct TargetProtocolRequirement;

template<typename Runtime>
using TargetRelativeProtocolRequirementPointer =
  RelativeIndirectablePointer<const TargetProtocolRequirement<Runtime>,
                              /*nullable*/ true>;

using RelativeProtocolRequirementPointer =
  TargetRelativeProtocolRequirementPointer<InProcess>;

/// An entry in the default override table, consisting of one of our methods
/// `replacement` together with (1) another of our methods `original` which
/// might have been overridden by a subclass and (2) an implementation of
/// `replacement` to be used by such a subclass if it does not provide its own
/// implementation.
template <typename Runtime>
struct TargetMethodDefaultOverrideDescriptor {
  /// The method which replaced the original at call-sites.
  TargetRelativeMethodDescriptorPointer<Runtime> Replacement;

  /// The method originally called at such call sites.
  TargetRelativeMethodDescriptorPointer<Runtime> Original;

  union {
    TargetCompactFunctionPointer<Runtime, void, /*nullable*/ true> Impl;
    TargetRelativeDirectPointer<Runtime, void, /*nullable*/ true> AsyncImpl;
    TargetRelativeDirectPointer<Runtime, void, /*nullable*/ true> CoroImpl;
  };

  bool isData() const {
    auto *replacement = Replacement.get();
    assert(replacement && "no replacement");
    return replacement->Flags.isData();
  }

  void *getImpl() const {
    auto *replacement = Replacement.get();
    assert(replacement && "no replacement");
    if (replacement->Flags.isAsync()) {
      return AsyncImpl.get();
    } else if (replacement->Flags.isCalleeAllocatedCoroutine()) {
      return CoroImpl.get();
    } else {
      return Impl.get();
    }
  }
};

/// Header for a table of default override descriptors.  Such a table is a
/// variable-sized structure whose length is stored in this header which is
/// followed by that many TargetMethodDefaultOverrideDescriptors.
template <typename Runtime>
struct TargetMethodDefaultOverrideTableHeader {
  /// The number of TargetMethodDefaultOverrideDescriptor records following this
  /// header in the class's nominal type descriptor.
  uint32_t NumEntries;
};

/// An entry in the method override table, referencing a method from one of our
/// ancestor classes, together with an implementation.
template <typename Runtime>
struct TargetMethodOverrideDescriptor {
  /// The class containing the base method.
  TargetRelativeContextPointer<Runtime> Class;

  /// The base method.
  TargetRelativeMethodDescriptorPointer<Runtime> Method;

  /// The implementation of the override.
  union {
    TargetCompactFunctionPointer<Runtime, void, /*nullable*/ true> Impl;
    TargetRelativeDirectPointer<Runtime, void, /*nullable*/ true> AsyncImpl;
    TargetRelativeDirectPointer<Runtime, void, /*nullable*/ true> CoroImpl;
  };

  void *getImpl() const {
    auto *baseMethod = Method.get();
    assert(baseMethod && "no base method");
    if (baseMethod->Flags.isAsync()) {
      return AsyncImpl.get();
    } else if (baseMethod->Flags.isCalleeAllocatedCoroutine()) {
      return CoroImpl.get();
    } else {
      return Impl.get();
    }
  }
};

/// Header for a class vtable override descriptor. This is a variable-sized
/// structure that provides implementations for overrides of methods defined
/// in superclasses.
template <typename Runtime>
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 <typename Runtime>
struct TargetClassMetadataBounds : TargetMetadataBounds<Runtime> {
  using StoredPointer = typename Runtime::StoredPointer;
  using StoredSize = typename Runtime::StoredSize;
  using StoredPointerDifference = typename Runtime::StoredPointerDifference;

  using TargetMetadataBounds<Runtime>::NegativeSizeInWords;
  using TargetMetadataBounds<Runtime>::PositiveSizeInWords;
  using TargetClassMetadata = TargetClassMetadataType<Runtime>;

  /// 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<Runtime>{negativeSizeInWords, positiveSizeInWords},
      ImmediateMembersOffset(immediateMembersOffset) {}

  /// Return the basic bounds of all Swift class metadata.
  /// The immediate members offset will not be meaningful.
  static constexpr TargetClassMetadataBounds<Runtime> forSwiftRootClass() {
    using MetadataTy = FullMetadata<TargetClassMetadataType<Runtime>>;
    return forAddressPointAndSize(sizeof(typename MetadataTy::HeaderType),
                                  sizeof(MetadataTy));
  }

  /// 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<Runtime>
  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<InProcess>;

/// The portion of a class metadata object that is compatible with
/// all classes, even non-Swift ones.
template <typename Runtime>
struct TargetAnyClassMetadata : public TargetHeapMetadata<Runtime> {
  using StoredPointer = typename Runtime::StoredPointer;
  using StoredSize = typename Runtime::StoredSize;
  using TargetClassMetadata = TargetClassMetadataType<Runtime>;

protected:
  constexpr TargetAnyClassMetadata(
      TargetAnyClassMetadataObjCInterop<Runtime> *isa,
      TargetClassMetadata *superclass)
      : TargetHeapMetadata<Runtime>(isa), Superclass(superclass) {}
public:
  constexpr TargetAnyClassMetadata(TargetClassMetadata *superclass)
      : TargetHeapMetadata<Runtime>(MetadataKind::Class),
        Superclass(superclass) {}

  // Note that ObjC classes do not have a metadata header.

  /// The metadata for the superclass.  This is null for the root class.
  TargetSignedPointer<Runtime, const TargetClassMetadata *
                                   __ptrauth_swift_objc_superclass>
      Superclass;

  /// Is this object a valid swift type metadata?  That is, can it be
  /// safely downcast to ClassMetadata?
  bool isTypeMetadata() const {
    return true;
  }
  /// A different perspective on the same bit.
  bool isPureObjC() const {
    return !isTypeMetadata();
  }
};

/// This is the class metadata object for all classes (Swift and ObjC) in a
/// runtime that has Objective-C interoperability.
template <typename Runtime>
struct TargetAnyClassMetadataObjCInterop
    : public TargetAnyClassMetadata<Runtime> {
  using StoredPointer = typename Runtime::StoredPointer;
  using StoredSize = typename Runtime::StoredSize;
  using TargetClassMetadataObjCInterop =
    // swift:: qualifier works around an MSVC quirk
    swift::TargetClassMetadata<Runtime, TargetAnyClassMetadataObjCInterop<Runtime>>;

  constexpr TargetAnyClassMetadataObjCInterop(
      TargetAnyClassMetadataObjCInterop<Runtime> *isa,
      TargetClassMetadataObjCInterop *superclass)
      : TargetAnyClassMetadata<Runtime>(isa, superclass),
        CacheData{nullptr, nullptr},
        Data(SWIFT_CLASS_IS_SWIFT_MASK) {}

  constexpr TargetAnyClassMetadataObjCInterop(
      TargetClassMetadataObjCInterop *superclass)
      : TargetAnyClassMetadata<Runtime>(superclass), CacheData{nullptr,
                                                               nullptr},
        Data(SWIFT_CLASS_IS_SWIFT_MASK) {}

  // Allow setting the metadata kind to a class ISA on class metadata.
  using TargetMetadata<Runtime>::getClassISA;
  using TargetMetadata<Runtime>::setClassISA;

  /// 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<Runtime, void> 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(TargetAnyClassMetadataObjCInterop, 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 = TargetAnyClassMetadataType<InProcess>;

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.
///
/// If the Runtime supports Objective-C interoperability, this class inherits
/// from TargetAnyClassMetadataObjCInterop, otherwise it inherits from
/// TargetAnyClassMetadata.
template <typename Runtime, typename TargetAnyClassMetadataVariant>
struct TargetClassMetadata : public TargetAnyClassMetadataVariant {
  using StoredPointer = typename Runtime::StoredPointer;
  using StoredSize = typename Runtime::StoredSize;

  TargetClassMetadata() = default;
  constexpr TargetClassMetadata(const TargetAnyClassMetadataVariant &base,
                                ClassFlags flags,
                                ClassIVarDestroyer *ivarDestroyer,
                                StoredPointer size, StoredPointer addressPoint,
                                StoredPointer alignMask,
                                StoredPointer classSize,
                                StoredPointer classAddressPoint)
      : TargetAnyClassMetadataVariant(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<Runtime, const TargetClassDescriptor<Runtime> * __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<Runtime, ClassIVarDestroyer * __ptrauth_swift_heap_object_destructor> 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 TargetAnyClassMetadataVariant::isTypeMetadata;

  ConstTargetMetadataPointer<Runtime, TargetClassDescriptor>
  getDescription() const {
    assert(isTypeMetadata());
    return Description;
  }

  typename Runtime::StoredSignedPointer
  getDescriptionAsSignedPointer() const {
    assert(isTypeMetadata());
    return Description;
  }

  void setDescription(const TargetClassDescriptor<Runtime> *description) {
    Description = description;
  }

  // [NOTE: Dynamic-subclass-KVO]
  //
  // Using Objective-C runtime, KVO can modify object behavior without needing
  // to modify the object's code. This is done by dynamically creating an
  // artificial subclass of the object's type.
  //
  // The isa pointer of the observed object is swapped out to point to
  // the artificial subclass, which has the following properties:
  // - Setters for observed keys are overridden to additionally post
  // notifications.
  // - The `-class` method is overridden to return the original class type
  // instead of the artificial subclass type.
  //
  // For more details, see:
  // https://www.mikeash.com/pyblog/friday-qa-2009-01-23.html

  /// Is this class an artificial subclass, such as one dynamically
  /// created for various dynamic purposes like KVO?
  /// See [NOTE: Dynamic-subclass-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<const void * const*>(this);
    return reinterpret_cast<const StoredPointer *>(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<Runtime>
  getClassBoundsAsSwiftSuperclass() const {
    using Bounds = TargetClassMetadataBounds<Runtime>;

    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;
  }

#if SWIFT_OBJC_INTEROP
  /// 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());
  }
#endif

  bool isStaticallySpecializedGenericMetadata() const {
    auto *description = getDescription();
    if (!description->isGeneric())
      return false;

    return this->Flags & ClassFlags::IsStaticSpecialization;
  }

  bool isCanonicalStaticallySpecializedGenericMetadata() const {
    auto *description = getDescription();
    if (!description->isGeneric())
      return false;

    return this->Flags & ClassFlags::IsCanonicalStaticSpecialization;
  }

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::Class;
  }
};
using ClassMetadata = TargetClassMetadataType<InProcess>;

/// The structure of class metadata that's compatible with dispatch objects.
/// This includes Swift heap metadata, followed by the vtable entries that
/// dispatch expects to see, with padding to place them at the expected offsets.
template <typename Runtime>
struct TargetDispatchClassMetadata : public TargetHeapMetadata<Runtime> {
  using InvokeCall = void (*)(void *, void *, uint32_t);

  TargetDispatchClassMetadata(MetadataKind Kind, unsigned long VTableType,
                              InvokeCall Invoke)
      : TargetHeapMetadata<Runtime>(Kind), VTableType(VTableType),
        VTableInvoke(Invoke) {}

  TargetPointer<Runtime, void> Opaque;
#if SWIFT_OBJC_INTEROP
  TargetPointer<Runtime, void> OpaqueObjC[3];
#endif

  unsigned long VTableType;
  TargetSignedPointer<Runtime, InvokeCall __ptrauth_swift_dispatch_invoke_function> VTableInvoke;
};
using DispatchClassMetadata = TargetDispatchClassMetadata<InProcess>;

/// The structure of metadata for heap-allocated local variables.
/// This is non-type metadata.
template <typename Runtime>
struct TargetHeapLocalVariableMetadata
  : public TargetHeapMetadata<Runtime> {
  using StoredPointer = typename Runtime::StoredPointer;
  uint32_t OffsetToFirstCapture;
  TargetPointer<Runtime, const char> CaptureDescription;

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::HeapLocalVariable;
  }
  constexpr TargetHeapLocalVariableMetadata()
      : TargetHeapMetadata<Runtime>(MetadataKind::HeapLocalVariable),
        OffsetToFirstCapture(0), CaptureDescription(nullptr) {}
};
using HeapLocalVariableMetadata
  = TargetHeapLocalVariableMetadata<InProcess>;

/// 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 <typename Runtime>
struct TargetObjCClassWrapperMetadata : public TargetMetadata<Runtime> {
  ConstTargetMetadataPointer<Runtime, TargetClassMetadataObjCInterop> Class;

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::ObjCClassWrapper;
  }
};
using ObjCClassWrapperMetadata
  = TargetObjCClassWrapperMetadata<InProcess>;

/// 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 <typename Runtime>
struct TargetForeignTypeMetadata : public TargetMetadata<Runtime> {
};
using ForeignTypeMetadata = TargetForeignTypeMetadata<InProcess>;

/// 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 <typename Runtime>
struct TargetForeignClassMetadata : public TargetForeignTypeMetadata<Runtime> {
  using StoredPointer = typename Runtime::StoredPointer;

  /// An out-of-line description of the type.
  TargetSignedPointer<Runtime, const TargetClassDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;

  /// The superclass of the foreign class, if any.
  ConstTargetMetadataPointer<Runtime, swift::TargetForeignClassMetadata>
    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<Runtime, TargetClassDescriptor>
  getDescription() const {
    return Description;
  }

  typename Runtime::StoredSignedPointer
  getDescriptionAsSignedPointer() const {
    return Description;
  }

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::ForeignClass;
  }
};
using ForeignClassMetadata = TargetForeignClassMetadata<InProcess>;

/// The structure of metadata objects for foreign reference types.
/// A foreign reference type is a non-Swift, non-Objective-C foreign type with
/// reference semantics. Foreign reference types are pointers/reference to
/// value types marked with the `swift_attr("import_reference")` attribute.
///
/// Foreign reference types may have *custom* reference counting operations, or
/// they may be immortal (and therefore trivial).
///
/// We assume for now that foreign reference types are entirely opaque
/// to Swift introspection.
template <typename Runtime>
struct TargetForeignReferenceTypeMetadata : public TargetForeignTypeMetadata<Runtime> {
  using StoredPointer = typename Runtime::StoredPointer;

  /// An out-of-line description of the type.
  TargetSignedPointer<Runtime, const TargetClassDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;

  /// 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<Runtime, TargetClassDescriptor>
  getDescription() const {
    return Description;
  }

  typename Runtime::StoredSignedPointer
  getDescriptionAsSignedPointer() const {
    return Description;
  }

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::ForeignReferenceType;
  }
};
using ForeignReferenceTypeMetadata = TargetForeignReferenceTypeMetadata<InProcess>;

/// The common structure of metadata for structs and enums.
template <typename Runtime>
struct TargetValueMetadata : public TargetMetadata<Runtime> {
  using StoredPointer = typename Runtime::StoredPointer;
  TargetValueMetadata(MetadataKind Kind,
                      const TargetTypeContextDescriptor<Runtime> *description)
      : TargetMetadata<Runtime>(Kind), Description(description) {}

  /// An out-of-line description of the type.
  TargetSignedPointer<Runtime, const TargetValueTypeDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::Struct
      || metadata->getKind() == MetadataKind::Enum
      || metadata->getKind() == MetadataKind::Optional;
  }

  ConstTargetMetadataPointer<Runtime, TargetValueTypeDescriptor>
  getDescription() const {
    return Description;
  }

  typename Runtime::StoredSignedPointer
  getDescriptionAsSignedPointer() const {
    return Description;
  }
};
using ValueMetadata = TargetValueMetadata<InProcess>;

/// The structure of type metadata for structs.
template <typename Runtime>
struct TargetStructMetadata : public TargetValueMetadata<Runtime> {
  using StoredPointer = typename Runtime::StoredPointer;
  using TargetValueMetadata<Runtime>::TargetValueMetadata;

  const TargetStructDescriptor<Runtime> *getDescription() const {
    return llvm::cast<TargetStructDescriptor<Runtime>>(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<const void * const*>(this);
    return reinterpret_cast<const uint32_t *>(asWords + offset);
  }

  bool isStaticallySpecializedGenericMetadata() const {
    auto *description = getDescription();
    if (!description->isGeneric())
      return false;

    auto *trailingFlags = getTrailingFlags();
    if (trailingFlags == nullptr)
      return false;

    return trailingFlags->isStaticSpecialization();
  }

  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<const void *const *>(this);
    return reinterpret_cast<const MetadataTrailingFlags *>(asWords + offset);
  }

  static constexpr int32_t getGenericArgumentOffset() {
    return sizeof(TargetStructMetadata<Runtime>) / sizeof(StoredPointer);
  }

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::Struct;
  }
};
using StructMetadata = TargetStructMetadata<InProcess>;

/// The structure of type metadata for enums.
template <typename Runtime>
struct TargetEnumMetadata : public TargetValueMetadata<Runtime> {
  using StoredPointer = typename Runtime::StoredPointer;
  using StoredSize = typename Runtime::StoredSize;
  using TargetValueMetadata<Runtime>::TargetValueMetadata;

  const TargetEnumDescriptor<Runtime> *getDescription() const {
    return llvm::cast<TargetEnumDescriptor<Runtime>>(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<const StoredSize *>(this);
    asWords += offset;
    return *asWords;
  }

  StoredSize &getPayloadSize() {
    assert(hasPayloadSize());
    auto offset = getDescription()->getPayloadSizeOffset();
    StoredSize *asWords = reinterpret_cast<StoredSize *>(this);
    asWords += offset;
    return *asWords;
  }

  bool isStaticallySpecializedGenericMetadata() const {
    auto *description = getDescription();
    if (!description->isGeneric())
      return false;

    auto *trailingFlags = getTrailingFlags();
    if (trailingFlags == nullptr)
      return false;

    return trailingFlags->isStaticSpecialization();
  }

  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<const void *const *>(this);
    return reinterpret_cast<const MetadataTrailingFlags *>(asWords + offset);
  }

  static constexpr int32_t getGenericArgumentOffset() {
    return sizeof(TargetEnumMetadata<Runtime>) / sizeof(StoredPointer);
  }

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::Enum
      || metadata->getKind() == MetadataKind::Optional;
  }
};
using EnumMetadata = TargetEnumMetadata<InProcess>;

template <typename Runtime>
struct TargetFunctionGlobalActorMetadata {
  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> GlobalActorType;
};
using FunctionGlobalActorMetadata = TargetFunctionGlobalActorMetadata<InProcess>;

template <typename Runtime>
struct TargetFunctionThrownErrorMetadata {
  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> ThrownErrorType;
};
using FunctionThrownErrorMetadata = TargetFunctionThrownErrorMetadata<InProcess>;

/// The structure of function type metadata.
template <typename Runtime>
struct TargetFunctionTypeMetadata : public TargetMetadata<Runtime>,
  swift::ABI::TrailingObjects<
    TargetFunctionTypeMetadata<Runtime>,
    ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>,
    ParameterFlags,
    TargetFunctionMetadataDifferentiabilityKind<typename Runtime::StoredSize>,
    TargetFunctionGlobalActorMetadata<Runtime>,
    ExtendedFunctionTypeFlags,
    TargetFunctionThrownErrorMetadata<Runtime>> {
  using StoredSize = typename Runtime::StoredSize;
  using Parameter = ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>;

private:
  using TrailingObjects =
      swift::ABI::TrailingObjects<
        TargetFunctionTypeMetadata<Runtime>,
        Parameter,
        ParameterFlags,
        TargetFunctionMetadataDifferentiabilityKind<StoredSize>,
        TargetFunctionGlobalActorMetadata<Runtime>,
        ExtendedFunctionTypeFlags,
        TargetFunctionThrownErrorMetadata<Runtime>>;
  friend TrailingObjects;

  template<typename T>
  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;

public:
  TargetFunctionTypeFlags<StoredSize> Flags;

  /// The type metadata for the result type.
  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> ResultType;

private:
  size_t numTrailingObjects(OverloadToken<Parameter>) const {
    return getNumParameters();
  }

  size_t numTrailingObjects(OverloadToken<ParameterFlags>) const {
    return hasParameterFlags() ? getNumParameters() : 0;
  }

  size_t numTrailingObjects(
      OverloadToken<TargetFunctionMetadataDifferentiabilityKind<StoredSize>>
  ) const {
    return isDifferentiable() ? 1 : 0;
  }

  size_t numTrailingObjects(
      OverloadToken<TargetFunctionGlobalActorMetadata<Runtime>>
  ) const {
    return hasGlobalActor() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<ExtendedFunctionTypeFlags>) const {
    return hasExtendedFlags() ? 1 : 0;
  }

  size_t numTrailingObjects(
      OverloadToken<TargetFunctionThrownErrorMetadata<Runtime>>
  ) const {
    return hasThrownError() ? 1 : 0;
  }
      
public:
  Parameter *getParameters() { 
    return this->template getTrailingObjects<Parameter>();
  }

  const Parameter *getParameters() const {
    return this->template getTrailingObjects<Parameter>();
  }

  Parameter getParameter(unsigned index) const {
    assert(index < getNumParameters());
    return getParameters()[index];
  }

  ParameterFlags getParameterFlags(unsigned index) const {
    assert(index < getNumParameters());
    return hasParameterFlags() ? getParameterFlags()[index] : ParameterFlags();
  }

  StoredSize getNumParameters() const {
    return Flags.getNumParameters();
  }
  FunctionMetadataConvention getConvention() const {
    return Flags.getConvention();
  }
  bool isAsync() const { return Flags.isAsync(); }
  bool isThrowing() const { return Flags.isThrowing(); }
  bool isSendable() const { return Flags.isSendable(); }
  bool isDifferentiable() const { return Flags.isDifferentiable(); }
  bool hasParameterFlags() const { return Flags.hasParameterFlags(); }
  bool isEscaping() const { return Flags.isEscaping(); }
  bool hasGlobalActor() const { return Flags.hasGlobalActor(); }
  bool hasExtendedFlags() const { return Flags.hasExtendedFlags(); }
  bool hasThrownError() const {
    if (!Flags.hasExtendedFlags())
      return false;

    return getExtendedFlags().isTypedThrows();
  }

  static constexpr StoredSize OffsetToFlags = sizeof(TargetMetadata<Runtime>);

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::Function;
  }

  ParameterFlags *getParameterFlags() {
    return this->template getTrailingObjects<ParameterFlags>();
  }

  const ParameterFlags *getParameterFlags() const {
    return this->template getTrailingObjects<ParameterFlags>();
  }

  TargetFunctionMetadataDifferentiabilityKind<StoredSize> *
  getDifferentiabilityKindAddress() {
    assert(isDifferentiable());
    return this->template getTrailingObjects<TargetFunctionMetadataDifferentiabilityKind<StoredSize>>();
  }

  TargetFunctionMetadataDifferentiabilityKind<StoredSize>
  getDifferentiabilityKind() const {
    if (isDifferentiable()) {
      return *(this->template getTrailingObjects<TargetFunctionMetadataDifferentiabilityKind<StoredSize>>());
    }
    return TargetFunctionMetadataDifferentiabilityKind<StoredSize>
        ::NonDifferentiable;
  }

  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> *
  getGlobalActorAddr() {
    assert(hasGlobalActor());
    auto globalActorAddr =
      this->template getTrailingObjects<TargetFunctionGlobalActorMetadata<Runtime>>();
    return &globalActorAddr->GlobalActorType;
  }

  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>
  getGlobalActor() const {
    if (!hasGlobalActor())
      return ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>();
    auto globalActorAddr =
      this->template getTrailingObjects<TargetFunctionGlobalActorMetadata<Runtime>>();
    return globalActorAddr->GlobalActorType;
  }

  ExtendedFunctionTypeFlags *getExtendedFlagsAddr() {
    assert(hasExtendedFlags());
    return this->template getTrailingObjects<ExtendedFunctionTypeFlags>();
  }
      
  ExtendedFunctionTypeFlags getExtendedFlags() const {
    if (!hasExtendedFlags())
      return ExtendedFunctionTypeFlags();

    return this->template getTrailingObjects<ExtendedFunctionTypeFlags>()[0];
  }

  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> *
  getThrownErrorAddr() {
    assert(hasThrownError());
    auto thrownErrorAddr =
      this->template getTrailingObjects<TargetFunctionThrownErrorMetadata<Runtime>>();
    return &thrownErrorAddr->ThrownErrorType;
  }

  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>
  getThrownError() const {
    if (!hasThrownError())
      return ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>();
    auto thrownErrorAddr =
      this->template getTrailingObjects<TargetFunctionThrownErrorMetadata<Runtime>>();
    return thrownErrorAddr->ThrownErrorType;
  }
};
using FunctionTypeMetadata = TargetFunctionTypeMetadata<InProcess>;

/// The structure of metadata for metatypes.
template <typename Runtime>
struct TargetMetatypeMetadata : public TargetMetadata<Runtime> {
  /// The type metadata for the element.
  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> InstanceType;

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::Metatype;
  }
};
using MetatypeMetadata = TargetMetatypeMetadata<InProcess>;

/// The structure of `Builtin.FixedArray` type metadata.
template <typename Runtime>
struct TargetFixedArrayTypeMetadata : public TargetMetadata<Runtime> {
  using StoredPointerDifference = typename Runtime::StoredPointerDifference;
  
  StoredPointerDifference Count;
  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> Element;
  
  // Returns the number of elements for which storage is reserved.
  // A type that is instantiated with negative size cannot have values
  // instantiated, so is laid out with zero size like an uninhabited type.
  StoredPointerDifference getRealizedCount() const {
    return Count < 0 ? 0 : Count;
  }

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::FixedArray;
  }
};
using FixedArrayTypeMetadata = TargetFixedArrayTypeMetadata<InProcess>;

/// The structure of tuple type metadata.
template <typename Runtime>
struct TargetTupleTypeMetadata : public TargetMetadata<Runtime> {
  using StoredSize = typename Runtime::StoredSize;
  using HeaderType = TargetTypeMetadataHeaderBase<Runtime>;
  TargetTupleTypeMetadata() = default;
  constexpr TargetTupleTypeMetadata(const TargetMetadata<Runtime> &base,
                                    uint32_t numElements,
                                    TargetPointer<Runtime, const char> labels)
    : TargetMetadata<Runtime>(base),
      NumElements(numElements),
      Labels(labels) {}

  /// The number of elements.
  StoredSize NumElements;

  /// The labels string;  see swift_getTupleTypeMetadata.
  TargetPointer<Runtime, const char> Labels;

  struct Element {
    /// The type of the element.
    ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> 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<Element*>(this + 1);
  }

  const Element *getElements() const {
    return reinterpret_cast<const Element*>(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<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::Tuple;
  }
};
using TupleTypeMetadata = TargetTupleTypeMetadata<InProcess>;
  
template <typename Runtime>
constexpr inline auto
TargetTupleTypeMetadata<Runtime>::getOffsetToNumElements() -> StoredSize {
  return offsetof(TargetTupleTypeMetadata<Runtime>, NumElements);
}

template <typename Runtime>
struct swift_ptrauth_struct_context_descriptor(ProtocolDescriptor)
    TargetProtocolDescriptor;

/// 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 <typename Runtime>
struct TargetProtocolRequirement {
  ProtocolRequirementFlags Flags;
  // TODO: name, type

  /// The optional default implementation of the protocol.
  union {
    TargetCompactFunctionPointer<Runtime, void, /*nullable*/ true> DefaultFuncImplementation;
    TargetRelativeDirectPointer<Runtime, void, /*nullable*/ true> DefaultImplementation;
  };

  void *getDefaultImplementation() const {
    if (Flags.isFunctionImpl()) {
      return DefaultFuncImplementation.get();
    } else {
      return DefaultImplementation.get();
    }
  }
};

using ProtocolRequirement = TargetProtocolRequirement<InProcess>;

template <typename Runtime>
struct swift_ptrauth_struct_context_descriptor(ProtocolDescriptor)
    TargetProtocolDescriptor;
using ProtocolDescriptor = TargetProtocolDescriptor<InProcess>;

template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalProtocolDescriptor = TargetProtocolDescriptor<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

/// 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 <typename Runtime>
class TargetWitnessTable {
  /// The protocol conformance descriptor from which this witness table
  /// was generated.
  ConstTargetMetadataPointer<Runtime, TargetProtocolConformanceDescriptor>
    Description;

public:
  const TargetProtocolConformanceDescriptor<Runtime> *getDescription() const {
    return Description;
  }
};

using WitnessTable = TargetWitnessTable<InProcess>;

template <typename Runtime>
using TargetWitnessTablePointer =
  ConstTargetMetadataPointer<Runtime, TargetWitnessTable>;

using WitnessTablePointer = TargetWitnessTablePointer<InProcess>;

using AssociatedWitnessTableAccessFunction =
  SWIFT_CC(swift) WitnessTable *(const Metadata *associatedType,
                                 const Metadata *self,
                                 const WitnessTable *selfConformance);

template<typename Runtime>
using TargetRelativeProtocolConformanceDescriptorPointer =
  RelativeIndirectablePointer<const TargetProtocolConformanceDescriptor<Runtime>,
                              /*nullable*/ false>;

/// A relative 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.
/// Entries are relative pointers.
template <typename Runtime>
class TargetRelativeWitnessTable {
  /// The protocol conformance descriptor from which this witness table
  /// was generated.
  TargetRelativeProtocolConformanceDescriptorPointer<Runtime> Description;

public:
  const TargetProtocolConformanceDescriptor<Runtime> *getDescription() const {
    return Description;
  }
};
using RelativeWitnessTable = TargetRelativeWitnessTable<InProcess>;

using AssociatedRelativeWitnessTableAccessFunction =
  SWIFT_CC(swift) RelativeWitnessTable *(const Metadata *associatedType,
                                 const Metadata *self,
                                 const RelativeWitnessTable *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 type metadata for simple existential types which
/// don't require an extended existential descriptor:
///
/// - They are existential over a single type T.
/// - Their head type is that type T.
/// - Their existential constraints are a composition of protocol
///   requirements, superclass constraints, and possibly a class
///   layout constraint on T.
template <typename Runtime>
struct TargetExistentialTypeMetadata
  : TargetMetadata<Runtime>,
    swift::ABI::TrailingObjects<
      TargetExistentialTypeMetadata<Runtime>,
      ConstTargetMetadataPointer<Runtime, TargetMetadata>,
      TargetProtocolDescriptorRef<Runtime>> {
  using HeaderType = TargetTypeMetadataHeaderBase<Runtime>;

private:
  using ProtocolDescriptorRef = TargetProtocolDescriptorRef<Runtime>;
  using MetadataPointer =
      ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>;
  using TrailingObjects =
          swift::ABI::TrailingObjects<
          TargetExistentialTypeMetadata<Runtime>,
          MetadataPointer,
          ProtocolDescriptorRef>;
  friend TrailingObjects;

  template<typename T>
  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;

  size_t numTrailingObjects(OverloadToken<ProtocolDescriptorRef>) const {
    return NumProtocols;
  }

  size_t numTrailingObjects(OverloadToken<MetadataPointer>) 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<Runtime>(MetadataKind::Existential),
      Flags(ExistentialTypeFlags()), NumProtocols(0) {}
  
  explicit constexpr TargetExistentialTypeMetadata(ExistentialTypeFlags Flags)
    : TargetMetadata<Runtime>(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<OpaqueValue *>(projectValue((const OpaqueValue*)container));
  }

  /// Get the dynamic type from an existential container of the type described
  /// by this metadata.
  const TargetMetadata<Runtime> *
  getDynamicType(const OpaqueValue *container) const;
  
  /// Get a witness table from an existential container of the type described
  /// by this metadata.
  const TargetWitnessTable<Runtime> * 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.
  llvm::ArrayRef<ProtocolDescriptorRef> getProtocols() const {
    return { this->template getTrailingObjects<ProtocolDescriptorRef>(),
             NumProtocols };
  }

  MetadataPointer getSuperclassConstraint() const {
    if (!Flags.hasSuperclassConstraint())
      return MetadataPointer();

    return this->template getTrailingObjects<MetadataPointer>()[0];
  }

  /// Retrieve the set of protocols required by the existential.
  llvm::MutableArrayRef<ProtocolDescriptorRef> getMutableProtocols() {
    return { this->template getTrailingObjects<ProtocolDescriptorRef>(),
             NumProtocols };
  }

  /// Set the superclass.
  void setSuperclassConstraint(MetadataPointer superclass) {
    assert(Flags.hasSuperclassConstraint());
    assert(superclass != nullptr);
    this->template getTrailingObjects<MetadataPointer>()[0] = superclass;
  }

  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::Existential;
  }
};
using ExistentialTypeMetadata
  = TargetExistentialTypeMetadata<InProcess>;

template<typename Runtime>
struct TargetExistentialTypeExpression {
  /// The type expression.
  TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> name;
};

/// A description of the shape of an existential type.
///
/// An existential type has the general form:
///   \exists <signature> . <type>
///
/// The signature is called the requirement signature.  In the most
/// common case (the only one Swift currently supports), it has exactly
/// one type parameter.  The types and conformances required by this
/// signature must be stored in the existential container at runtime.
///
/// The type is called the type (sub)expression, and it is expressed
/// in terms of the type parameters introduced by the requirement
/// signature.  It is required to name each of the type parameters in
/// an identity position (outside of the base type of a member type
/// expression).  In the most common case, it is the unique type
/// parameter type.  Swift currently only supports existential
/// subexpressions that are either the (unique) type parameter or
/// a metatype thereof (possibly multiply-derived).
///
/// In order to efficiently support generic substitution of the
/// constraints of existential types, extended existential type
/// descriptors represent a generalizable form of the existential:
///   \forall <gen sig> . \exists <req sig> . <type>
///
/// The new signature is called the generalization signature of the
/// shape.  All concrete references to types within the requirement
/// signature and head type which are not expressed in terms of
/// the requirement signature are replaced with type parameters freshly
/// added to the generalization signature.  Any given existential type
/// is then a specialization of this generalization.
///
/// For example, the existential type
///   \exists <T: Collection where T.Element == Int> . T
/// is generalized as
///   \forall <U> . \exists <T: Collection where T.Element == U> . T
/// and is the application of this generalization at <Int>.
///
/// The soundness condition on this is that the generalization
/// signatures, requirement signatures, and head types must be
/// identical for any two existential types for which a generic
/// substitution can carry one to the other.
///
/// Only particularly complex existential types are represented with
/// an explicit existential shape.  Types which are a simple composition
/// of layout, superclass, and unconstrained protocol constraints on
/// an opaque or (metatype-of)+-opaque are represented with
/// ExistentialTypeMetadata or ExistentialMetatypeMetadata.
/// Types which *can* be represented with those classes *must*
/// be represented with them.
template <typename Runtime>
struct TargetExtendedExistentialTypeShape
  : swift::ABI::TrailingObjects<
      TargetExtendedExistentialTypeShape<Runtime>,
      // Optional generalization signature header
      TargetGenericContextDescriptorHeader<Runtime>,
      // Optional type subexpression
      TargetExistentialTypeExpression<Runtime>,
      // Optional suggested value witnesses
      TargetRelativeIndirectablePointer<Runtime, const TargetValueWitnessTable<Runtime>,
                                        /*nullable*/ false>,
      // Parameters for requirement signature, followed by parameters
      // for generalization signature
      GenericParamDescriptor,
      // Requirements for requirement signature, followed by requirements
      // for generalization signature
      TargetGenericRequirementDescriptor<Runtime>,
      // Optional header describing any type packs in the generalization
      // signature.
      GenericPackShapeHeader,
      // For each type pack in the generalization signature, a descriptor
      // storing the shape class.
      GenericPackShapeDescriptor> {
private:
  using RelativeValueWitnessTablePointer =
    TargetRelativeIndirectablePointer<Runtime,
                                      const TargetValueWitnessTable<Runtime>,
                                      /*nullable*/ false>;
  using TrailingObjects =
    swift::ABI::TrailingObjects<
      TargetExtendedExistentialTypeShape<Runtime>,
      TargetGenericContextDescriptorHeader<Runtime>,
      TargetExistentialTypeExpression<Runtime>,
      RelativeValueWitnessTablePointer,
      GenericParamDescriptor,
      TargetGenericRequirementDescriptor<Runtime>,
      GenericPackShapeHeader,
      GenericPackShapeDescriptor>;
  friend TrailingObjects;

  template<typename T>
  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;

  size_t numTrailingObjects(OverloadToken<TargetGenericContextDescriptorHeader<Runtime>>) const {
    return Flags.hasGeneralizationSignature();
  }

  size_t numTrailingObjects(OverloadToken<TargetExistentialTypeExpression<Runtime>>) const {
    return Flags.hasTypeExpression();
  }

  size_t numTrailingObjects(OverloadToken<RelativeValueWitnessTablePointer>) const {
    return Flags.hasSuggestedValueWitnesses();
  }

  size_t numTrailingObjects(OverloadToken<GenericParamDescriptor>) const {
    return (Flags.hasImplicitReqSigParams() ? 0 : getNumReqSigParams())
         + (Flags.hasImplicitGenSigParams() ? 0 : getNumGenSigParams());
  }

  size_t numTrailingObjects(OverloadToken<TargetGenericRequirementDescriptor<Runtime>>) const {
    return getNumGenSigRequirements() + getNumReqSigRequirements();
  }

  size_t numTrailingObjects(OverloadToken<GenericPackShapeHeader>) const {
    return (Flags.hasTypePacks() ? 1 : 0);
  }

  size_t numTrailingObjects(OverloadToken<GenericPackShapeDescriptor>) const {
    if (!Flags.hasTypePacks())
      return 0;

    return getGenSigPackShapeHeader().NumTypePacks;
  }

  const TargetGenericContextDescriptorHeader<Runtime> *
  getGenSigHeader() const {
    assert(hasGeneralizationSignature());
    return this->template getTrailingObjects<
                   TargetGenericContextDescriptorHeader<Runtime>>();
  }

public:
  using SpecialKind = ExtendedExistentialTypeShapeFlags::SpecialKind;

  /// Flags for the existential shape.
  ExtendedExistentialTypeShapeFlags Flags;

  /// The mangling of the generalized existential type, expressed
  /// (if necessary) in terms of the type parameters of the
  /// generalization signature.
  ///
  /// If this shape is non-unique, this is always a flat string, not a
  /// "symbolic" mangling which can contain relative references.  This
  /// allows uniquing to simply compare the string content.
  ///
  /// In principle, the content of the requirement signature and type
  /// expression are derivable from this type.  We store them separately
  /// so that code which only needs to work with the logical content of
  /// the type doesn't have to break down the existential type string.
  /// This both (1) allows those operations to work substantially more
  /// efficiently (and without needing code to produce a requirement
  /// signature from an existential type to exist in the runtime) and
  /// (2) potentially allows old runtimes to support new existential
  /// types without as much invasive code.
  ///
  /// The content of this string is *not* necessarily derivable from
  /// the requirement signature.  This is because there may be multiple
  /// existential types that have equivalent logical content but which
  /// we nonetheless distinguish at compile time.  Storing this also
  /// allows us to far more easily produce a formal type from this
  /// shape reflectively.
  TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false>
      ExistentialType;

  /// The header describing the requirement signature of the existential.
  TargetGenericContextDescriptorHeader<Runtime> ReqSigHeader;

  RuntimeGenericSignature<Runtime> getRequirementSignature() const {
    return {ReqSigHeader, getReqSigParams(), getReqSigRequirements(),
            {0, 0}, nullptr, {0}, nullptr};
  }

  unsigned getNumReqSigParams() const {
    return ReqSigHeader.NumParams;
  }

  const GenericParamDescriptor *getReqSigParams() const {
    return Flags.hasImplicitReqSigParams()
               ? swift::targetImplicitGenericParamDescriptors<Runtime>()
               : this->template getTrailingObjects<GenericParamDescriptor>();
  }

  unsigned getNumReqSigRequirements() const {
    return ReqSigHeader.NumRequirements;
  }

  const TargetGenericRequirementDescriptor<Runtime> *
  getReqSigRequirements() const {
    return this->template getTrailingObjects<
                              TargetGenericRequirementDescriptor<Runtime>>();
  }

  /// The type expression of the existential, as a symbolic mangled type
  /// string.  Must be null if the header is just the (single)
  /// requirement type parameter.
  const TargetExistentialTypeExpression<Runtime> *getTypeExpression() const {
    return Flags.hasTypeExpression()
               ? this->template getTrailingObjects<
                     TargetExistentialTypeExpression<Runtime>>()
               : nullptr;
  }

  bool isTypeExpressionOpaque() const {
    return !Flags.hasTypeExpression();
  }

  /// The suggested value witness table for the existential.
  /// Required if:
  /// - the special kind is SpecialKind::ExplicitLayout
  /// - the special kind is SpecialKind::None and the type head
  ///   isn't opaque
  TargetPointer<Runtime, const TargetValueWitnessTable<Runtime>>
  getSuggestedValueWitnesses() const {
    return Flags.hasSuggestedValueWitnesses()
             ? this->template getTrailingObjects<
                 RelativeValueWitnessTablePointer>()->get()
             : nullptr;
  }

  /// Return the amount of space used in the existential container
  /// for storing the existential arguments (including both the
  /// type metadata and the conformances).
  unsigned getContainerSignatureLayoutSizeInWords() const {
    unsigned rawSize = ReqSigHeader.getArgumentLayoutSizeInWords();
    switch (Flags.getSpecialKind()) {
    // The default and explicitly-sized-value-layout cases don't optimize
    // the storage of the signature.
    case SpecialKind::None:
    case SpecialKind::ExplicitLayout:
      return rawSize;

    // The class and metadata cases don't store type metadata.
    case SpecialKind::Class:
    case SpecialKind::Metatype:
      // Requirement signatures won't have non-key parameters.
      return rawSize - ReqSigHeader.NumParams;
    }

    // Assume any future cases don't optimize metadata storage.
    return rawSize;
  }

  bool hasGeneralizationSignature() const {
    return Flags.hasGeneralizationSignature();
  }

  RuntimeGenericSignature<Runtime> getGeneralizationSignature() const {
    if (!hasGeneralizationSignature()) return RuntimeGenericSignature<Runtime>();
    return {*getGenSigHeader(), getGenSigParams(), getGenSigRequirements(),
            getGenSigPackShapeHeader(), getGenSigPackShapeDescriptors(),
            {0}, nullptr};
  }

  unsigned getNumGenSigParams() const {
    return hasGeneralizationSignature()
             ? getGenSigHeader()->NumParams : 0;
  }

  const GenericParamDescriptor *getGenSigParams() const {
    assert(hasGeneralizationSignature());
    if (Flags.hasImplicitGenSigParams())
      return swift::targetImplicitGenericParamDescriptors<Runtime>();
    auto base = this->template getTrailingObjects<GenericParamDescriptor>();
    if (!Flags.hasImplicitReqSigParams())
      base += getNumReqSigParams();
    return base;
  }

  unsigned getNumGenSigRequirements() const {
    return hasGeneralizationSignature()
             ? getGenSigHeader()->NumRequirements : 0;
  }

  const TargetGenericRequirementDescriptor<Runtime> *
  getGenSigRequirements() const {
    assert(hasGeneralizationSignature());
    return getReqSigRequirements() + ReqSigHeader.NumRequirements;
  }

  GenericPackShapeHeader getGenSigPackShapeHeader() const {
    assert(hasGeneralizationSignature());
    if (!Flags.hasTypePacks())
      return {0, 0};
    return *this->template getTrailingObjects<GenericPackShapeHeader>();
  }

  const GenericPackShapeDescriptor *getGenSigPackShapeDescriptors() const {
    assert(hasGeneralizationSignature());
    if (!Flags.hasTypePacks())
      return nullptr;
    return this->template getTrailingObjects<GenericPackShapeDescriptor>();
  }

  /// Return the amount of space used in ExtendedExistentialTypeMetadata
  /// for this shape to store the generalization arguments.
  unsigned getGenSigArgumentLayoutSizeInWords() const {
    if (!hasGeneralizationSignature()) return 0;
    return getGenSigHeader()->getArgumentLayoutSizeInWords();
  }
  
  bool isCopyable() const {
    for (auto &reqt : getRequirementSignature().getRequirements()) {
      if (reqt.getKind() != GenericRequirementKind::InvertedProtocols) {
        continue;
      }
      if (reqt.getInvertedProtocols()
              .contains(InvertibleProtocolKind::Copyable)) {
        return false;
      }
    }
    return true;
  }
};
using ExtendedExistentialTypeShape
  = TargetExtendedExistentialTypeShape<InProcess>;

/// A hash which is guaranteed (ignoring a weakness in the
/// selected cryptographic hash algorithm) to be unique for the
/// source string.  Cryptographic hashing is reasonable to use
/// for certain kinds of complex uniquing performed by the
/// runtime when the representation being uniqued would otherwise
/// be prohibitively difficult to hash and compare, such as a
/// generic signature.
///
/// The hash is expected to be computed at compile time and simply
/// trusted at runtime.  We are therefore not concerned about
/// malicious collisions: an attacker would have to control the
/// program text, and there is nothing they can accomplish from a
/// hash collision that they couldn't do more easily by just changing
/// the program to do what they want.  We just want a hash with
/// minimal chance of a birthday-problem collision.  As long as
/// we use a cryptographic hash algorithm, even a 64-bit hash would
/// probably do the trick just fine, since the number of objects
/// being uniqued will be far less than 2^32.  Still, to stay on the
/// safe side, we use a 128-bit hash; the additional 8 bytes is
/// fairly marginal compared to the size of (e.g.) even the smallest
/// existential shape.
///
/// We'd like to use BLAKE3 for this, but pending acceptance of
/// that into LLVM, we're using SHA-256.  We simply truncate the
/// hash to the desired length.
struct UniqueHash {
  static_assert(NumBytes_UniqueHash % sizeof(uint32_t) == 0,
                "NumBytes_UniqueHash not a multiple of 4");
  enum { NumChunks = NumBytes_UniqueHash / sizeof(uint32_t) };

  uint32_t Data[NumChunks];

  friend bool operator==(const UniqueHash &lhs, const UniqueHash &rhs) {
    for (unsigned i = 0; i != NumChunks; ++i)
      if (lhs.Data[i] != rhs.Data[i])
        return false;
    return true;
  }

  friend uint32_t hash_value(const UniqueHash &hash) {
    // It's a cryptographic hash, so there's no point in merging
    // hash data from multiple chunks.
    return hash.Data[0];
  }
};

/// A descriptor for an extended existential type descriptor which
/// needs to be uniqued at runtime.
///
/// Uniquing is performed by comparing the existential type strings
/// of the shapes.
template <typename Runtime>
struct TargetNonUniqueExtendedExistentialTypeShape {
  /// A reference to memory that can be used to cache a globally-unique
  /// descriptor for this existential shape.
  TargetRelativeDirectPointer<Runtime,
    std::atomic<ConstTargetMetadataPointer<Runtime,
                  TargetExtendedExistentialTypeShape>>> UniqueCache;

  llvm::StringRef getExistentialTypeStringForUniquing() const {
    // When we have a non-unique shape, we're guaranteed that
    // ExistentialType contains no symbolic references, so we can just
    // recover it this way rather than having to parse it.
    return LocalCopy.ExistentialType.get();
  }

  /// The local copy of the existential shape descriptor.
  TargetExtendedExistentialTypeShape<Runtime> LocalCopy;
};
using NonUniqueExtendedExistentialTypeShape
  = TargetNonUniqueExtendedExistentialTypeShape<InProcess>;

/// The structure of type metadata for existential types which require
/// an extended existential descriptor.
///
/// An extended existential type metadata is a concrete application of
/// an extended existential descriptor to its generalization arguments,
/// which there may be none of.  See ExtendedExistentialDescriptor.
template <typename Runtime>
struct TargetExtendedExistentialTypeMetadata
  : TargetMetadata<Runtime>,
    swift::ABI::TrailingObjects<
      TargetExtendedExistentialTypeMetadata<Runtime>,
      ConstTargetPointer<Runtime, void>> {
  using StoredSize = typename Runtime::StoredSize;

private:
  using TrailingObjects =
    swift::ABI::TrailingObjects<
      TargetExtendedExistentialTypeMetadata<Runtime>,
      ConstTargetPointer<Runtime, void>>;
  friend TrailingObjects;

  template<typename T>
  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;

  size_t numTrailingObjects(OverloadToken<ConstTargetPointer<Runtime, void>>) const {
    return Shape->getGenSigArgumentLayoutSizeInWords();
  }

public:
  static constexpr StoredSize OffsetToArguments = sizeof(TargetMetadata<Runtime>);

public:
  explicit constexpr
  TargetExtendedExistentialTypeMetadata(const ExtendedExistentialTypeShape *shape)
    : TargetMetadata<Runtime>(MetadataKind::ExtendedExistential),
      Shape(shape) {}

  TargetSignedPointer<Runtime, const ExtendedExistentialTypeShape *
                    __ptrauth_swift_nonunique_extended_existential_type_shape>
    Shape;

  ConstTargetPointer<Runtime, void> const *getGeneralizationArguments() const {
    return this->template getTrailingObjects<ConstTargetPointer<Runtime, void>>();
  }

public:
  static bool classof(const TargetMetadata<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::ExtendedExistential;
  }
};
using ExtendedExistentialTypeMetadata
  = TargetExtendedExistentialTypeMetadata<InProcess>;

/// The basic layout of an existential metatype type.
template <typename Runtime>
struct TargetExistentialMetatypeContainer {
  ConstTargetMetadataPointer<Runtime, TargetMetadata> Value;

  TargetWitnessTablePointer<Runtime> *getWitnessTables() {
    return reinterpret_cast<TargetWitnessTablePointer<Runtime> *>(this + 1);
  }
  TargetWitnessTablePointer<Runtime> const *getWitnessTables() const {
    return reinterpret_cast<TargetWitnessTablePointer<Runtime> 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<InProcess>;

/// The structure of metadata for existential metatypes.
template <typename Runtime>
struct TargetExistentialMetatypeMetadata
  : public TargetMetadata<Runtime> {
  /// The type metadata for the element.
  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> InstanceType;

  /// The number of witness tables and class-constrained-ness of the
  /// underlying type.
  ExistentialTypeFlags Flags;

  static bool classof(const TargetMetadata<Runtime> *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<InProcess>;

/// Heap metadata for a box, which may have been generated statically by the
/// compiler or by the runtime.
template <typename Runtime>
struct TargetBoxHeapMetadata : public TargetHeapMetadata<Runtime> {
  /// The offset from the beginning of a box to its value.
  unsigned Offset;

  constexpr TargetBoxHeapMetadata(MetadataKind kind, unsigned offset)
  : TargetHeapMetadata<Runtime>(kind), Offset(offset) {}
};
using BoxHeapMetadata = TargetBoxHeapMetadata<InProcess>;

/// Heap metadata for runtime-instantiated generic boxes.
template <typename Runtime>
struct TargetGenericBoxHeapMetadata : public TargetBoxHeapMetadata<Runtime> {
  using super = TargetBoxHeapMetadata<Runtime>;
  using super::Offset;

  /// The type inside the box.
  ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> BoxedType;

  constexpr
  TargetGenericBoxHeapMetadata(MetadataKind kind, unsigned offset,
    ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> boxedType)
  : TargetBoxHeapMetadata<Runtime>(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<char*>(box);
    return reinterpret_cast<OpaqueValue *>(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<Runtime> *metadata) {
    return metadata->getKind() == MetadataKind::HeapGenericLocalVariable;
  }
};
using GenericBoxHeapMetadata = TargetGenericBoxHeapMetadata<InProcess>;

/// 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 <typename Runtime>
struct TargetResilientWitness {
  TargetRelativeProtocolRequirementPointer<Runtime> Requirement;
  union {
    TargetRelativeDirectPointer<Runtime, void> Impl;
    TargetCompactFunctionPointer<Runtime, void> FuncImpl;
  };

  void *getWitness(ProtocolRequirementFlags flags) const {
    if (flags.isFunctionImpl()) {
      return FuncImpl.get();
    } else {
      return Impl.get();
    }
  }
};
using ResilientWitness = TargetResilientWitness<InProcess>;

template <typename Runtime>
struct TargetResilientWitnessTable final
  : public swift::ABI::TrailingObjects<
             TargetResilientWitnessTable<Runtime>,
             TargetResilientWitness<Runtime>> {
  uint32_t NumWitnesses;

  using TrailingObjects = swift::ABI::TrailingObjects<
                             TargetResilientWitnessTable<Runtime>,
                             TargetResilientWitness<Runtime>>;
  friend TrailingObjects;

  template<typename T>
  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;

  size_t numTrailingObjects(
                        OverloadToken<TargetResilientWitness<Runtime>>) const {
    return NumWitnesses;
  }

  llvm::ArrayRef<TargetResilientWitness<Runtime>>
  getWitnesses() const {
    return {this->template getTrailingObjects<TargetResilientWitness<Runtime>>(),
            NumWitnesses};
  }

  const TargetResilientWitness<Runtime> &
  getWitness(unsigned i) const {
    return getWitnesses()[i];
  }
};
using ResilientWitnessTable = TargetResilientWitnessTable<InProcess>;

/// 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 <typename Runtime>
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.
  TargetCompactFunctionPointer<
      Runtime,
      void(TargetWitnessTable<Runtime> *instantiatedTable,
           const TargetMetadata<Runtime> *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. Might be null when building with
  /// -disable-preallocated-instantiation-caches.
  RelativeDirectPointer<PrivateDataType> 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<InProcess>;

/// The structure of a type metadata record.
///
/// This contains enough static information to recover type metadata from a
/// name.
template <typename Runtime>
struct TargetTypeMetadataRecord {
private:
  union {
    /// A direct reference to a nominal type descriptor.
    RelativeDirectPointerIntPair<TargetContextDescriptor<Runtime>,
                                 TypeReferenceKind>
      DirectNominalTypeDescriptor;

    /// An indirect reference to a nominal type descriptor.
    RelativeDirectPointerIntPair<TargetSignedPointer<Runtime, TargetContextDescriptor<Runtime> * __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<Runtime> *
  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<InProcess>;

/// The structure of a protocol reference record.
template <typename Runtime>
struct TargetProtocolRecord {
  /// The protocol referenced.
  ///
  /// The remaining low bit is reserved for future use.
  RelativeContextPointerIntPair<Runtime, /*reserved=*/bool,
                                TargetProtocolDescriptor>
    Protocol;
};
using ProtocolRecord = TargetProtocolRecord<InProcess>;

template<typename Runtime> class TargetGenericRequirementDescriptor;

/// Header containing information about the resilient witnesses in a
/// protocol conformance descriptor.
template <typename Runtime>
struct TargetResilientWitnessesHeader {
  uint32_t NumWitnesses;
};
using ResilientWitnessesHeader = TargetResilientWitnessesHeader<InProcess>;

/// Describes a reference to a global actor type and its conformance to the
/// global actor protocol.
template<typename Runtime>
struct TargetGlobalActorReference {
private:
  using SignedDescriptorPointer =
      const TargetProtocolConformanceDescriptor<Runtime>
          *__ptrauth_swift_protocol_conformance_descriptor;

public:
  /// The type of the global actor.
  RelativeDirectPointer<const char, /*nullable*/ false> type;

  /// The conformance of the global actor to the GlobalActor protocol.
  RelativeIndirectablePointer<
      const TargetProtocolConformanceDescriptor<Runtime>,
      /*nullable*/ false,
      /*offset*/ int32_t,
      /*indirect type*/ SignedDescriptorPointer>
      conformance;
};

/// Describes the context of a protocol conformance that is relevant when
/// the conformance is used, such as global actor isolation.
struct ConformanceExecutionContext;

/// 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 <typename Runtime>
struct TargetProtocolConformanceDescriptor final
  : public swift::ABI::TrailingObjects<
             TargetProtocolConformanceDescriptor<Runtime>,
             TargetRelativeContextPointer<Runtime>,
             TargetGenericRequirementDescriptor<Runtime>,
             GenericPackShapeDescriptor,
             TargetResilientWitnessesHeader<Runtime>,
             TargetResilientWitness<Runtime>,
             TargetGenericWitnessTable<Runtime>,
             TargetGlobalActorReference<Runtime>> {

  using TrailingObjects = swift::ABI::TrailingObjects<
                             TargetProtocolConformanceDescriptor<Runtime>,
                             TargetRelativeContextPointer<Runtime>,
                             TargetGenericRequirementDescriptor<Runtime>,
                             GenericPackShapeDescriptor,
                             TargetResilientWitnessesHeader<Runtime>,
                             TargetResilientWitness<Runtime>,
                             TargetGenericWitnessTable<Runtime>,
                             TargetGlobalActorReference<Runtime>>;
  friend TrailingObjects;

  template<typename T>
  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;

public:
  using GenericRequirementDescriptor =
    TargetGenericRequirementDescriptor<Runtime>;

  using ResilientWitnessesHeader = TargetResilientWitnessesHeader<Runtime>;
  using ResilientWitness = TargetResilientWitness<Runtime>;
  using GenericWitnessTable = TargetGenericWitnessTable<Runtime>;

private:
  /// The protocol being conformed to.
  TargetRelativeContextPointer<Runtime, TargetProtocolDescriptor> Protocol;
  
  // Some description of the type that conforms to the protocol.
  TargetTypeReference<Runtime> TypeRef;

  /// The witness table pattern, which may also serve as the witness table.
  RelativeDirectPointer<const TargetWitnessTable<Runtime>> WitnessTablePattern;

  /// Various flags, including the kind of conformance.
  ConformanceFlags Flags;

public:
  ConstTargetPointer<Runtime, TargetProtocolDescriptor<Runtime>>
  getProtocol() const {
    return Protocol;
  }

  TypeReferenceKind getTypeKind() const {
    return Flags.getTypeReferenceKind();
  }

  const char *getDirectObjCClassName() const {
    return TypeRef.getDirectObjCClassName(getTypeKind());
  }

  const TargetClassMetadataObjCInterop<Runtime> *const *
  getIndirectObjCClass() const {
    return TypeRef.getIndirectObjCClass(getTypeKind());
  }

  const TargetContextDescriptor<Runtime> *getTypeDescriptor() const {
    return TypeRef.getTypeDescriptor(getTypeKind());
  }

  constexpr inline auto
  getTypeRefDescriptorOffset() const -> typename Runtime::StoredSize {
    return offsetof(typename std::remove_reference<decltype(*this)>::type, TypeRef);
  }

  constexpr inline auto
  getProtocolDescriptorOffset() const -> typename Runtime::StoredSize {
    return offsetof(typename std::remove_reference<decltype(*this)>::type, Protocol);
  }

  TargetContextDescriptor<Runtime> * __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<Runtime> *getRetroactiveContext() const {
    if (!Flags.isRetroactive()) return nullptr;

    return this->template getTrailingObjects<
        TargetRelativeContextPointer<Runtime>>();
  }

  /// 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<TargetGenericRequirementDescriptor<Runtime>>
  getConditionalRequirements() const {
    return {this->template getTrailingObjects<TargetGenericRequirementDescriptor<Runtime>>(),
            Flags.getNumConditionalRequirements()};
  }

  /// Retrieve the pack shape descriptors for the conditional pack requirements.
  llvm::ArrayRef<GenericPackShapeDescriptor>
  getConditionalPackShapeDescriptors() const {
    return {this->template getTrailingObjects<GenericPackShapeDescriptor>(),
            Flags.getNumConditionalPackShapeDescriptors()};
  }

  /// Get the directly-referenced witness table pattern, which may also
  /// serve as the witness table.
  const swift::TargetWitnessTable<Runtime> *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<Runtime> *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.
  ///
  /// The context will be populated with any information that needs to be
  /// checked before this witness table can be used within a given execution
  /// context.
  const swift::TargetWitnessTable<Runtime> *
  getWitnessTable(const TargetMetadata<Runtime> *type,
                  ConformanceExecutionContext &context) const;

  /// Retrieve the resilient witnesses.
  llvm::ArrayRef<ResilientWitness> getResilientWitnesses() const {
    if (!Flags.hasResilientWitnesses())
      return { };

    return llvm::ArrayRef<ResilientWitness>(
        this->template getTrailingObjects<ResilientWitness>(),
        numTrailingObjects(OverloadToken<ResilientWitness>()));
  }

  ConstTargetPointer<Runtime, GenericWitnessTable>
  getGenericWitnessTable() const {
    if (!Flags.hasGenericWitnessTable())
      return nullptr;

    return this->template getTrailingObjects<GenericWitnessTable>();
  }

  /// Whether this conformance has any conditional requirements that need to
  /// be evaluated.
  bool hasGlobalActorIsolation() const {
    return Flags.hasGlobalActorIsolation();
  }

  /// Retrieve the global actor type to which this conformance is isolated, if
  /// any.
  llvm::StringRef
  getGlobalActorType() const {
    if (!Flags.hasGlobalActorIsolation())
      return llvm::StringRef();

    return Demangle::makeSymbolicMangledNameStringRef(this->template getTrailingObjects<TargetGlobalActorReference<Runtime>>()->type);
  }

  /// Retrieve the protocol conformance of the global actor type to the
  /// GlobalActor protocol.
  const TargetProtocolConformanceDescriptor<Runtime> *
  getGlobalActorConformance() const {
    if (!Flags.hasGlobalActorIsolation())
      return nullptr;

    return this->template getTrailingObjects<TargetGlobalActorReference<Runtime>>()->conformance;
  }

#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<TargetRelativeContextPointer<Runtime>>) const {
    return Flags.isRetroactive() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<GenericRequirementDescriptor>) const {
    return Flags.getNumConditionalRequirements();
  }

  size_t numTrailingObjects(OverloadToken<GenericPackShapeDescriptor>) const {
    return Flags.getNumConditionalPackShapeDescriptors();
  }

  size_t numTrailingObjects(OverloadToken<ResilientWitnessesHeader>) const {
    return Flags.hasResilientWitnesses() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<ResilientWitness>) const {
    return Flags.hasResilientWitnesses()
      ? this->template getTrailingObjects<ResilientWitnessesHeader>()
          ->NumWitnesses
      : 0;
  }

  size_t numTrailingObjects(OverloadToken<GenericWitnessTable>) const {
    return Flags.hasGenericWitnessTable() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<RelativeDirectPointer<const char, /*nullable*/ true>>) const {
    return Flags.hasGlobalActorIsolation() ? 1 : 0;
  }
};
using ProtocolConformanceDescriptor
  = TargetProtocolConformanceDescriptor<InProcess>;

template<typename Runtime>
using TargetProtocolConformanceRecord =
  RelativeDirectPointer<TargetProtocolConformanceDescriptor<Runtime>,
                        /*Nullable=*/false>;

using ProtocolConformanceRecord = TargetProtocolConformanceRecord<InProcess>;

template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalProtocolConformanceDescriptor = TargetProtocolConformanceDescriptor<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalProtocolConformanceRecord = TargetProtocolConformanceRecord<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

template <typename Runtime>
struct swift_ptrauth_struct_context_descriptor(ModuleContextDescriptor)
    TargetModuleContextDescriptor;

/// Base class for all context descriptors.
template <typename Runtime>
struct swift_ptrauth_struct_context_descriptor(ContextDescriptor)
    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<Runtime> Parent;

  bool isGeneric() const { return Flags.isGeneric(); }
  bool isUnique() const { return Flags.isUnique(); }
  bool hasInvertibleProtocols() const {
    return Flags.hasInvertibleProtocols();
  }
  ContextDescriptorKind getKind() const { return Flags.getKind(); }

  /// Get the generic context information for this context, or null if the
  /// context is not generic.
  const TargetGenericContext<Runtime> *getGenericContext() const;

  /// Get the module context for this context.
  const TargetModuleContextDescriptor<Runtime> *getModuleContext() const;

  /// Retrieve the set of protocols that are inverted by this type's
  /// primary definition.
  ///
  /// This type might still conditionally conform to any of the protocols
  /// that are inverted here, but that information is recorded in the
  /// conditional inverted protocols of the corresponding `GenericContext`.
  const InvertibleProtocolSet *
  getInvertedProtocols() 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;
  }

  constexpr inline auto
  getParentOffset() const -> typename Runtime::StoredSize {
    return offsetof(typename std::remove_reference<decltype(*this)>::type, Parent);
  }

#ifndef NDEBUG
  [[deprecated("Only meant for use in the debugger")]] void dump() const;
#endif

private:
  TargetContextDescriptor(const TargetContextDescriptor &) = delete;
  TargetContextDescriptor(TargetContextDescriptor &&) = delete;
  TargetContextDescriptor &operator=(const TargetContextDescriptor &) = delete;
  TargetContextDescriptor &operator=(TargetContextDescriptor &&) = delete;
};

using ContextDescriptor = TargetContextDescriptor<InProcess>;
template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalContextDescriptor = TargetContextDescriptor<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

inline bool isCImportedModuleName(llvm::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 <typename Runtime>
struct swift_ptrauth_struct_context_descriptor(ModuleContextDescriptor)
    TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
  /// The module name.
  TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> Name;

  /// Is this module a special C-imported module?
  bool isCImportedContext() const {
    return isCImportedModuleName(Name.get());
  }

  constexpr inline auto
  getNameOffset() const -> typename Runtime::StoredSize {
    return offsetof(typename std::remove_reference<decltype(*this)>::type, Name);
  }

  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
    return cd->getKind() == ContextDescriptorKind::Module;
  }
};

using ModuleContextDescriptor = TargetModuleContextDescriptor<InProcess>;

template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalModuleContextDescriptor = TargetModuleContextDescriptor<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

template<typename Runtime>
inline bool TargetContextDescriptor<Runtime>::isCImportedContext() const {
  return getModuleContext()->isCImportedContext();
}

template<typename Runtime>
inline const TargetModuleContextDescriptor<Runtime> *
TargetContextDescriptor<Runtime>::getModuleContext() const {
  // All context chains should eventually find a module.
  for (auto cur = this; true; cur = cur->Parent.get()) {
    if (auto module = dyn_cast<TargetModuleContextDescriptor<Runtime>>(cur))
      return module;
  }
}

/// Descriptor for an extension context.
template <typename Runtime>
struct swift_ptrauth_struct_context_descriptor(ExtensionContextDescriptor)
    TargetExtensionContextDescriptor final
    : TargetContextDescriptor<Runtime>,
      TrailingGenericContextObjects<TargetExtensionContextDescriptor<Runtime>>
{
private:
  using TrailingGenericContextObjects =
      swift::TrailingGenericContextObjects<TargetExtensionContextDescriptor<Runtime>>;

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.
  TargetRelativeDirectPointer<Runtime, const char> ExtendedContext;

  using TrailingGenericContextObjects::getGenericContext;

  llvm::StringRef getMangledExtendedContext() const {
    return Demangle::makeSymbolicMangledNameStringRef(ExtendedContext.get());
  }
  
  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
    return cd->getKind() == ContextDescriptorKind::Extension;
  }
};

using ExtensionContextDescriptor = TargetExtensionContextDescriptor<InProcess>;

template<typename Runtime>
struct TargetMangledContextName {
  /// The mangled name of the context.
  TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> name;
};

template <typename Runtime>
struct swift_ptrauth_struct_context_descriptor(AnonymousContextDescriptor)
    TargetAnonymousContextDescriptor final
    : TargetContextDescriptor<Runtime>,
      TrailingGenericContextObjects<TargetAnonymousContextDescriptor<Runtime>,
                                    TargetGenericContextDescriptorHeader,
                                    TargetMangledContextName<Runtime>>
{
private:
  using TrailingGenericContextObjects =
      swift::TrailingGenericContextObjects<TargetAnonymousContextDescriptor<Runtime>,
                                           TargetGenericContextDescriptorHeader,
                                           TargetMangledContextName<Runtime>>;
  using TrailingObjects =
    typename TrailingGenericContextObjects::TrailingObjects;
  friend TrailingObjects;

public:
  using MangledContextName = TargetMangledContextName<Runtime>;

  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<Runtime, char> getMangledName() const {
    if (!hasMangledName())
      return ConstTargetPointer<Runtime, char>();

    return this->template getTrailingObjects<MangledContextName>()->name;
  }

  /// Retrieve a pointer to the mangled context name structure.
  const MangledContextName *getMangledContextName() const {
    if (!hasMangledName())
      return nullptr;

    return this->template getTrailingObjects<MangledContextName>();
  }

private:
  template<typename T>
  using OverloadToken =
    typename TrailingGenericContextObjects::template OverloadToken<T>;

  using TrailingGenericContextObjects::numTrailingObjects;

  size_t numTrailingObjects(OverloadToken<MangledContextName>) const {
    return this->hasMangledName() ? 1 : 0;
  }

public:
  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
    return cd->getKind() == ContextDescriptorKind::Anonymous;
  }
};
using AnonymousContextDescriptor = TargetAnonymousContextDescriptor<InProcess>;

template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalAnonymousContextDescriptor = TargetAnonymousContextDescriptor<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

/// 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 <typename Runtime>
struct swift_ptrauth_struct_context_descriptor(ProtocolDescriptor)
    TargetProtocolDescriptor final
    : TargetContextDescriptor<Runtime>,
      swift::ABI::TrailingObjects<
        TargetProtocolDescriptor<Runtime>,
        TargetGenericRequirementDescriptor<Runtime>,
        TargetProtocolRequirement<Runtime>>
{
private:
  using TrailingObjects
    = swift::ABI::TrailingObjects<
        TargetProtocolDescriptor<Runtime>,
        TargetGenericRequirementDescriptor<Runtime>,
        TargetProtocolRequirement<Runtime>>;

  friend TrailingObjects;

  template<typename T>
  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;

public:
  size_t numTrailingObjects(
            OverloadToken<TargetGenericRequirementDescriptor<Runtime>>) const {
    return NumRequirementsInSignature;
  }

  size_t numTrailingObjects(
            OverloadToken<TargetProtocolRequirement<Runtime>>) const {
    return NumRequirements;
  }


  /// The name of the protocol.
  TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> 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<const char, /*Nullable=*/true> AssociatedTypeNames;

  ProtocolContextDescriptorFlags getProtocolContextDescriptorFlags() const {
    return ProtocolContextDescriptorFlags(this->Flags.getKindSpecificFlags());
  }

  /// Retrieve the requirements that make up the requirement signature of
  /// this protocol.
  llvm::ArrayRef<TargetGenericRequirementDescriptor<Runtime>>
  getRequirementSignature() const {
    return {this->template getTrailingObjects<
                             TargetGenericRequirementDescriptor<Runtime>>(),
            NumRequirementsInSignature};
  }

  /// Retrieve the requirements of this protocol.
  llvm::ArrayRef<TargetProtocolRequirement<Runtime>>
  getRequirements() const {
    return {this->template getTrailingObjects<
                             TargetProtocolRequirement<Runtime>>(),
            NumRequirements};
  }

  constexpr inline auto
  getNameOffset() const -> typename Runtime::StoredSize {
    return offsetof(typename std::remove_reference<decltype(*this)>::type, Name);
  }

  /// Retrieve the requirement base descriptor address.
  ConstTargetPointer<Runtime, TargetProtocolRequirement<Runtime>>
  getRequirementBaseDescriptor() const {
    return getRequirements().data() - WitnessTableFirstRequirementOffset;
  }

#ifndef NDEBUG
  [[deprecated("Only meant for use in the debugger")]] void dump() const;
#endif

  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
    return cd->getKind() == ContextDescriptorKind::Protocol;
  }
};

/// The descriptor for an opaque type.
template <typename Runtime>
struct swift_ptrauth_struct_context_descriptor(OpaqueTypeDescriptor)
    TargetOpaqueTypeDescriptor final
    : TargetContextDescriptor<Runtime>,
    TrailingGenericContextObjects<TargetOpaqueTypeDescriptor<Runtime>,
                                  TargetGenericContextDescriptorHeader,
                                  RelativeDirectPointer<const char>,
                                  InvertibleProtocolSet>
{
private:
  using TrailingGenericContextObjects =
      swift::TrailingGenericContextObjects<TargetOpaqueTypeDescriptor<Runtime>,
                                           TargetGenericContextDescriptorHeader,
                                           RelativeDirectPointer<const char>,
                                           InvertibleProtocolSet>;
  using TrailingObjects =
    typename TrailingGenericContextObjects::TrailingObjects;
  friend TrailingObjects;

  template<typename T>
  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;

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<RelativeDirectPointer<const char>>) const {
    return getNumUnderlyingTypeArguments();
  }
  
  const RelativeDirectPointer<const char> &
  getUnderlyingTypeArgumentMangledName(unsigned i) const {
    assert(i < getNumUnderlyingTypeArguments());
    return (this
         ->template getTrailingObjects<RelativeDirectPointer<const char>>())[i];
  }

  llvm::StringRef getUnderlyingTypeArgument(unsigned i) const {
    assert(i < getNumUnderlyingTypeArguments());
    const char *ptr = getUnderlyingTypeArgumentMangledName(i);    
    return Demangle::makeSymbolicMangledNameStringRef(ptr);
  }

  /// Retrieve the set of protocols that are inverted by this type's
  /// primary definition.
  ///
  /// This type might still conditionally conform to any of the protocols
  /// that are inverted here, but that information is recorded in the
  /// conditional inverted protocols of the corresponding `GenericContext`.
  const InvertibleProtocolSet &
  getInvertedProtocols() const {
    assert(this->hasInvertibleProtocols());
    return
      *this->template getTrailingObjects<InvertibleProtocolSet>();
  }
  
  size_t numTrailingObjects(OverloadToken<InvertibleProtocolSet>) const {
    return this->hasInvertibleProtocols() ? 1 : 0;
  }

  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
    return cd->getKind() == ContextDescriptorKind::OpaqueType;
  }
};

template <template <typename Runtime> class ObjCInteropKind,
          unsigned PointerSize>
using ExternalOpaqueTypeDescriptor = TargetOpaqueTypeDescriptor<
    External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;
using OpaqueTypeDescriptor = TargetOpaqueTypeDescriptor<InProcess>;

/// 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 <typename Runtime>
struct TargetGenericMetadataInstantiationCache {
  /// Data that the runtime can use for its own purposes.  It is guaranteed
  /// to be zero-filled by the compiler. Might be null when building with
  /// -disable-preallocated-instantiation-caches.
  TargetPointer<Runtime, void>
  PrivateData[swift::NumGenericMetadataPrivateDataWords];
};
using GenericMetadataInstantiationCache =
  TargetGenericMetadataInstantiationCache<InProcess>;

/// 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<InProcess> *type,
             const void *arguments,
             const TargetGenericMetadataPattern<InProcess> *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<InProcess> *pattern);

/// An instantiation pattern for type metadata.
template <typename Runtime>
struct TargetGenericMetadataPattern {
  /// The function to call to instantiate the template.
  TargetCompactFunctionPointer<Runtime, MetadataInstantiator>
    InstantiationFunction;

  /// The function to call to complete the instantiation.  If this is null,
  /// the instantiation function must always generate complete metadata.
  TargetCompactFunctionPointer<Runtime, MetadataCompleter, /*nullable*/ true>
    CompletionFunction;

  /// Flags describing the layout of this instantiation pattern.
  GenericMetadataPatternFlags PatternFlags;

  bool hasExtraDataPattern() const {
    return PatternFlags.hasExtraDataPattern();
  }
};
using GenericMetadataPattern =
  TargetGenericMetadataPattern<InProcess>;

/// Part of a generic metadata instantiation pattern.
template <typename Runtime>
struct TargetGenericMetadataPartialPattern {
  /// A reference to the pattern.  The pattern must always be at least
  /// word-aligned.
  TargetRelativeDirectPointer<Runtime, typename Runtime::StoredPointer> 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<InProcess>;

/// A base class for conveniently adding trailing fields to a
/// generic metadata pattern.
template <typename Runtime,
          typename Self,
          typename... ExtraTrailingObjects>
class TargetGenericMetadataPatternTrailingObjects :
  protected swift::ABI::TrailingObjects<Self,
                                TargetGenericMetadataPartialPattern<Runtime>,
                                ExtraTrailingObjects...> {

  using TrailingObjects =
    swift::ABI::TrailingObjects<Self,
                                TargetGenericMetadataPartialPattern<Runtime>,
                                ExtraTrailingObjects...>;
  friend TrailingObjects;

  using GenericMetadataPartialPattern =
    TargetGenericMetadataPartialPattern<Runtime>;

  const Self *asSelf() const {
    return static_cast<const Self *>(this);
  }

  template<typename T>
  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;

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]
  /// See also: [pre-5.3-extra-data-zeroing]
  const GenericMetadataPartialPattern *getExtraDataPattern() const {
    assert(asSelf()->hasExtraDataPattern());
    return this->template getTrailingObjects<GenericMetadataPartialPattern>();
  }

protected:
  /// Return the class immediate-members pattern.
  const GenericMetadataPartialPattern *class_getImmediateMembersPattern() const{
    assert(asSelf()->class_hasImmediateMembersPattern());
    return this->template getTrailingObjects<GenericMetadataPartialPattern>()
             + size_t(asSelf()->hasExtraDataPattern());
  }

  size_t numTrailingObjects(OverloadToken<GenericMetadataPartialPattern>) const{
    return size_t(asSelf()->hasExtraDataPattern())
         + size_t(asSelf()->class_hasImmediateMembersPattern());
  }
};

/// An instantiation pattern for generic class metadata.
template <typename Runtime>
struct TargetGenericClassMetadataPattern final :
       TargetGenericMetadataPattern<Runtime>,
       TargetGenericMetadataPatternTrailingObjects<Runtime,
         TargetGenericClassMetadataPattern<Runtime>> {
  using TrailingObjects =
       TargetGenericMetadataPatternTrailingObjects<Runtime,
         TargetGenericClassMetadataPattern<Runtime>>;
  friend TrailingObjects;

  using TargetGenericMetadataPattern<Runtime>::PatternFlags;

  /// The heap-destructor function.
  TargetCompactFunctionPointer<Runtime, HeapObjectDestroyer> Destroy;

  /// The ivar-destructor function.
  TargetCompactFunctionPointer<Runtime, ClassIVarDestroyer, /*nullable*/ true>
    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<InProcess>;

/// An instantiation pattern for generic value metadata.
template <typename Runtime>
struct TargetGenericValueMetadataPattern final :
       TargetGenericMetadataPattern<Runtime>,
       TargetGenericMetadataPatternTrailingObjects<Runtime,
         TargetGenericValueMetadataPattern<Runtime>> {
  using TrailingObjects =
       TargetGenericMetadataPatternTrailingObjects<Runtime,
         TargetGenericValueMetadataPattern<Runtime>>;
  friend TrailingObjects;

  using TargetGenericMetadataPattern<Runtime>::PatternFlags;

  /// The value-witness table.  Indirectable so that we can re-use tables
  /// from other libraries if that seems wise.
  TargetRelativeIndirectablePointer<Runtime, const TargetValueWitnessTable<Runtime>>
    ValueWitnesses;

  const TargetValueWitnessTable<Runtime> *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<InProcess>;

template <typename Runtime>
struct TargetTypeGenericContextDescriptorHeader {
  /// The metadata instantiation cache.
  TargetRelativeDirectPointer<Runtime,
                              TargetGenericMetadataInstantiationCache<Runtime>>
    InstantiationCache;

  GenericMetadataInstantiationCache *getInstantiationCache() const {
    return InstantiationCache.get();
  }

  /// The default instantiation pattern.
  TargetRelativeDirectPointer<Runtime, TargetGenericMetadataPattern<Runtime>>
    DefaultInstantiationPattern;

  /// The base header.  Must always be the final member.
  TargetGenericContextDescriptorHeader<Runtime> Base;
  
  operator const TargetGenericContextDescriptorHeader<Runtime> &() const {
    return Base;
  }
};
using TypeGenericContextDescriptorHeader =
  TargetTypeGenericContextDescriptorHeader<InProcess>;

/// 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<void *>(Function);
  }
  
  /// Invoke with an array of arguments of dynamic size.
  MetadataResponse operator()(MetadataRequest request,
                              llvm::ArrayRef<const void *> 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<Fn0*>(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<Fn1*>(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<Fn2*>(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<Fn3*>(Function)(request, arg0, arg1, arg2);
  }
  
  /// Invoke with more than 3 arguments.
  template<typename...Args>
  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<FnN*>(Function)(request, args);
  }
};

/// The control structure for performing non-trivial initialization of
/// singleton foreign metadata.
template <typename Runtime>
struct TargetForeignMetadataInitialization {
  /// The completion function.  The pattern will always be null.
  TargetCompactFunctionPointer<Runtime, MetadataCompleter, /*nullable*/ true>
    CompletionFunction;
};

/// The cache structure for non-trivial initialization of singleton value
/// metadata.
template <typename Runtime>
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<TargetMetadataPointer<Runtime, TargetMetadata>> Metadata;

  /// The private cache data.
  std::atomic<TargetPointer<Runtime, void>> Private;
};
using SingletonMetadataCache =
  TargetSingletonMetadataCache<InProcess>;

template <typename Runtime>
struct TargetResilientClassMetadataPattern;

/// A function for allocating metadata for a resilient class, calculating
/// the correct metadata size at runtime.
using MetadataRelocator =
  Metadata *(const TargetTypeContextDescriptor<InProcess> *type,
             const TargetResilientClassMetadataPattern<InProcess> *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 <typename Runtime>
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.
  TargetCompactFunctionPointer<Runtime, MetadataRelocator, /*nullable*/ true>
    RelocationFunction;

  /// The heap-destructor function.
  TargetCompactFunctionPointer<Runtime, HeapObjectDestroyer> Destroy;

  /// The ivar-destructor function.
  TargetCompactFunctionPointer<Runtime, ClassIVarDestroyer, /*nullable*/ true>
    IVarDestroyer;

  /// The class flags.
  ClassFlags Flags;

  // The following fields are only present in ObjC interop.

  /// Our ClassROData.
  TargetRelativeDirectPointer<Runtime, void> Data;

  /// Our metaclass.
  TargetRelativeDirectPointer<Runtime, TargetAnyClassMetadata<Runtime>> Metaclass;
};

using ResilientClassMetadataPattern =
  TargetResilientClassMetadataPattern<InProcess>;

/// 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 <typename Runtime>
struct TargetSingletonMetadataInitialization {
  /// The initialization cache.  Out-of-line because mutable.
  TargetRelativeDirectPointer<Runtime,
                              TargetSingletonMetadataCache<Runtime>>
    InitializationCache;

  union {
    /// The incomplete metadata, for structs, enums and classes without
    /// resilient ancestry.
    TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>>
      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<Runtime, TargetResilientClassMetadataPattern<Runtime>>
      ResilientPattern;
  };

  /// The completion function.  The pattern will always be null, even
  /// for a resilient class.
  TargetCompactFunctionPointer<Runtime, MetadataCompleter>
    CompletionFunction;

  bool hasResilientClassPattern(
      const TargetTypeContextDescriptor<Runtime> *description) const {
    auto *classDescription =
      dyn_cast<TargetClassDescriptor<Runtime>>(description);
    return (classDescription != nullptr &&
            classDescription->hasResilientSuperclass());
  }

  /// This method can only be called from the runtime itself. It is defined
  /// in Metadata.cpp.
  TargetMetadata<Runtime> *allocate(
      const TargetTypeContextDescriptor<Runtime> *description) const;
};

template <typename Runtime>
struct TargetCanonicalSpecializedMetadatasListCount {
  uint32_t count;
};

template <typename Runtime>
struct TargetCanonicalSpecializedMetadatasListEntry {
  TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>, /*Nullable*/ false> metadata;
};

template <typename Runtime>
struct TargetCanonicalSpecializedMetadataAccessorsListEntry {
  TargetCompactFunctionPointer<Runtime, MetadataResponse(MetadataRequest), /*Nullable*/ false> accessor;
};

template <typename Runtime>
struct TargetCanonicalSpecializedMetadatasCachingOnceToken {
  TargetRelativeDirectPointer<Runtime, swift_once_t, /*Nullable*/ false> token;
};

template <typename Runtime>
struct TargetSingletonMetadataPointer {
  TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>,
                              /*Nullable*/ false>
      metadata;
};

template <typename Runtime>
class swift_ptrauth_struct_context_descriptor(TypeContextDescriptor)
    TargetTypeContextDescriptor : public TargetContextDescriptor<Runtime> {
public:
  /// The name of the type.
  TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> 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.
  TargetCompactFunctionPointer<Runtime, MetadataResponse(...),
                              /*Nullable*/ true> AccessFunctionPtr;
  
  /// A pointer to the field descriptor for the type, if any.
  TargetRelativeDirectPointer<Runtime,
                              const reflection::TargetFieldDescriptor<Runtime>,
                              /*nullable*/ true>
      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 initialization?
  bool hasForeignMetadataInitialization() const {
    return getTypeContextDescriptorFlags().hasForeignMetadataInitialization();
  }

  bool hasCanonicalMetadataPrespecializations() const {
    return this->isGeneric() &&
           getTypeContextDescriptorFlags()
               .hasCanonicalMetadataPrespecializationsOrSingletonMetadataPointer();
  }

  bool hasSingletonMetadataPointer() const {
    return !this->isGeneric() &&
           getTypeContextDescriptorFlags()
               .hasCanonicalMetadataPrespecializationsOrSingletonMetadataPointer();
  }

  bool hasLayoutString() const {
    return getTypeContextDescriptorFlags().hasLayoutString();
  }

  /// Given that this type has foreign metadata initialization, return the
  /// control structure for it.
  const TargetForeignMetadataInitialization<Runtime> &
  getForeignMetadataInitialization() const;

  const TargetSingletonMetadataInitialization<Runtime> &
  getSingletonMetadataInitialization() const;

  const TargetTypeGenericContextDescriptorHeader<Runtime> &
  getFullGenericContextHeader() const;

  const TargetGenericContextDescriptorHeader<Runtime> &
  getGenericContextHeader() const {
    return getFullGenericContextHeader();
  }

  llvm::ArrayRef<GenericParamDescriptor> 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;

  constexpr inline auto
  getNameOffset() const -> typename Runtime::StoredSize {
    return offsetof(typename std::remove_reference<decltype(*this)>::type, Name);
  }

  /// Return the start of the generic arguments array in the nominal
  /// type's metadata. The returned value is measured in sizeof(StoredPointer).
  const TargetMetadata<Runtime> * const *getGenericArguments(
                               const TargetMetadata<Runtime> *metadata) const {
    auto offset = getGenericArgumentOffset();
    auto words =
      reinterpret_cast<const TargetMetadata<Runtime> * const *>(metadata);
    return words + offset;
  }

  const llvm::ArrayRef<TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>, /*Nullable*/ false>>
  getCanonicalMetadataPrespecializations() const;

  swift_once_t *getCanonicalMetadataPrespecializationCachingOnceToken() const;

  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
    return cd->getKind() >= ContextDescriptorKind::Type_First
        && cd->getKind() <= ContextDescriptorKind::Type_Last;
  }
};

/// 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 <typename Runtime>
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<StoredPointerDifference> ImmediateMembersOffset;

  /// The positive and negative bounds of the class metadata.
  TargetMetadataBounds<Runtime> 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<Runtime> &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<Runtime> 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<InProcess>;

template <typename Runtime>
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<Runtime, const void, /*nullable*/true> 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 <typename Runtime>
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<Runtime, const void> Stub;
};

template <typename Runtime>
class swift_ptrauth_struct_context_descriptor(ClassDescriptor)
    TargetClassDescriptor final
    : public TargetTypeContextDescriptor<Runtime>,
      public TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
                              TargetTypeGenericContextDescriptorHeader,
                              /*additional trailing objects:*/
                              TargetResilientSuperclass<Runtime>,
                              TargetForeignMetadataInitialization<Runtime>,
                              TargetSingletonMetadataInitialization<Runtime>,
                              TargetVTableDescriptorHeader<Runtime>,
                              TargetMethodDescriptor<Runtime>,
                              TargetOverrideTableHeader<Runtime>,
                              TargetMethodOverrideDescriptor<Runtime>,
                              TargetObjCResilientClassStubInfo<Runtime>,
                              TargetCanonicalSpecializedMetadatasListCount<Runtime>,
                              TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
                              TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>,
                              TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>,
                              InvertibleProtocolSet,
                              TargetSingletonMetadataPointer<Runtime>,
                              TargetMethodDefaultOverrideTableHeader<Runtime>,
                              TargetMethodDefaultOverrideDescriptor<Runtime>> {
private:
  using TrailingGenericContextObjects = 
    swift::TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
                                         TargetTypeGenericContextDescriptorHeader,
                                         TargetResilientSuperclass<Runtime>,
                                         TargetForeignMetadataInitialization<Runtime>,
                                         TargetSingletonMetadataInitialization<Runtime>,
                                         TargetVTableDescriptorHeader<Runtime>,
                                         TargetMethodDescriptor<Runtime>,
                                         TargetOverrideTableHeader<Runtime>,
                                         TargetMethodOverrideDescriptor<Runtime>,
                                         TargetObjCResilientClassStubInfo<Runtime>,
                                         TargetCanonicalSpecializedMetadatasListCount<Runtime>,
                                         TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
                                         TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>,
                                         TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>,
                                         InvertibleProtocolSet,
                                         TargetSingletonMetadataPointer<Runtime>,
                                         TargetMethodDefaultOverrideTableHeader<Runtime>,
                                         TargetMethodDefaultOverrideDescriptor<Runtime>>;

  using TrailingObjects =
    typename TrailingGenericContextObjects::TrailingObjects;
  friend TrailingObjects;

public:
  using MethodDescriptor = TargetMethodDescriptor<Runtime>;
  using VTableDescriptorHeader = TargetVTableDescriptorHeader<Runtime>;
  using OverrideTableHeader = TargetOverrideTableHeader<Runtime>;
  using MethodOverrideDescriptor = TargetMethodOverrideDescriptor<Runtime>;
  using ResilientSuperclass = TargetResilientSuperclass<Runtime>;
  using ForeignMetadataInitialization =
    TargetForeignMetadataInitialization<Runtime>;
  using SingletonMetadataInitialization =
    TargetSingletonMetadataInitialization<Runtime>;
  using ObjCResilientClassStubInfo =
    TargetObjCResilientClassStubInfo<Runtime>;
  using Metadata =
    TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>, /*Nullable*/ false>;
  using MetadataListCount =
    TargetCanonicalSpecializedMetadatasListCount<Runtime>;
  using MetadataListEntry = 
    TargetCanonicalSpecializedMetadatasListEntry<Runtime>;
  using MetadataAccessor = 
    TargetCompactFunctionPointer<Runtime, MetadataResponse(MetadataRequest), /*Nullable*/ false>;
  using MetadataAccessorListEntry =
      TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>;
  using MetadataCachingOnceToken =
      TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>;
  using SingletonMetadataPointer = TargetSingletonMetadataPointer<Runtime>;
  using DefaultOverrideTableHeader =
      TargetMethodDefaultOverrideTableHeader<Runtime>;
  using DefaultOverrideDescriptor =
      TargetMethodDefaultOverrideDescriptor<Runtime>;

  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<Runtime>::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<Runtime, const char> 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<Runtime,
                                TargetStoredClassMetadataBounds<Runtime>>
      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<typename T>
  using OverloadToken =
    typename TrailingGenericContextObjects::template OverloadToken<T>;
  
  using TrailingGenericContextObjects::numTrailingObjects;

  size_t numTrailingObjects(OverloadToken<ResilientSuperclass>) const {
    return this->hasResilientSuperclass() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<ForeignMetadataInitialization>) const{
    return this->hasForeignMetadataInitialization() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<SingletonMetadataInitialization>) const{
    return this->hasSingletonMetadataInitialization() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<VTableDescriptorHeader>) const {
    return hasVTable() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<MethodDescriptor>) const {
    if (!hasVTable())
      return 0;

    return getVTableDescriptor()->VTableSize;
  }

  size_t numTrailingObjects(OverloadToken<OverrideTableHeader>) const {
    return hasOverrideTable() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<MethodOverrideDescriptor>) const {
    if (!hasOverrideTable())
      return 0;

    return getOverrideTable()->NumEntries;
  }

  size_t numTrailingObjects(OverloadToken<ObjCResilientClassStubInfo>) const {
    return hasObjCResilientClassStub() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<MetadataListCount>) const {
    return this->hasCanonicalMetadataPrespecializations() ?
      1
      : 0;
  }

  size_t numTrailingObjects(OverloadToken<MetadataListEntry>) const {
    return this->hasCanonicalMetadataPrespecializations() ?
      this->template getTrailingObjects<MetadataListCount>()->count
      : 0;
  }

  size_t numTrailingObjects(OverloadToken<MetadataAccessorListEntry>) const {
    return this->hasCanonicalMetadataPrespecializations() ?
      this->template getTrailingObjects<MetadataListCount>()->count
      : 0;
  }

  size_t numTrailingObjects(OverloadToken<MetadataCachingOnceToken>) const {
    return this->hasCanonicalMetadataPrespecializations() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<SingletonMetadataPointer>) const {
    return this->hasSingletonMetadataPointer() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<DefaultOverrideTableHeader>) const {
    return hasDefaultOverrideTable() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<DefaultOverrideDescriptor>) const {
    if (!hasDefaultOverrideTable())
      return 0;
    return getDefaultOverrideTable()->NumEntries;
  }

public:
  const TargetRelativeDirectPointer<Runtime, const void, /*nullable*/true> &
  getResilientSuperclass() const {
    assert(this->hasResilientSuperclass());
    return this->template getTrailingObjects<ResilientSuperclass>()->Superclass;
  }

  const ForeignMetadataInitialization &getForeignMetadataInitialization() const{
    assert(this->hasForeignMetadataInitialization());
    return *this->template getTrailingObjects<ForeignMetadataInitialization>();
  }

  const SingletonMetadataInitialization &getSingletonMetadataInitialization() const{
    assert(this->hasSingletonMetadataInitialization());
    return *this->template getTrailingObjects<SingletonMetadataInitialization>();
  }

  /// 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 hasDefaultOverrideTable() const {
    return getTypeContextDescriptorFlags().class_hasDefaultOverrideTable();
  }

  bool isActor() const {
    return this->getTypeContextDescriptorFlags().class_isActor();
  }

  bool isDefaultActor() const {
    return this->getTypeContextDescriptorFlags().class_isDefaultActor();
  }

  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<VTableDescriptorHeader>();
  }

  llvm::ArrayRef<MethodDescriptor> getMethodDescriptors() const {
    if (!hasVTable())
      return {};
    return {this->template getTrailingObjects<MethodDescriptor>(),
            numTrailingObjects(OverloadToken<MethodDescriptor>{})};
  }

  const OverrideTableHeader *getOverrideTable() const {
    if (!hasOverrideTable())
      return nullptr;
    return this->template getTrailingObjects<OverrideTableHeader>();
  }

  llvm::ArrayRef<MethodOverrideDescriptor> getMethodOverrideDescriptors() const {
    if (!hasOverrideTable())
      return {};
    return {this->template getTrailingObjects<MethodOverrideDescriptor>(),
            numTrailingObjects(OverloadToken<MethodOverrideDescriptor>{})};
  }

  const DefaultOverrideTableHeader *getDefaultOverrideTable() const {
    if (!hasDefaultOverrideTable())
      return nullptr;
    return this->template getTrailingObjects<DefaultOverrideTableHeader>();
  }

  llvm::ArrayRef<DefaultOverrideDescriptor> getDefaultOverrideDescriptors()
      const {
    if (!hasDefaultOverrideTable())
      return {};
    return {this->template getTrailingObjects<DefaultOverrideDescriptor>(),
            numTrailingObjects(OverloadToken<DefaultOverrideDescriptor>{})};
  }

  /// Return the bounds of this class's metadata.
  TargetClassMetadataBounds<Runtime> 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<Runtime> 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<MethodDescriptor>{}));
    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<ObjCResilientClassStubInfo>()
      ->Stub.get();
  }

  llvm::ArrayRef<Metadata> getCanonicalMetadataPrespecializations() const {
    if (!this->hasCanonicalMetadataPrespecializations()) {
      return {};
    }

    auto *listCount = this->template getTrailingObjects<MetadataListCount>();
    auto *list = this->template getTrailingObjects<MetadataListEntry>();
    return llvm::ArrayRef<Metadata>(
        reinterpret_cast<const Metadata *>(list),
        listCount->count
        );
  }

  llvm::ArrayRef<MetadataAccessor> getCanonicalMetadataPrespecializationAccessors() const {
    if (!this->hasCanonicalMetadataPrespecializations()) {
      return {};
    }

    auto *listCount = this->template getTrailingObjects<MetadataListCount>();
    auto *list = this->template getTrailingObjects<MetadataAccessorListEntry>();
    return llvm::ArrayRef<MetadataAccessor>(
        reinterpret_cast<const MetadataAccessor *>(list),
        listCount->count
        );
  }

  swift_once_t *getCanonicalMetadataPrespecializationCachingOnceToken() const {
    if (!this->hasCanonicalMetadataPrespecializations()) {
      return nullptr;
    }
    auto box = this->template getTrailingObjects<MetadataCachingOnceToken>();
    return box->token.get();
  }

  TargetMetadata<Runtime> *getSingletonMetadata() const {
    if (!this->hasSingletonMetadataInitialization())
      return nullptr;

    auto box = this->template getTrailingObjects<SingletonMetadataPointer>();
    return box->token.get();
  }

  /// Retrieve the set of protocols that are inverted by this type's
  /// primary definition.
  ///
  /// This type might still conditionally conform to any of the protocols
  /// that are inverted here, but that information is recorded in the
  /// conditional inverted protocols of the corresponding `GenericContext`.
  const InvertibleProtocolSet &
  getInvertedProtocols() const {
    assert(this->hasInvertibleProtocols());
    return
      *this->template getTrailingObjects<InvertibleProtocolSet>();
  }

  size_t numTrailingObjects(OverloadToken<InvertibleProtocolSet>) const {
    return this->hasInvertibleProtocols() ? 1 : 0;
  }

  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
    return cd->getKind() == ContextDescriptorKind::Class;
  }
};

using ClassDescriptor = TargetClassDescriptor<InProcess>;

template <typename Runtime>
class swift_ptrauth_struct_context_descriptor(ValueTypeDescriptor)
    TargetValueTypeDescriptor : public TargetTypeContextDescriptor<Runtime>{
public:
  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
    return cd->getKind() == ContextDescriptorKind::Struct ||
           cd->getKind() == ContextDescriptorKind::Enum;
  }
};
using ValueTypeDescriptor = TargetValueTypeDescriptor<InProcess>;

template <typename Runtime>
class swift_ptrauth_struct_context_descriptor(StructDescriptor)
    TargetStructDescriptor final
    : public TargetValueTypeDescriptor<Runtime>,
      public TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
                            TargetTypeGenericContextDescriptorHeader,
                            /*additional trailing objects*/
                            TargetForeignMetadataInitialization<Runtime>,
                            TargetSingletonMetadataInitialization<Runtime>,
                            TargetCanonicalSpecializedMetadatasListCount<Runtime>,
                            TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
                            TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>,
                            InvertibleProtocolSet,
                            TargetSingletonMetadataPointer<Runtime>> {
public:
  using ForeignMetadataInitialization =
    TargetForeignMetadataInitialization<Runtime>;
  using SingletonMetadataInitialization =
    TargetSingletonMetadataInitialization<Runtime>;
  using Metadata =
    TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>, /*Nullable*/ false>;
  using MetadataListCount =
    TargetCanonicalSpecializedMetadatasListCount<Runtime>;
  using MetadataListEntry =
    TargetCanonicalSpecializedMetadatasListEntry<Runtime>;
  using MetadataCachingOnceToken =
      TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>;
  using SingletonMetadataPointer = TargetSingletonMetadataPointer<Runtime>;

private:
  using TrailingGenericContextObjects =
      swift::TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
                                           TargetTypeGenericContextDescriptorHeader,
                                           ForeignMetadataInitialization,
                                           SingletonMetadataInitialization,
                                           MetadataListCount,
                                           MetadataListEntry,
                                           MetadataCachingOnceToken,
                                           InvertibleProtocolSet,
                                           TargetSingletonMetadataPointer<Runtime>>;

  using TrailingObjects =
    typename TrailingGenericContextObjects::TrailingObjects;
  friend TrailingObjects;

  template<typename T>
  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
  using TrailingGenericContextObjects::numTrailingObjects;

  size_t numTrailingObjects(OverloadToken<ForeignMetadataInitialization>) const{
    return this->hasForeignMetadataInitialization() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<SingletonMetadataInitialization>) const{
    return this->hasSingletonMetadataInitialization() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<MetadataListCount>) const {
    return this->hasCanonicalMetadataPrespecializations() ?
      1
      : 0;
  }

  size_t numTrailingObjects(OverloadToken<MetadataListEntry>) const {
    return this->hasCanonicalMetadataPrespecializations() ?
      this->template getTrailingObjects<MetadataListCount>()->count
      : 0;
  }

  size_t numTrailingObjects(OverloadToken<MetadataCachingOnceToken>) const {
    return this->hasCanonicalMetadataPrespecializations() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<SingletonMetadataPointer>) const {
    return this->hasSingletonMetadataPointer() ? 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<ForeignMetadataInitialization>();
  }

  const SingletonMetadataInitialization &getSingletonMetadataInitialization() const{
    assert(this->hasSingletonMetadataInitialization());
    return *this->template getTrailingObjects<SingletonMetadataInitialization>();
  }

  static constexpr int32_t getGenericArgumentOffset() {
    return TargetStructMetadata<Runtime>::getGenericArgumentOffset();
  }

  llvm::ArrayRef<Metadata> getCanonicalMetadataPrespecializations() const {
    if (!this->hasCanonicalMetadataPrespecializations()) {
      return {};
    }

    auto *listCount = this->template getTrailingObjects<MetadataListCount>();
    auto *list = this->template getTrailingObjects<MetadataListEntry>();
    return llvm::ArrayRef<Metadata>(
        reinterpret_cast<const Metadata *>(list),
        listCount->count
        );
  }

  swift_once_t *getCanonicalMetadataPrespecializationCachingOnceToken() const {
    if (!this->hasCanonicalMetadataPrespecializations()) {
      return nullptr;
    }
    auto box = this->template getTrailingObjects<MetadataCachingOnceToken>();
    return box->token.get();
  }

  TargetMetadata<Runtime> *getSingletonMetadata() const {
    if (!this->hasSingletonMetadataInitialization())
      return nullptr;

    auto box = this->template getTrailingObjects<SingletonMetadataPointer>();
    return box->token.get();
  }

  /// Retrieve the set of protocols that are inverted by this type's
  /// primary definition.
  ///
  /// This type might still conditionally conform to any of the protocols
  /// that are inverted here, but that information is recorded in the
  /// conditional inverted protocols of the corresponding `GenericContext`.
  const InvertibleProtocolSet &
  getInvertedProtocols() const {
    assert(this->hasInvertibleProtocols());
    return
      *this->template getTrailingObjects<InvertibleProtocolSet>();
  }

  size_t numTrailingObjects(OverloadToken<InvertibleProtocolSet>) const {
    return this->hasInvertibleProtocols() ? 1 : 0;
  }

  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
    return cd->getKind() == ContextDescriptorKind::Struct;
  }
};

using StructDescriptor = TargetStructDescriptor<InProcess>;

template <typename Runtime>
class swift_ptrauth_struct_context_descriptor(EnumDescriptor)
    TargetEnumDescriptor final
    : public TargetValueTypeDescriptor<Runtime>,
      public TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
                            TargetTypeGenericContextDescriptorHeader,
                            /*additional trailing objects*/
                            TargetForeignMetadataInitialization<Runtime>,
                            TargetSingletonMetadataInitialization<Runtime>,
                            TargetCanonicalSpecializedMetadatasListCount<Runtime>,
                            TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
                            TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>,
                            InvertibleProtocolSet,
                            TargetSingletonMetadataPointer<Runtime>> {
public:
  using SingletonMetadataInitialization =
    TargetSingletonMetadataInitialization<Runtime>;
  using ForeignMetadataInitialization =
    TargetForeignMetadataInitialization<Runtime>;
  using Metadata =
    TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>, /*Nullable*/ false>;
  using MetadataListCount =
    TargetCanonicalSpecializedMetadatasListCount<Runtime>;
  using MetadataListEntry =
    TargetCanonicalSpecializedMetadatasListEntry<Runtime>;
  using MetadataCachingOnceToken =
      TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>;
  using SingletonMetadataPointer = TargetSingletonMetadataPointer<Runtime>;

private:
  using TrailingGenericContextObjects =
    swift::TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
                                        TargetTypeGenericContextDescriptorHeader,
                                        ForeignMetadataInitialization,
                                        SingletonMetadataInitialization,
                                        MetadataListCount,
                                        MetadataListEntry, 
                                        MetadataCachingOnceToken,
                                        InvertibleProtocolSet,
                                        TargetSingletonMetadataPointer<Runtime>>;

  using TrailingObjects =
    typename TrailingGenericContextObjects::TrailingObjects;
  friend TrailingObjects;

  template<typename T>
  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
  using TrailingGenericContextObjects::numTrailingObjects;

  size_t numTrailingObjects(OverloadToken<ForeignMetadataInitialization>) const{
    return this->hasForeignMetadataInitialization() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<SingletonMetadataInitialization>) const{
    return this->hasSingletonMetadataInitialization() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<MetadataListCount>) const {
    return this->hasCanonicalMetadataPrespecializations() ?
      1
      : 0;
  }

  size_t numTrailingObjects(OverloadToken<MetadataListEntry>) const {
    return this->hasCanonicalMetadataPrespecializations() ?
      this->template getTrailingObjects<MetadataListCount>()->count
      : 0;
  }

  size_t numTrailingObjects(OverloadToken<MetadataCachingOnceToken>) const {
    return this->hasCanonicalMetadataPrespecializations() ? 1 : 0;
  }

  size_t numTrailingObjects(OverloadToken<SingletonMetadataPointer>) const {
    return this->hasSingletonMetadataPointer() ? 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<Runtime>::getGenericArgumentOffset();
  }

  const ForeignMetadataInitialization &getForeignMetadataInitialization() const{
    assert(this->hasForeignMetadataInitialization());
    return *this->template getTrailingObjects<ForeignMetadataInitialization>();
  }

  const SingletonMetadataInitialization &getSingletonMetadataInitialization() const{
    assert(this->hasSingletonMetadataInitialization());
    return *this->template getTrailingObjects<SingletonMetadataInitialization>();
  }

  llvm::ArrayRef<Metadata> getCanonicalMetadataPrespecializations() const {
    if (!this->hasCanonicalMetadataPrespecializations()) {
      return {};
    }

    auto *listCount = this->template getTrailingObjects<MetadataListCount>();
    auto *list = this->template getTrailingObjects<MetadataListEntry>();
    return llvm::ArrayRef<Metadata>(
        reinterpret_cast<const Metadata *>(list),
        listCount->count
        );
  }

  swift_once_t *getCanonicalMetadataPrespecializationCachingOnceToken() const {
    if (!this->hasCanonicalMetadataPrespecializations()) {
      return nullptr;
    }
    auto box = this->template getTrailingObjects<MetadataCachingOnceToken>();
    return box->token.get();
  }

  TargetMetadata<Runtime> *getSingletonMetadata() const {
    if (!this->hasSingletonMetadataInitialization())
      return nullptr;

    auto box = this->template getTrailingObjects<SingletonMetadataPointer>();
    return box->token.get();
  }

  /// Retrieve the set of protocols that are inverted by this type's
  /// primary definition.
  ///
  /// This type might still conditionally conform to any of the protocols
  /// that are inverted here, but that information is recorded in the
  /// conditional inverted protocols of the corresponding `GenericContext`.
  const InvertibleProtocolSet &
  getInvertedProtocols() const {
    assert(this->hasInvertibleProtocols());
    return
      *this->template getTrailingObjects<InvertibleProtocolSet>();
  }
               
  size_t numTrailingObjects(OverloadToken<InvertibleProtocolSet>) const {
    return this->hasInvertibleProtocols() ? 1 : 0;
  }

  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
    return cd->getKind() == ContextDescriptorKind::Enum;
  }

#ifndef NDEBUG
  [[deprecated("Only meant for use in the debugger")]] void dump() const;
#endif
};

using EnumDescriptor = TargetEnumDescriptor<InProcess>;

template<typename Runtime>
inline const TargetGenericContext<Runtime> *
TargetContextDescriptor<Runtime>::getGenericContext() const {
  if (!isGeneric())
    return nullptr;

  switch (getKind()) {
  case ContextDescriptorKind::Module:
    // Never generic.
    return nullptr;
  case ContextDescriptorKind::Extension:
    return llvm::cast<TargetExtensionContextDescriptor<Runtime>>(this)
      ->getGenericContext();
  case ContextDescriptorKind::Anonymous:
    return llvm::cast<TargetAnonymousContextDescriptor<Runtime>>(this)
      ->getGenericContext();
  case ContextDescriptorKind::Class:
    return llvm::cast<TargetClassDescriptor<Runtime>>(this)
        ->getGenericContext();
  case ContextDescriptorKind::Enum:
    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
        ->getGenericContext();
  case ContextDescriptorKind::Struct:
    return llvm::cast<TargetStructDescriptor<Runtime>>(this)
        ->getGenericContext();
  case ContextDescriptorKind::OpaqueType:
    return llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)
        ->getGenericContext();
  default:    
    // We don't know about this kind of descriptor.
    return nullptr;
  }
}

template<typename Runtime>
inline const InvertibleProtocolSet *
TargetContextDescriptor<Runtime>::getInvertedProtocols() const {
  if (!this->hasInvertibleProtocols())
    return nullptr;

  switch (getKind()) {
  case ContextDescriptorKind::Class:
    return &llvm::cast<TargetClassDescriptor<Runtime>>(this)
        ->getInvertedProtocols();
  case ContextDescriptorKind::Enum:
    return &llvm::cast<TargetEnumDescriptor<Runtime>>(this)
        ->getInvertedProtocols();
  case ContextDescriptorKind::Struct:
    return &llvm::cast<TargetStructDescriptor<Runtime>>(this)
        ->getInvertedProtocols();
  case ContextDescriptorKind::OpaqueType:
    return &llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)
        ->getInvertedProtocols();
  default:
    // We don't know about this kind of descriptor.
    return nullptr;
  }
}

template <typename Runtime>
int32_t TargetTypeContextDescriptor<Runtime>::getGenericArgumentOffset() const {
  switch (this->getKind()) {
  case ContextDescriptorKind::Class:
    return llvm::cast<TargetClassDescriptor<Runtime>>(this)
        ->getGenericArgumentOffset();
  case ContextDescriptorKind::Enum:
    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
        ->getGenericArgumentOffset();
  case ContextDescriptorKind::Struct:
    return llvm::cast<TargetStructDescriptor<Runtime>>(this)
        ->getGenericArgumentOffset();
  default:
    swift_unreachable("Not a type context descriptor.");
  }
}

template <typename Runtime>
const TargetTypeGenericContextDescriptorHeader<Runtime> &
TargetTypeContextDescriptor<Runtime>::getFullGenericContextHeader() const {
  switch (this->getKind()) {
  case ContextDescriptorKind::Class:
    return llvm::cast<TargetClassDescriptor<Runtime>>(this)
        ->getFullGenericContextHeader();
  case ContextDescriptorKind::Enum:
    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
        ->getFullGenericContextHeader();
  case ContextDescriptorKind::Struct:
    return llvm::cast<TargetStructDescriptor<Runtime>>(this)
        ->getFullGenericContextHeader();
  default:
    swift_unreachable("Not a type context descriptor.");
  }
}

template <typename Runtime>
llvm::ArrayRef<GenericParamDescriptor> 
TargetTypeContextDescriptor<Runtime>::getGenericParams() const {
  switch (this->getKind()) {
  case ContextDescriptorKind::Class:
    return llvm::cast<TargetClassDescriptor<Runtime>>(this)->getGenericParams();
  case ContextDescriptorKind::Enum:
    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)->getGenericParams();
  case ContextDescriptorKind::Struct:
    return llvm::cast<TargetStructDescriptor<Runtime>>(this)->getGenericParams();
  case ContextDescriptorKind::OpaqueType:
    return llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)->getGenericParams();
  default:
    swift_unreachable("Not a type context descriptor.");
  }
}

template <typename Runtime>
const TargetForeignMetadataInitialization<Runtime> &
TargetTypeContextDescriptor<Runtime>::getForeignMetadataInitialization() const {
  switch (this->getKind()) {
  case ContextDescriptorKind::Class:
    return llvm::cast<TargetClassDescriptor<Runtime>>(this)
        ->getForeignMetadataInitialization();
  case ContextDescriptorKind::Enum:
    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
        ->getForeignMetadataInitialization();
  case ContextDescriptorKind::Struct:
    return llvm::cast<TargetStructDescriptor<Runtime>>(this)
        ->getForeignMetadataInitialization();
  default:
    swift_unreachable("Not a type context descriptor.");
  }
}

template<typename Runtime>
inline const TargetSingletonMetadataInitialization<Runtime> &
TargetTypeContextDescriptor<Runtime>::getSingletonMetadataInitialization() const {
  switch (this->getKind()) {
  case ContextDescriptorKind::Enum:
    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
        ->getSingletonMetadataInitialization();
  case ContextDescriptorKind::Struct:
    return llvm::cast<TargetStructDescriptor<Runtime>>(this)
        ->getSingletonMetadataInitialization();
  case ContextDescriptorKind::Class:
    return llvm::cast<TargetClassDescriptor<Runtime>>(this)
        ->getSingletonMetadataInitialization();
  default:
    swift_unreachable("Not a enum, struct or class type descriptor.");
  }
}

template<typename Runtime>
inline const llvm::ArrayRef<TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>, /*Nullable*/ false>>
TargetTypeContextDescriptor<Runtime>::getCanonicalMetadataPrespecializations() const {
  switch (this->getKind()) {
  case ContextDescriptorKind::Enum:
    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
        ->getCanonicalMetadataPrespecializations();
  case ContextDescriptorKind::Struct:
    return llvm::cast<TargetStructDescriptor<Runtime>>(this)
        ->getCanonicalMetadataPrespecializations();
  case ContextDescriptorKind::Class:
    return llvm::cast<TargetClassDescriptor<Runtime>>(this)
        ->getCanonicalMetadataPrespecializations();
  default:
    swift_unreachable("Not a type context descriptor.");
  }
}

template <typename Runtime>
inline swift_once_t *TargetTypeContextDescriptor<
    Runtime>::getCanonicalMetadataPrespecializationCachingOnceToken() const {
  switch (this->getKind()) {
  case ContextDescriptorKind::Enum:
    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
        ->getCanonicalMetadataPrespecializationCachingOnceToken();
  case ContextDescriptorKind::Struct:
    return llvm::cast<TargetStructDescriptor<Runtime>>(this)
        ->getCanonicalMetadataPrespecializationCachingOnceToken();
  case ContextDescriptorKind::Class:
    return llvm::cast<TargetClassDescriptor<Runtime>>(this)
        ->getCanonicalMetadataPrespecializationCachingOnceToken();
  default:
    swift_unreachable("Not a type context 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<DynamicReplacementChainEntry, false> root;
  uint32_t flags;

  uint16_t getExtraDiscriminator() const {
    return flags & 0x0000FFFF;
  }
  bool isAsync() const { return ((flags >> 16) & 0x1); }
  bool isCalleeAllocatedCoroutine() const { return ((flags >> 16) & 0x2); }
  bool isData() const { return isAsync() || isCalleeAllocatedCoroutine(); }
};

/// A record describing a dynamic function replacement.
class DynamicReplacementDescriptor {
  RelativeIndirectablePointer<
      const DynamicReplacementKey, false, int32_t,
      TargetSignedPointer<InProcess,
                          DynamicReplacementKey *
                              __ptrauth_swift_dynamic_replacement_key>>
      replacedFunctionKey;
  union {
    TargetCompactFunctionPointer<InProcess, void, false> replacementFunction;
    TargetRelativeDirectPointer<InProcess, void, false> replacementAsyncFunction;
    TargetRelativeDirectPointer<InProcess, void, false> replacementCoroFunction;
  };
  RelativeDirectPointer<DynamicReplacementChainEntry, false> chainEntry;
  uint32_t flags;

  enum : uint32_t { EnableChainingMask = 0x1 };

  void *getReplacementFunction() const {
    if (replacedFunctionKey->isAsync()) {
      return replacementAsyncFunction.get();
    } else if (replacedFunctionKey->isCalleeAllocatedCoroutine()) {
      return replacementCoroFunction.get();
    } else {
      return replacementFunction.get();
    }
  }

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<DynamicReplacementScope,
                                          DynamicReplacementDescriptor> {

  uint32_t flags;
  uint32_t numReplacements;

  using TrailingObjects =
      swift::ABI::TrailingObjects<DynamicReplacementScope,
                                  DynamicReplacementDescriptor>;
  friend TrailingObjects;

  llvm::ArrayRef<DynamicReplacementDescriptor>
  getReplacementDescriptors() const {
    return {this->template getTrailingObjects<DynamicReplacementDescriptor>(),
            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; }
};

/// An "accessible" function that can be looked up based on a string key,
/// and then called through a fully-abstracted entry point whose arguments
/// can be constructed in code.
template <typename Runtime>
struct TargetAccessibleFunctionRecord {
public:
  /// The name of the function, which is a unique string assigned to the
  /// function so it can be looked up later.
  RelativeDirectPointer<const char, /*nullable*/ false> Name;

  /// The generic environment associated with this accessor function.
  RelativeDirectPointer<GenericEnvironmentDescriptor, /*nullable*/ true>
      GenericEnvironment;

  /// The Swift function type, encoded as a mangled name.
  RelativeDirectPointer<const char, /*nullable*/ false> FunctionType;

  /// The fully-abstracted function to call.
  ///
  /// Could be a sync or async function pointer depending on flags.
  RelativeDirectPointer<void *, /*nullable*/ false> Function;

  /// Flags providing more information about the function.
  AccessibleFunctionFlags Flags;
};

using AccessibleFunctionRecord = TargetAccessibleFunctionRecord<InProcess>;

enum class PackLifetime : uint8_t {
  OnStack = 0,
  OnHeap = 1
};

/// A pointer to a metadata or witness table pack. If the LSB is set,
/// the pack is allocated on the heap; otherwise, it is allocated on
/// the stack.
template<typename Runtime, template <typename> class Pointee>
class TargetPackPointer {
  typename Runtime::StoredSize Ptr;

  using PointerType = typename Runtime::template Pointer<const Pointee<Runtime>>;

public:
  explicit TargetPackPointer() : Ptr(0) {}

  explicit TargetPackPointer(typename Runtime::StoredSize rawPtr) : Ptr(rawPtr) {}

  explicit TargetPackPointer(const void *rawPtr)
    : Ptr(reinterpret_cast<typename Runtime::StoredSize>(rawPtr)) {}

  explicit TargetPackPointer(PointerType const *ptr, PackLifetime lifetime)
    : Ptr(reinterpret_cast<typename Runtime::StoredSize>(ptr) |
          (lifetime == PackLifetime::OnHeap ? 1 : 0)) {}

  explicit operator bool() const {
    return Ptr != 0;
  }

  // Strips off the LSB.
  const PointerType *getElements() const {
    return reinterpret_cast<const PointerType *>(Ptr & ~1);
  }

  // Strips off the LSB.
  PointerType *getElements() {
    return reinterpret_cast<PointerType *>(Ptr & ~1);
  }

  // Leaves the LSB.
  const PointerType *getPointer() const {
    return reinterpret_cast<const PointerType *>(Ptr);
  }

  PackLifetime getLifetime() const {
    return (bool)(Ptr & 1) ? PackLifetime::OnHeap : PackLifetime::OnStack;
  }

  // Get the number of elements in the pack, only valid for on-heap packs.
  size_t getNumElements() const {
    if (getLifetime() == PackLifetime::OnHeap)
      return *(reinterpret_cast<const size_t *>(Ptr & ~1) - 1);

    fatalError(0, "Cannot get length of on-stack pack");
  }
};

/// A pointer to a metadata pack.
template<typename Runtime>
using TargetMetadataPackPointer = TargetPackPointer<Runtime, TargetMetadata>;

using MetadataPackPointer = TargetMetadataPackPointer<InProcess>;

/// A pointer to a witness table pack.
template<typename Runtime>
using TargetWitnessTablePackPointer = TargetPackPointer<Runtime, TargetWitnessTable>;

using WitnessTablePackPointer = TargetWitnessTablePackPointer<InProcess>;

} // end namespace swift

#pragma clang diagnostic pop

#endif // SWIFT_ABI_METADATA_H
