Skip to content
Permalink
main
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
945 lines (819 sloc) 37.3 KB
//===--- 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 runtime support for generating and uniquing metadata.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_RUNTIME_METADATA_H
#define SWIFT_RUNTIME_METADATA_H
#include "swift/ABI/Metadata.h"
#include "swift/Reflection/Records.h"
#include "swift/Runtime/Once.h"
namespace swift {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
// Tags used to denote different kinds of allocations made with the metadata
// allocator. This is encoded in a header on each allocation when metadata
// iteration is enabled, and allows tools to know where each allocation came
// from.
enum MetadataAllocatorTags : uint16_t {
#define TAG(name, value) name##Tag = value,
#include "../../../stdlib/public/runtime/MetadataAllocatorTags.def"
};
template <typename Runtime> struct MetadataAllocationBacktraceHeader {
TargetPointer<Runtime, const void> Next;
TargetPointer<Runtime, void> Allocation;
uint32_t Count;
// Count backtrace pointers immediately follow.
};
/// The buffer used by a yield-once coroutine (such as the generalized
/// accessors `read` and `modify`).
struct YieldOnceBuffer {
void *Data[NumWords_YieldOnceBuffer];
};
using YieldOnceContinuation =
SWIFT_CC(swift) void (YieldOnceBuffer *buffer, bool forUnwind);
/// The return type of a call to a yield-once coroutine. The function
/// must be declared with the swiftcall calling convention.
template <class ResultTy>
struct YieldOnceResult {
YieldOnceContinuation *Continuation;
ResultTy YieldValue;
};
template <class FnTy>
struct YieldOnceCoroutine;
/// A template which generates the type of the ramp function of a
/// yield-once coroutine.
template <class ResultTy, class... ArgTys>
struct YieldOnceCoroutine<ResultTy(ArgTys...)> {
using type =
SWIFT_CC(swift) YieldOnceResult<ResultTy> (YieldOnceBuffer *buffer,
ArgTys...);
};
#if SWIFT_OBJC_INTEROP
// Const cast shorthands for ObjC types.
/// Cast to id, discarding const if necessary.
template <typename T>
static inline id id_const_cast(const T* value) {
return reinterpret_cast<id>(const_cast<T*>(value));
}
/// Cast to Class, discarding const if necessary.
template <typename T>
static inline Class class_const_cast(const T* value) {
return reinterpret_cast<Class>(const_cast<T*>(value));
}
/// Cast to Protocol*, discarding const if necessary.
template <typename T>
static inline Protocol* protocol_const_cast(const T* value) {
return reinterpret_cast<Protocol *>(const_cast<T*>(value));
}
/// Cast from a CF type, discarding const if necessary.
template <typename T>
static inline T cf_const_cast(const void* value) {
return reinterpret_cast<T>(const_cast<void *>(value));
}
#endif
/// A standard routine, suitable for placement in the value witness
/// table, for copying an opaque POD object.
SWIFT_RUNTIME_EXPORT
OpaqueValue *swift_copyPOD(OpaqueValue *dest,
OpaqueValue *src,
const Metadata *self);
/// A value-witness table with enum entry points.
/// These entry points are available only if the HasEnumWitnesses flag bit is
/// set in the 'flags' field.
struct EnumValueWitnessTable : ValueWitnessTable {
#define WANT_ONLY_ENUM_VALUE_WITNESSES
#define VALUE_WITNESS(LOWER_ID, UPPER_ID) \
ValueWitnessTypes::LOWER_ID LOWER_ID;
#define FUNCTION_VALUE_WITNESS(LOWER_ID, UPPER_ID, RET, PARAMS) \
ValueWitnessTypes::LOWER_ID LOWER_ID;
#include "swift/ABI/ValueWitness.def"
constexpr EnumValueWitnessTable()
: ValueWitnessTable{},
getEnumTag(nullptr),
destructiveProjectEnumData(nullptr),
destructiveInjectEnumTag(nullptr) {}
constexpr EnumValueWitnessTable(
const ValueWitnessTable &base,
ValueWitnessTypes::getEnumTagUnsigned getEnumTag,
ValueWitnessTypes::destructiveProjectEnumDataUnsigned
destructiveProjectEnumData,
ValueWitnessTypes::destructiveInjectEnumTagUnsigned
destructiveInjectEnumTag)
: ValueWitnessTable(base),
getEnumTag(getEnumTag),
destructiveProjectEnumData(destructiveProjectEnumData),
destructiveInjectEnumTag(destructiveInjectEnumTag) {}
static bool classof(const ValueWitnessTable *table) {
return table->flags.hasEnumWitnesses();
}
};
/// A type layout record. This is the subset of the value witness table that is
/// necessary to perform dependent layout of generic value types. It excludes
/// the value witness functions and includes only the size, alignment,
/// extra inhabitants, and miscellaneous flags about the type.
struct TypeLayout {
ValueWitnessTypes::size size;
ValueWitnessTypes::stride stride;
ValueWitnessTypes::flags flags;
ValueWitnessTypes::extraInhabitantCount extraInhabitantCount;
private:
void _static_assert_layout();
public:
TypeLayout() = default;
constexpr TypeLayout(ValueWitnessTypes::size size,
ValueWitnessTypes::stride stride,
ValueWitnessTypes::flags flags,
ValueWitnessTypes::extraInhabitantCount xiCount)
: size(size), stride(stride), flags(flags), extraInhabitantCount(xiCount) {}
const TypeLayout *getTypeLayout() const { return this; }
/// The number of extra inhabitants, that is, bit patterns that do not form
/// valid values of the type, in this type's binary representation.
unsigned getNumExtraInhabitants() const {
return extraInhabitantCount;
}
bool hasExtraInhabitants() const {
return extraInhabitantCount != 0;
}
};
inline void TypeLayout::_static_assert_layout() {
#define CHECK_TYPE_LAYOUT_OFFSET(FIELD) \
static_assert(offsetof(ValueWitnessTable, FIELD) \
- offsetof(ValueWitnessTable, size) \
== offsetof(TypeLayout, FIELD), \
"layout of " #FIELD " in TypeLayout doesn't match " \
"value witness table")
CHECK_TYPE_LAYOUT_OFFSET(size);
CHECK_TYPE_LAYOUT_OFFSET(flags);
CHECK_TYPE_LAYOUT_OFFSET(extraInhabitantCount);
CHECK_TYPE_LAYOUT_OFFSET(stride);
#undef CHECK_TYPE_LAYOUT_OFFSET
}
template <>
inline void ValueWitnessTable::publishLayout(const TypeLayout &layout) {
size = layout.size;
stride = layout.stride;
extraInhabitantCount = layout.extraInhabitantCount;
// Currently there is nothing in the runtime or ABI which tries to
// asynchronously check completion, so we can just do a normal store here.
//
// If we decide to start allowing that (to speed up checkMetadataState,
// maybe), we'll have to:
// - turn this into an store-release,
// - turn the load in checkIsComplete() into a load-acquire, and
// - do something about getMutableVWTableForInit.
flags = layout.flags;
}
template <> inline bool ValueWitnessTable::checkIsComplete() const {
return !flags.isIncomplete();
}
template <>
inline const EnumValueWitnessTable *ValueWitnessTable::_asEVWT() const {
assert(EnumValueWitnessTable::classof(this));
return static_cast<const EnumValueWitnessTable *>(this);
}
// Standard value-witness tables.
#define BUILTIN_TYPE(Symbol, _) \
SWIFT_RUNTIME_EXPORT const ValueWitnessTable VALUE_WITNESS_SYM(Symbol);
#define BUILTIN_POINTER_TYPE(Symbol, _) \
SWIFT_RUNTIME_EXPORT const ValueWitnessTable VALUE_WITNESS_SYM(Symbol);
#include "swift/Runtime/BuiltinTypes.def"
// The () -> () table can be used for arbitrary function types.
SWIFT_RUNTIME_EXPORT
const ValueWitnessTable
VALUE_WITNESS_SYM(FUNCTION_MANGLING); // () -> ()
// The @escaping () -> () table can be used for arbitrary escaping function types.
SWIFT_RUNTIME_EXPORT
const ValueWitnessTable
VALUE_WITNESS_SYM(NOESCAPE_FUNCTION_MANGLING); // @noescape () -> ()
// The @convention(thin) () -> () table can be used for arbitrary thin function types.
SWIFT_RUNTIME_EXPORT
const ValueWitnessTable
VALUE_WITNESS_SYM(THIN_FUNCTION_MANGLING); // @convention(thin) () -> ()
// The () table can be used for arbitrary empty types.
SWIFT_RUNTIME_EXPORT
const ValueWitnessTable VALUE_WITNESS_SYM(EMPTY_TUPLE_MANGLING); // ()
// The table for aligned-pointer-to-pointer types.
SWIFT_RUNTIME_EXPORT
const ValueWitnessTable METATYPE_VALUE_WITNESS_SYM(Bo); // Builtin.NativeObject.Type
/// Return the value witnesses for unmanaged pointers.
static inline const ValueWitnessTable &getUnmanagedPointerValueWitnesses() {
#if __POINTER_WIDTH__ == 64
return VALUE_WITNESS_SYM(Bi64_);
#else
return VALUE_WITNESS_SYM(Bi32_);
#endif
}
/// Return value witnesses for a pointer-aligned pointer type.
static inline
const ValueWitnessTable &
getUnmanagedPointerPointerValueWitnesses() {
return METATYPE_VALUE_WITNESS_SYM(Bo);
}
using OpaqueMetadata = TargetOpaqueMetadata<InProcess>;
// Standard POD opaque metadata.
// The "Int" metadata are used for arbitrary POD data with the
// matching characteristics.
using FullOpaqueMetadata = FullMetadata<OpaqueMetadata>;
#define BUILTIN_TYPE(Symbol, Name) \
SWIFT_RUNTIME_EXPORT \
const FullOpaqueMetadata METADATA_SYM(Symbol);
#include "swift/Runtime/BuiltinTypes.def"
/// The standard metadata for the empty tuple type.
SWIFT_RUNTIME_EXPORT
const
FullMetadata<TupleTypeMetadata> METADATA_SYM(EMPTY_TUPLE_MANGLING);
/// The standard metadata for the empty protocol composition type, Any.
SWIFT_RUNTIME_EXPORT
const
FullMetadata<ExistentialTypeMetadata> METADATA_SYM(ANY_MANGLING);
/// The standard metadata for the empty class-constrained protocol composition
/// type, AnyObject.
SWIFT_RUNTIME_EXPORT
const
FullMetadata<ExistentialTypeMetadata> METADATA_SYM(ANYOBJECT_MANGLING);
/// True if two context descriptors in the currently running program describe
/// the same context.
bool equalContexts(const ContextDescriptor *a, const ContextDescriptor *b);
/// Determines whether two type context descriptors describe the same type
/// context.
///
/// Runtime availability: Swift 5.4.
///
/// \param lhs The first type context descriptor to compare.
/// \param rhs The second type context descriptor to compare.
///
/// \returns true if both describe the same type context, false otherwise.
SWIFT_RUNTIME_EXPORT
SWIFT_CC(swift)
bool swift_compareTypeContextDescriptors(const TypeContextDescriptor *lhs,
const TypeContextDescriptor *rhs);
/// Compute the bounds of class metadata with a resilient superclass.
ClassMetadataBounds getResilientMetadataBounds(
const ClassDescriptor *descriptor);
int32_t getResilientImmediateMembersOffset(const ClassDescriptor *descriptor);
/// Fetch a uniqued metadata object for a nominal type which requires
/// singleton metadata initialization.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
MetadataResponse
swift_getSingletonMetadata(MetadataRequest request,
const TypeContextDescriptor *description);
/// Fetch a uniqued metadata object for the generic nominal type described by
/// the provided candidate metadata, using that candidate metadata if there is
/// not already a canonical metadata.
///
/// Runtime availability: Swift 5.4
///
/// \param candidate A prespecialized metadata record for a type which is not
/// statically made to be canonical which will be canonicalized
/// if no other canonical metadata exists for the type.
/// \param cache A pointer to a cache which will be set to the canonical
/// metadata record for the type described by the candidate
/// metadata record. If the cache has already been populated, its
/// contents will be returned.
/// \returns The canonical metadata for the specialized generic type described
/// by the provided candidate metadata.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift) MetadataResponse
swift_getCanonicalSpecializedMetadata(MetadataRequest request,
const Metadata *candidate,
const Metadata **cache);
/// Fetch a uniqued metadata object for the generic nominal type described by
/// the provided description and arguments, adding the canonical
/// prespecializations attached to the type descriptor to the metadata cache on
/// first run.
///
/// In contrast to swift_getGenericMetadata, this function is for use by
/// metadata accessors for which canonical generic metadata has been specialized
/// at compile time.
///
/// Runtime availability: Swift 5.4
///
/// \param request A specification of the metadata to be returned.
/// \param arguments The generic arguments--metadata and witness tables--which
/// the returned metadata is to have been instantiated with.
/// \param description The type descriptor for the generic type whose
/// generic metadata is to have been instantiated.
/// \param token The token that ensures that prespecialized records are added to
/// the metadata cache only once.
/// \returns The canonical metadata for the specialized generic type described
/// by the provided candidate metadata.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift) MetadataResponse
swift_getCanonicalPrespecializedGenericMetadata(
MetadataRequest request, const void *const *arguments,
const TypeContextDescriptor *description, swift_once_t *token);
/// Fetch a uniqued metadata object for a generic nominal type.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
MetadataResponse
swift_getGenericMetadata(MetadataRequest request,
const void * const *arguments,
const TypeContextDescriptor *description);
/// Allocate a generic class metadata object. This is intended to be
/// called by the metadata instantiation function of a generic class.
///
/// This function:
/// - computes the required size of the metadata object based on the
/// class hierarchy;
/// - allocates memory for the metadata object based on the computed
/// size and the additional requirements imposed by the pattern;
/// - copies information from the pattern into the allocated metadata; and
/// - fully initializes the ClassMetadata header, except that the
/// superclass pointer will be null (or SwiftObject under ObjC interop
/// if there is no formal superclass).
///
/// The instantiation function is responsible for completing the
/// initialization, including:
/// - setting the superclass pointer;
/// - copying class data from the superclass;
/// - installing the generic arguments;
/// - installing new v-table entries and overrides; and
/// - registering the class with the runtime under ObjC interop.
/// Most of this work can be achieved by calling swift_initClassMetadata.
SWIFT_RUNTIME_EXPORT
ClassMetadata *
swift_allocateGenericClassMetadata(const ClassDescriptor *description,
const void *arguments,
const GenericClassMetadataPattern *pattern);
/// Allocate a generic value metadata object. This is intended to be
/// called by the metadata instantiation function of a generic struct or
/// enum.
SWIFT_RUNTIME_EXPORT
ValueMetadata *
swift_allocateGenericValueMetadata(const ValueTypeDescriptor *description,
const void *arguments,
const GenericValueMetadataPattern *pattern,
size_t extraDataSize);
/// Check that the given metadata has the right state.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
MetadataResponse swift_checkMetadataState(MetadataRequest request,
const Metadata *type);
/// Retrieve a witness table based on a given conformance.
///
/// \param conformance - The protocol conformance descriptor, which
/// contains any information required to form the witness table.
///
/// \param type - The conforming type, used to form a uniquing key
/// for the conformance.
///
/// \param instantiationArgs - An opaque pointer that's forwarded to
/// the instantiation function, used for conditional conformances.
/// This API implicitly embeds an assumption that these arguments
/// never form part of the uniquing key for the conformance, which
/// is ultimately a statement about the user model of overlapping
/// conformances.
SWIFT_RUNTIME_EXPORT
const WitnessTable *
swift_getWitnessTable(const ProtocolConformanceDescriptor *conformance,
const Metadata *type,
const void * const *instantiationArgs);
/// Retrieve an associated type witness from the given witness table.
///
/// \param wtable The witness table.
/// \param conformingType Metadata for the conforming type.
/// \param reqBase "Base" requirement used to compute the witness index
/// \param assocType Associated type descriptor.
///
/// \returns metadata for the associated type witness.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
MetadataResponse swift_getAssociatedTypeWitness(
MetadataRequest request,
WitnessTable *wtable,
const Metadata *conformingType,
const ProtocolRequirement *reqBase,
const ProtocolRequirement *assocType);
/// Retrieve an associated conformance witness table from the given witness
/// table.
///
/// \param wtable The witness table.
/// \param conformingType Metadata for the conforming type.
/// \param assocType Metadata for the associated type.
/// \param reqBase "Base" requirement used to compute the witness index
/// \param assocConformance Associated conformance descriptor.
///
/// \returns corresponding witness table.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
const WitnessTable *swift_getAssociatedConformanceWitness(
WitnessTable *wtable,
const Metadata *conformingType,
const Metadata *assocType,
const ProtocolRequirement *reqBase,
const ProtocolRequirement *assocConformance);
/// Determine whether two protocol conformance descriptors describe the same
/// conformance of a type to a protocol.
///
/// Runtime availability: Swift 5.4
///
/// \param lhs The first protocol conformance descriptor to compare.
/// \param rhs The second protocol conformance descriptor to compare.
///
/// \returns true if both describe the same conformance, false otherwise.
SWIFT_RUNTIME_EXPORT
SWIFT_CC(swift)
bool swift_compareProtocolConformanceDescriptors(
const ProtocolConformanceDescriptor *lhs,
const ProtocolConformanceDescriptor *rhs);
/// Fetch a uniqued metadata for a function type.
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata(FunctionTypeFlags flags,
const Metadata *const *parameters,
const uint32_t *parameterFlags,
const Metadata *result);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata0(FunctionTypeFlags flags,
const Metadata *result);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata1(FunctionTypeFlags flags,
const Metadata *arg0,
const Metadata *result);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata2(FunctionTypeFlags flags,
const Metadata *arg0,
const Metadata *arg1,
const Metadata *result);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *swift_getFunctionTypeMetadata3(
FunctionTypeFlags flags,
const Metadata *arg0,
const Metadata *arg1,
const Metadata *arg2,
const Metadata *result);
#if SWIFT_OBJC_INTEROP
SWIFT_RUNTIME_EXPORT
void
swift_instantiateObjCClass(const ClassMetadata *theClass);
SWIFT_RUNTIME_EXPORT
Class
swift_getInitializedObjCClass(Class c);
/// Fetch a uniqued type metadata for an ObjC class.
SWIFT_RUNTIME_EXPORT
const Metadata *
swift_getObjCClassMetadata(const ClassMetadata *theClass);
/// Get the ObjC class object from class type metadata.
SWIFT_RUNTIME_EXPORT
const ClassMetadata *
swift_getObjCClassFromMetadata(const Metadata *theClass);
// Get the ObjC class object from class type metadata,
// or nullptr if the type isn't an ObjC class.
const ClassMetadata *
swift_getObjCClassFromMetadataConditional(const Metadata *theClass);
SWIFT_RUNTIME_EXPORT
const ClassMetadata *
swift_getObjCClassFromObject(HeapObject *object);
#endif
/// Fetch a unique type metadata object for a foreign type.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
MetadataResponse
swift_getForeignTypeMetadata(MetadataRequest request,
ForeignTypeMetadata *nonUnique);
/// Fetch a uniqued metadata for a tuple type.
///
/// The labels argument is null if and only if there are no element
/// labels in the tuple. Otherwise, it is a null-terminated
/// concatenation of space-terminated NFC-normalized UTF-8 strings,
/// assumed to point to constant global memory.
///
/// That is, for the tuple type (a : Int, Int, c : Int), this
/// argument should be:
/// "a c \0"
///
/// This representation allows label strings to be efficiently
/// (1) uniqued within a linkage unit and (2) compared with strcmp.
/// In other words, it's optimized for code size and uniquing
/// efficiency, not for the convenience of actually consuming
/// these strings.
///
/// \param elements - potentially invalid if numElements is zero;
/// otherwise, an array of metadata pointers.
/// \param labels - the labels string
/// \param proposedWitnesses - an optional proposed set of value witnesses.
/// This is useful when working with a non-dependent tuple type
/// where the entrypoint is just being used to unique the metadata.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
MetadataResponse
swift_getTupleTypeMetadata(MetadataRequest request,
TupleTypeFlags flags,
const Metadata * const *elements,
const char *labels,
const ValueWitnessTable *proposedWitnesses);
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
MetadataResponse
swift_getTupleTypeMetadata2(MetadataRequest request,
const Metadata *elt0, const Metadata *elt1,
const char *labels,
const ValueWitnessTable *proposedWitnesses);
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
MetadataResponse
swift_getTupleTypeMetadata3(MetadataRequest request,
const Metadata *elt0, const Metadata *elt1,
const Metadata *elt2, const char *labels,
const ValueWitnessTable *proposedWitnesses);
/// Perform layout as if for a tuple whose elements have the given layouts.
///
/// \param tupleLayout - A structure into which to write the tuple layout.
/// Must be non-null.
/// \param elementOffsets - An array into which to write the offsets of
/// the elements. May be null. Must have space for all elements,
/// including element 0 (which will always have offset 0).
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
void swift_getTupleTypeLayout(TypeLayout *tupleLayout,
uint32_t *elementOffsets,
TupleTypeFlags flags,
const TypeLayout * const *elements);
/// Perform layout as if for a two-element tuple whose elements have
/// the given layouts.
///
/// \param tupleLayout - A structure into which to write the tuple layout.
/// Must be non-null.
/// \returns The offset of the second element.
/// The first element always has offset 0.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
size_t swift_getTupleTypeLayout2(TypeLayout *tupleLayout,
const TypeLayout *elt0,
const TypeLayout *elt1);
struct OffsetPair { size_t First; size_t Second; };
/// Perform layout as if for a three-element tuple whose elements have
/// the given layouts.
///
/// \param tupleLayout - A structure into which to write the tuple layout.
/// Must be non-null.
/// \returns The offsets of the second and third elements.
/// The first element always has offset 0.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
OffsetPair swift_getTupleTypeLayout3(TypeLayout *tupleLayout,
const TypeLayout *elt0Layout,
const TypeLayout *elt1Layout,
const TypeLayout *elt2Layout);
/// Initialize the value witness table and struct field offset vector for a
/// struct, using the "Universal" layout strategy.
SWIFT_RUNTIME_EXPORT
void swift_initStructMetadata(StructMetadata *self,
StructLayoutFlags flags,
size_t numFields,
const TypeLayout * const *fieldTypes,
uint32_t *fieldOffsets);
/// Allocate the metadata for a class and copy fields from the given pattern.
/// The final size of the metadata is calculated at runtime from the metadata
/// bounds in the class descriptor.
///
/// This function is only intended to be called from the relocation function
/// of a resilient class pattern.
///
/// The metadata completion function must complete the metadata by calling
/// swift_initClassMetadata().
SWIFT_RUNTIME_EXPORT
ClassMetadata *
swift_relocateClassMetadata(const ClassDescriptor *descriptor,
const ResilientClassMetadataPattern *pattern);
/// Initialize various fields of the class metadata.
///
/// Namely:
/// - The superclass field is set to \p super.
/// - If the class metadata was allocated at runtime, copies the
/// vtable entries from the superclass and installs the class's
/// own vtable entries and overrides of superclass vtable entries.
/// - Copies the field offsets and generic parameters and conformances
/// from the superclass.
/// - Initializes the field offsets using the runtime type layouts
/// passed in \p fieldTypes.
///
/// This initialization pattern in the following cases:
/// - The class has generic ancestry, or resiliently-sized fields.
/// In this case the metadata was emitted statically but is incomplete,
/// because, the superclass field, generic parameters and conformances,
/// and field offset vector entries require runtime completion.
///
/// - The class is not generic, and has resilient ancestry.
/// In this case the class metadata was allocated from a resilient
/// class metadata pattern by swift_relocateClassMetadata().
///
/// - The class is generic.
/// In this case the class metadata was allocated from a generic
/// class metadata pattern by swift_allocateGenericClassMetadata().
SWIFT_RUNTIME_EXPORT
void swift_initClassMetadata(ClassMetadata *self,
ClassLayoutFlags flags,
size_t numFields,
const TypeLayout * const *fieldTypes,
size_t *fieldOffsets);
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
MetadataDependency
swift_initClassMetadata2(ClassMetadata *self,
ClassLayoutFlags flags,
size_t numFields,
const TypeLayout * const *fieldTypes,
size_t *fieldOffsets);
#if SWIFT_OBJC_INTEROP
/// Initialize various fields of the class metadata.
///
/// This is a special function only used to re-initialize metadata of
/// classes that are visible to Objective-C and have resilient fields.
///
/// This means the class does not have generic or resilient ancestry,
/// and is itself not generic. However, it might have fields whose
/// size is not known at compile time.
SWIFT_RUNTIME_EXPORT
void swift_updateClassMetadata(ClassMetadata *self,
ClassLayoutFlags flags,
size_t numFields,
const TypeLayout * const *fieldTypes,
size_t *fieldOffsets);
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
MetadataDependency
swift_updateClassMetadata2(ClassMetadata *self,
ClassLayoutFlags flags,
size_t numFields,
const TypeLayout * const *fieldTypes,
size_t *fieldOffsets);
#endif
/// Given class metadata, a class descriptor and a method descriptor, look up
/// and load the vtable entry from the given metadata. The metadata must be of
/// the same class or a subclass of the descriptor.
SWIFT_RUNTIME_EXPORT
void *
swift_lookUpClassMethod(const ClassMetadata *metadata,
const MethodDescriptor *method,
const ClassDescriptor *description);
/// Fetch a uniqued metadata for a metatype type.
SWIFT_RUNTIME_EXPORT
const MetatypeMetadata *
swift_getMetatypeMetadata(const Metadata *instanceType);
/// Fetch a uniqued metadata for an existential metatype type.
SWIFT_RUNTIME_EXPORT
const ExistentialMetatypeMetadata *
swift_getExistentialMetatypeMetadata(const Metadata *instanceType);
/// Fetch a uniqued metadata for an existential type. The array
/// referenced by \c protocols will be sorted in-place.
SWIFT_RUNTIME_EXPORT
const ExistentialTypeMetadata *
swift_getExistentialTypeMetadata(ProtocolClassConstraint classConstraint,
const Metadata *superclassConstraint,
size_t numProtocols,
const ProtocolDescriptorRef *protocols);
/// Perform a copy-assignment from one existential container to another.
/// Both containers must be of the same existential type representable with the
/// same number of witness tables.
SWIFT_RUNTIME_EXPORT
OpaqueValue *swift_assignExistentialWithCopy(OpaqueValue *dest,
const OpaqueValue *src,
const Metadata *type);
/// Perform a copy-assignment from one existential container to another.
/// Both containers must be of the same existential type representable with no
/// witness tables.
OpaqueValue *swift_assignExistentialWithCopy0(OpaqueValue *dest,
const OpaqueValue *src,
const Metadata *type);
/// Perform a copy-assignment from one existential container to another.
/// Both containers must be of the same existential type representable with one
/// witness table.
OpaqueValue *swift_assignExistentialWithCopy1(OpaqueValue *dest,
const OpaqueValue *src,
const Metadata *type);
/// Calculate the numeric index of an extra inhabitant of a heap object
/// pointer in memory.
inline int swift_getHeapObjectExtraInhabitantIndex(HeapObject * const* src) {
// This must be consistent with the getHeapObjectExtraInhabitantIndex
// implementation in IRGen's ExtraInhabitants.cpp.
using namespace heap_object_abi;
uintptr_t value = reinterpret_cast<uintptr_t>(*src);
if (value >= LeastValidPointerValue)
return -1;
// Check for tagged pointers on appropriate platforms. Knowing that
// value < LeastValidPointerValue tells us a lot.
#if SWIFT_OBJC_INTEROP
if (value & ((uintptr_t(1) << ObjCReservedLowBits) - 1))
return -1;
return int(value >> ObjCReservedLowBits);
#else
return int(value);
#endif
}
/// Store an extra inhabitant of a heap object pointer to memory,
/// in the style of a value witness.
inline void swift_storeHeapObjectExtraInhabitant(HeapObject **dest, int index) {
// This must be consistent with the storeHeapObjectExtraInhabitant
// implementation in IRGen's ExtraInhabitants.cpp.
#if SWIFT_OBJC_INTEROP
auto value = uintptr_t(index) << heap_object_abi::ObjCReservedLowBits;
#else
auto value = uintptr_t(index);
#endif
*dest = reinterpret_cast<HeapObject*>(value);
}
/// Return the number of extra inhabitants in a heap object pointer.
inline constexpr unsigned swift_getHeapObjectExtraInhabitantCount() {
// This must be consistent with the getHeapObjectExtraInhabitantCount
// implementation in IRGen's ExtraInhabitants.cpp.
using namespace heap_object_abi;
// The runtime needs no more than INT_MAX inhabitants.
#if SWIFT_OBJC_INTEROP
return (LeastValidPointerValue >> ObjCReservedLowBits) > INT_MAX
? (unsigned)INT_MAX
: (unsigned)(LeastValidPointerValue >> ObjCReservedLowBits);
#else
return (LeastValidPointerValue) > INT_MAX
? unsigned(INT_MAX)
: unsigned(LeastValidPointerValue);
#endif
}
/// Calculate the numeric index of an extra inhabitant of a function
/// pointer in memory.
inline int swift_getFunctionPointerExtraInhabitantIndex(void * const* src) {
// This must be consistent with the getFunctionPointerExtraInhabitantIndex
// implementation in IRGen's ExtraInhabitants.cpp.
uintptr_t value = reinterpret_cast<uintptr_t>(*src);
return (value < heap_object_abi::LeastValidPointerValue
? (int) value : -1);
}
/// Store an extra inhabitant of a function pointer to memory, in the
/// style of a value witness.
inline void swift_storeFunctionPointerExtraInhabitant(void **dest, int index) {
// This must be consistent with the storeFunctionPointerExtraInhabitantIndex
// implementation in IRGen's ExtraInhabitants.cpp.
*dest = reinterpret_cast<void*>(static_cast<uintptr_t>(index));
}
/// Return the number of extra inhabitants in a function pointer.
inline constexpr unsigned swift_getFunctionPointerExtraInhabitantCount() {
// This must be consistent with the getFunctionPointerExtraInhabitantCount
// implementation in IRGen's ExtraInhabitants.cpp.
using namespace heap_object_abi;
// The runtime needs no more than INT_MAX inhabitants.
return (LeastValidPointerValue) > INT_MAX
? (unsigned)INT_MAX
: (unsigned)(LeastValidPointerValue);
}
/// Return the type name for a given type metadata.
std::string nameForMetadata(const Metadata *type,
bool qualified = true);
/// Register a block of protocol records for dynamic lookup.
SWIFT_RUNTIME_EXPORT
void swift_registerProtocols(const ProtocolRecord *begin,
const ProtocolRecord *end);
/// Register a block of protocol conformance records for dynamic lookup.
SWIFT_RUNTIME_EXPORT
void swift_registerProtocolConformances(const ProtocolConformanceRecord *begin,
const ProtocolConformanceRecord *end);
/// Register a block of type context descriptors for dynamic lookup.
SWIFT_RUNTIME_EXPORT
void swift_registerTypeMetadataRecords(const TypeMetadataRecord *begin,
const TypeMetadataRecord *end);
/// Return the superclass, if any. The result is nullptr for root
/// classes and class protocol types.
SWIFT_CC(swift)
SWIFT_RUNTIME_STDLIB_INTERNAL
const Metadata *_swift_class_getSuperclass(const Metadata *theClass);
SWIFT_CC(swift)
SWIFT_RUNTIME_STDLIB_INTERNAL MetadataResponse
getSuperclassMetadata(MetadataRequest request, const ClassMetadata *self);
#if !NDEBUG
/// Verify that the given metadata pointer correctly roundtrips its
/// mangled name through the demangler.
void verifyMangledNameRoundtrip(const Metadata *metadata);
#endif
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
const TypeContextDescriptor *swift_getTypeContextDescriptor(const Metadata *type);
// Defined in KeyPath.swift in the standard library.
SWIFT_RUNTIME_EXPORT
const HeapObject *swift_getKeyPath(const void *pattern, const void *arguments);
// For some reason, MSVC doesn't accept these declarations outside of
// swiftCore. TODO: figure out a reasonable way to declare them.
#if defined(swiftCore_EXPORTS)
/// Given a pointer to a borrowed value of type `Root` and a
/// `KeyPath<Root, Value>`, project a pointer to a borrowed value of type
/// `Value`.
SWIFT_RUNTIME_EXPORT
YieldOnceCoroutine<const OpaqueValue* (const OpaqueValue *root,
void *keyPath)>::type
swift_readAtKeyPath;
/// Given a pointer to a mutable value of type `Root` and a
/// `WritableKeyPath<Root, Value>`, project a pointer to a mutable value
/// of type `Value`.
SWIFT_RUNTIME_EXPORT
YieldOnceCoroutine<OpaqueValue* (OpaqueValue *root, void *keyPath)>::type
swift_modifyAtWritableKeyPath;
/// Given a pointer to a borrowed value of type `Root` and a
/// `ReferenceWritableKeyPath<Root, Value>`, project a pointer to a
/// mutable value of type `Value`.
SWIFT_RUNTIME_EXPORT
YieldOnceCoroutine<OpaqueValue* (const OpaqueValue *root, void *keyPath)>::type
swift_modifyAtReferenceWritableKeyPath;
#endif // swiftCore_EXPORTS
SWIFT_RUNTIME_EXPORT
void swift_enableDynamicReplacementScope(const DynamicReplacementScope *scope);
SWIFT_RUNTIME_EXPORT
void swift_disableDynamicReplacementScope(const DynamicReplacementScope *scope);
#pragma clang diagnostic pop
} // end namespace swift
#endif // SWIFT_RUNTIME_METADATA_H