Files
swift-mirror/include/swift/ABI/ValueWitness.def
John McCall 2ba7090fe8 Remove the extra-inhabitant value witness functions.
This is essentially a long-belated follow-up to Arnold's #12606.
The key observation here is that the enum-tag-single-payload witnesses
are strictly more powerful than the XI witnesses: you can simulate
the XI witnesses by using an extra case count that's <= the XI count.
Of course the result is less efficient than the XI witnesses, but
that's less important than overall code size, and we can work on
fast-paths for that.

The extra inhabitant count is stored in a 32-bit field (always present)
following the ValueWitnessFlags, which now occupy a fixed 32 bits.
This inflates non-XI VWTs on 32-bit targets by a word, but the net effect
on XI VWTs is to shrink them by two words, which is likely to be the
more important change.  Also, being able to access the XI count directly
should be a nice win.
2018-12-11 22:18:44 -05:00

314 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)
/// 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)
/// 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,
INT_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