mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
315 lines
12 KiB
C++
315 lines
12 KiB
C++
//===--- ValueWitness.def - Value witness x-macros --------------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// X-macro definition file for value witness tables.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// This file is "parameterized" in the sense that exactly one of the
|
|
// following macros *must* be defined:
|
|
|
|
/// WANT_ALL_VALUE_WITNESSES
|
|
/// Define this to expand all value witnesses, not just the ones from
|
|
/// a specific category.
|
|
#if defined(WANT_ALL_VALUE_WITNESSES)
|
|
#undef WANT_ALL_VALUE_WITNESSES
|
|
#define WANT_REQUIRED_VALUE_WITNESSES 1
|
|
#define WANT_ENUM_VALUE_WITNESSES 1
|
|
|
|
/// WANT_ONLY_REQUIRED_VALUE_WITNESSES
|
|
/// Define this to expand only the required value witnesses.
|
|
#elif defined(WANT_ONLY_REQUIRED_VALUE_WITNESSES)
|
|
#undef WANT_ONLY_REQUIRED_VALUE_WITNESSES
|
|
#define WANT_REQUIRED_VALUE_WITNESSES 1
|
|
#define WANT_ENUM_VALUE_WITNESSES 0
|
|
|
|
/// WANT_ONLY_ENUM_VALUE_WITNESSES
|
|
/// Define this to expand only the enum value witnesses.
|
|
#elif defined(WANT_ONLY_ENUM_VALUE_WITNESSES)
|
|
#undef WANT_ONLY_ENUM_VALUE_WITNESSES
|
|
#define WANT_REQUIRED_VALUE_WITNESSES 0
|
|
#define WANT_ENUM_VALUE_WITNESSES 1
|
|
|
|
/// WANT_REQUIRED_VALUE_WITNESSES
|
|
/// WANT_ENUM_VALUE_WITNESSES
|
|
/// Define all of these to control exactly what to expand.
|
|
#else
|
|
#if !defined(WANT_REQUIRED_VALUE_WITNESSES) || !defined(WANT_ENUM_VALUE_WITNESSES)
|
|
#error failed to define a WANT macro; possible typo?
|
|
#endif
|
|
#endif
|
|
|
|
/// VALUE_WITNESS(lowerId, upperId)
|
|
/// A fallback called for value witnesses if either of DATA_VALUE_WITNESS or
|
|
/// FUNCTION_VALUE_WITNESS is not defined.
|
|
|
|
/// FUNCTION_VALUE_WITNESS(lowerId, upperId, returnType, paramTypeList)
|
|
/// A function value witness. Types will be defined in terms of the
|
|
/// following macros:
|
|
/// MUTABLE_VALUE_TYPE - a pointer to a mutable opaque value
|
|
/// IMMUTABLE_VALUE_TYPE - a pointer to an immutable opaque value
|
|
/// MUTABLE_BUFFER_TYPE - a pointer to a fixed-size value buffer
|
|
/// IMMUTABLE_BUFFER_TYPE - a pointer to an immutable fixed-size buffer
|
|
/// TYPE_TYPE - a pointer to type metadata
|
|
/// SIZE_TYPE - StoredSize
|
|
/// INT_TYPE - int
|
|
/// UINT_TYPE - unsigned int
|
|
/// VOID_TYPE - void
|
|
/// Defaults to VALUE_WITNESS.
|
|
/// FIXME: The 'copy' witnesses should be using immutable types but aren't.
|
|
#ifndef FUNCTION_VALUE_WITNESS
|
|
#define FUNCTION_VALUE_WITNESS(lowerId, upperId, returnType, paramTypes) \
|
|
VALUE_WITNESS(lowerId, upperId)
|
|
#endif
|
|
|
|
/// DATA_VALUE_WITNESS(lowerId, upperId, type)
|
|
/// A non-function value witness. Types are specified as for
|
|
/// FUNCTION_VALUE_WITNESS
|
|
/// Defaults to VALUE_WITNESS.
|
|
#ifndef DATA_VALUE_WITNESS
|
|
#define DATA_VALUE_WITNESS(lowerId, upperId, type) \
|
|
VALUE_WITNESS(lowerId, upperId)
|
|
#endif
|
|
|
|
/// Begin a range of value witnesses. This will be expanded immediately
|
|
/// after the first value in the range, whose ID will be upperId.
|
|
/// Range expansions do not interact well with the use of WANT_ONLY_*.
|
|
#ifndef BEGIN_VALUE_WITNESS_RANGE
|
|
#define BEGIN_VALUE_WITNESS_RANGE(rangeId, upperId)
|
|
#endif
|
|
|
|
/// End a range of value witnesses. This will be expanded immediately
|
|
/// after the last value in the range, whose ID will be upperId.
|
|
/// Range expansions do not interact well with the use of WANT_ONLY_*.
|
|
#ifndef END_VALUE_WITNESS_RANGE
|
|
#define END_VALUE_WITNESS_RANGE(rangeId, upperId)
|
|
#endif
|
|
|
|
#if WANT_REQUIRED_VALUE_WITNESSES
|
|
|
|
/// T *(*initializeBufferWithCopyOfBuffer)(B *dest, B *src, M *self);
|
|
/// Given an invalid buffer, initialize it as a copy of the
|
|
/// object in the source buffer.
|
|
FUNCTION_VALUE_WITNESS(initializeBufferWithCopyOfBuffer,
|
|
InitializeBufferWithCopyOfBuffer,
|
|
MUTABLE_VALUE_TYPE,
|
|
(MUTABLE_BUFFER_TYPE, MUTABLE_BUFFER_TYPE, TYPE_TYPE))
|
|
|
|
BEGIN_VALUE_WITNESS_RANGE(ValueWitness,
|
|
InitializeBufferWithCopyOfBuffer)
|
|
BEGIN_VALUE_WITNESS_RANGE(RequiredValueWitness,
|
|
InitializeBufferWithCopyOfBuffer)
|
|
BEGIN_VALUE_WITNESS_RANGE(RequiredValueWitnessFunction,
|
|
InitializeBufferWithCopyOfBuffer)
|
|
|
|
/// void (*destroy)(T *object, witness_t *self);
|
|
///
|
|
/// Given a valid object of this type, destroy it, leaving it as an
|
|
/// invalid object. This is useful when generically destroying
|
|
/// an object which has been allocated in-line, such as an array,
|
|
/// struct, or tuple element.
|
|
FUNCTION_VALUE_WITNESS(destroy,
|
|
Destroy,
|
|
VOID_TYPE,
|
|
(MUTABLE_VALUE_TYPE, TYPE_TYPE))
|
|
|
|
/// T *(*initializeWithCopy)(T *dest, T *src, M *self);
|
|
///
|
|
/// Given an invalid object of this type, initialize it as a copy of
|
|
/// the source object. Returns the dest object.
|
|
FUNCTION_VALUE_WITNESS(initializeWithCopy,
|
|
InitializeWithCopy,
|
|
MUTABLE_VALUE_TYPE,
|
|
(MUTABLE_VALUE_TYPE, MUTABLE_VALUE_TYPE, TYPE_TYPE))
|
|
|
|
/// T *(*assignWithCopy)(T *dest, T *src, M *self);
|
|
///
|
|
/// Given a valid object of this type, change it to be a copy of the
|
|
/// source object. Returns the dest object.
|
|
FUNCTION_VALUE_WITNESS(assignWithCopy,
|
|
AssignWithCopy,
|
|
MUTABLE_VALUE_TYPE,
|
|
(MUTABLE_VALUE_TYPE, MUTABLE_VALUE_TYPE, TYPE_TYPE))
|
|
|
|
/// T *(*initializeWithTake)(T *dest, T *src, M *self);
|
|
///
|
|
/// Given an invalid object of this type, initialize it by taking
|
|
/// the value of the source object. The source object becomes
|
|
/// invalid. Returns the dest object.
|
|
FUNCTION_VALUE_WITNESS(initializeWithTake,
|
|
InitializeWithTake,
|
|
MUTABLE_VALUE_TYPE,
|
|
(MUTABLE_VALUE_TYPE, MUTABLE_VALUE_TYPE, TYPE_TYPE))
|
|
|
|
/// T *(*assignWithTake)(T *dest, T *src, M *self);
|
|
///
|
|
/// Given a valid object of this type, change it to be a copy of the
|
|
/// source object. The source object becomes invalid. Returns the
|
|
/// dest object.
|
|
FUNCTION_VALUE_WITNESS(assignWithTake,
|
|
AssignWithTake,
|
|
MUTABLE_VALUE_TYPE,
|
|
(MUTABLE_VALUE_TYPE, MUTABLE_VALUE_TYPE, TYPE_TYPE))
|
|
|
|
/// unsigned (*getEnumTagSinglePayload)(const T* enum, UINT_TYPE emptyCases,
|
|
/// M *self);
|
|
/// Given an instance of valid single payload enum with a payload of this
|
|
/// witness table's type (e.g Optional<ThisType>) , get the tag of the enum.
|
|
FUNCTION_VALUE_WITNESS(getEnumTagSinglePayload,
|
|
GetEnumTagSinglePayload,
|
|
UINT_TYPE,
|
|
(IMMUTABLE_VALUE_TYPE, UINT_TYPE, TYPE_TYPE))
|
|
|
|
/// void (*storeEnumTagSinglePayload)(T* enum, UINT_TYPE whichCase,
|
|
/// UINT_TYPE emptyCases, M *self);
|
|
/// Given uninitialized memory for an instance of a single payload enum with a
|
|
/// payload of this witness table's type (e.g Optional<ThisType>), store the
|
|
/// tag.
|
|
FUNCTION_VALUE_WITNESS(storeEnumTagSinglePayload,
|
|
StoreEnumTagSinglePayload,
|
|
VOID_TYPE,
|
|
(MUTABLE_VALUE_TYPE, UINT_TYPE, UINT_TYPE, TYPE_TYPE))
|
|
|
|
END_VALUE_WITNESS_RANGE(RequiredValueWitnessFunction,
|
|
StoreEnumTagSinglePayload)
|
|
|
|
/// SIZE_TYPE size;
|
|
///
|
|
/// The required storage size of a single object of this type.
|
|
DATA_VALUE_WITNESS(size,
|
|
Size,
|
|
SIZE_TYPE)
|
|
|
|
BEGIN_VALUE_WITNESS_RANGE(TypeLayoutWitness,
|
|
Size)
|
|
|
|
BEGIN_VALUE_WITNESS_RANGE(RequiredTypeLayoutWitness,
|
|
Size)
|
|
|
|
/// SIZE_TYPE stride;
|
|
///
|
|
/// The required size per element of an array of this type. It is at least
|
|
/// one, even for zero-sized types, like the empty tuple.
|
|
DATA_VALUE_WITNESS(stride,
|
|
Stride,
|
|
SIZE_TYPE)
|
|
|
|
|
|
/// UINT_TYPE flags;
|
|
///
|
|
/// The ValueWitnessAlignmentMask bits represent the required
|
|
/// alignment of the first byte of an object of this type, expressed
|
|
/// as a mask of the low bits that must not be set in the pointer.
|
|
/// This representation can be easily converted to the 'alignof'
|
|
/// result by merely adding 1, but it is more directly useful for
|
|
/// performing dynamic structure layouts, and it grants an
|
|
/// additional bit of precision in a compact field without needing
|
|
/// to switch to an exponent representation.
|
|
///
|
|
/// The ValueWitnessIsNonPOD bit is set if the type is not POD.
|
|
///
|
|
/// The ValueWitnessIsNonInline bit is set if the type cannot be
|
|
/// represented in a fixed-size buffer or if it is not bitwise takable.
|
|
///
|
|
/// The ExtraInhabitantsMask bits represent the number of "extra inhabitants"
|
|
/// of the bit representation of the value that do not form valid values of
|
|
/// the type.
|
|
///
|
|
/// The Enum_HasSpareBits bit is set if the type's binary representation
|
|
/// has unused bits.
|
|
///
|
|
/// The HasEnumWitnesses bit is set if the type is an enum type.
|
|
DATA_VALUE_WITNESS(flags,
|
|
Flags,
|
|
UINT_TYPE)
|
|
|
|
/// UINT_TYPE extraInhabitantCount;
|
|
///
|
|
/// The number of extra inhabitants in the type.
|
|
DATA_VALUE_WITNESS(extraInhabitantCount,
|
|
ExtraInhabitantCount,
|
|
UINT_TYPE)
|
|
|
|
END_VALUE_WITNESS_RANGE(RequiredTypeLayoutWitness,
|
|
ExtraInhabitantCount)
|
|
|
|
END_VALUE_WITNESS_RANGE(RequiredValueWitness,
|
|
ExtraInhabitantCount)
|
|
|
|
END_VALUE_WITNESS_RANGE(TypeLayoutWitness,
|
|
ExtraInhabitantCount)
|
|
|
|
#endif /* WANT_REQUIRED_VALUE_WITNESSES */
|
|
|
|
#if WANT_ENUM_VALUE_WITNESSES
|
|
|
|
// The following value witnesses are conditionally present if the witnessed
|
|
// type is an enum.
|
|
|
|
/// unsigned (*getEnumTag)(T *obj, M *self);
|
|
///
|
|
/// Given a valid object of this enum type, extracts the tag value indicating
|
|
/// which case of the enum is inhabited. Returned values are in the range
|
|
/// [0..NumElements-1].
|
|
FUNCTION_VALUE_WITNESS(getEnumTag,
|
|
GetEnumTag,
|
|
UINT_TYPE,
|
|
(IMMUTABLE_VALUE_TYPE, TYPE_TYPE))
|
|
|
|
BEGIN_VALUE_WITNESS_RANGE(EnumValueWitness,
|
|
GetEnumTag)
|
|
|
|
/// void (*destructiveProjectEnumData)(T *obj, M *self);
|
|
/// Given a valid object of this enum type, destructively extracts the
|
|
/// associated payload.
|
|
FUNCTION_VALUE_WITNESS(destructiveProjectEnumData,
|
|
DestructiveProjectEnumData,
|
|
VOID_TYPE,
|
|
(MUTABLE_VALUE_TYPE, TYPE_TYPE))
|
|
|
|
/// void (*destructiveInjectEnumTag)(T *obj, unsigned tag, M *self);
|
|
/// Given an enum case tag and a valid object of case's payload type,
|
|
/// destructively inserts the tag into the payload. The given tag value
|
|
/// must be in the range [-ElementsWithPayload..ElementsWithNoPayload-1].
|
|
FUNCTION_VALUE_WITNESS(destructiveInjectEnumTag,
|
|
DestructiveInjectEnumTag,
|
|
VOID_TYPE,
|
|
(MUTABLE_VALUE_TYPE, UINT_TYPE, TYPE_TYPE))
|
|
|
|
END_VALUE_WITNESS_RANGE(EnumValueWitness,
|
|
DestructiveInjectEnumTag)
|
|
|
|
END_VALUE_WITNESS_RANGE(ValueWitness,
|
|
DestructiveInjectEnumTag)
|
|
|
|
#endif /* WANT_ENUM_VALUE_WITNESSES */
|
|
|
|
#undef MUTABLE_VALUE_TYPE
|
|
#undef IMMUTABLE_VALUE_TYPE
|
|
#undef MUTABLE_BUFFER_TYPE
|
|
#undef IMMUTABLE_BUFFER_TYPE
|
|
#undef TYPE_TYPE
|
|
#undef SIZE_TYPE
|
|
#undef INT_TYPE
|
|
#undef VOID_TYPE
|
|
|
|
#undef END_VALUE_WITNESS_RANGE
|
|
#undef BEGIN_VALUE_WITNESS_RANGE
|
|
#undef DATA_VALUE_WITNESS
|
|
#undef FUNCTION_VALUE_WITNESS
|
|
#undef VALUE_WITNESS
|
|
#undef ENUM_VALUE_WITNESS
|
|
#undef NON_REQUIRED_VALUE_WITNESS
|
|
#undef REQUIRED_VALUE_WITNESS
|
|
#undef WANT_ENUM_VALUE_WITNESSES
|
|
#undef WANT_REQUIRED_VALUE_WITNESSES
|