Skip to content

Instantly share code, notes, and snippets.

@koron
Last active June 10, 2018 06:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koron/96405064efe2ac47a649eb4c3f2572f2 to your computer and use it in GitHub Desktop.
Save koron/96405064efe2ac47a649eb4c3f2572f2 to your computer and use it in GitHub Desktop.
$ g++ -E ValueWitness.hpp | sed -e '/^$/d -e '/^#/d' > _out.hpp
enum class ValueWitness : unsigned {
InitializeBufferWithCopyOfBuffer,
First_ValueWitness = InitializeBufferWithCopyOfBuffer,
First_RequiredValueWitness = InitializeBufferWithCopyOfBuffer,
First_RequiredValueWitnessFunction = InitializeBufferWithCopyOfBuffer,
Destroy,
InitializeWithCopy,
AssignWithCopy,
InitializeWithTake,
AssignWithTake,
GetEnumTagSinglePayload,
StoreEnumTagSinglePayload,
Last_RequiredValueWitnessFunction = StoreEnumTagSinglePayload,
Size,
First_TypeLayoutWitness = Size,
First_RequiredTypeLayoutWitness = Size,
Flags,
Stride,
Last_RequiredTypeLayoutWitness = Stride,
Last_RequiredValueWitness = Stride,
ExtraInhabitantFlags,
First_ExtraInhabitantValueWitness = ExtraInhabitantFlags,
Last_TypeLayoutWitness = ExtraInhabitantFlags,
StoreExtraInhabitant,
First_ExtraInhabitantValueWitnessFunction = StoreExtraInhabitant,
GetExtraInhabitantIndex,
Last_ExtraInhabitantValueWitnessFunction = GetExtraInhabitantIndex,
Last_ExtraInhabitantValueWitness = GetExtraInhabitantIndex,
GetEnumTag,
First_EnumValueWitness = GetEnumTag,
DestructiveProjectEnumData,
DestructiveInjectEnumTag,
Last_EnumValueWitness = DestructiveInjectEnumTag,
Last_ValueWitness = DestructiveInjectEnumTag,
};
// copy from https://github.com/apple/swift/blob/0ba027f04ba553c87d99bdfacdb82c468b7119c9/include/swift/ABI/ValueWitness.def
//===--- 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_EXTRA_INHABITANT_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_EXTRA_INHABITANT_VALUE_WITNESSES 0
#define WANT_ENUM_VALUE_WITNESSES 0
/// WANT_ONLY_EXTRA_INHABITANT_VALUE_WITNESSES
/// Define this to expand only the extra-inhabitant value witnesses.
#elif defined(WANT_ONLY_EXTRA_INHABITANT_VALUE_WITNESSES)
#undef WANT_ONLY_EXTRA_INHABITANT_VALUE_WITNESSES
#define WANT_REQUIRED_VALUE_WITNESSES 0
#define WANT_EXTRA_INHABITANT_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_EXTRA_INHABITANT_VALUE_WITNESSES 0
#define WANT_ENUM_VALUE_WITNESSES 1
/// WANT_REQUIRED_VALUE_WITNESSES
/// WANT_EXTRA_INHABITANT_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_EXTRA_INHABITANT_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 - size_t
/// 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_t 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_t 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 Enum_HasExtraInhabitants bit is set if the type's binary
/// representation has "extra inhabitants" that do not form valid values of
/// the type, and the value witness table contains the ExtraInhabitantWitness
/// entries.
///
/// 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,
SIZE_TYPE)
/// size_t 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)
END_VALUE_WITNESS_RANGE(RequiredTypeLayoutWitness,
Stride)
END_VALUE_WITNESS_RANGE(RequiredValueWitness,
Stride)
#endif /* WANT_REQUIRED_VALUE_WITNESSES */
#if WANT_EXTRA_INHABITANT_VALUE_WITNESSES
// The following value witnesses are conditionally present based on
// the Enum_HasExtraInhabitants bit of the flags.
/// size_t extraInhabitantFlags;
///
/// These bits are always present if the extra inhabitants witnesses are:
///
/// - The NumExtraInhabitantsMask bits contain the number of extra
/// inhabitants of the type representation.
///
/// If the Enum_HasSpareBits flag is set in the value witness flags, these
/// additional flags are available:
///
/// - The NumSpareBitsMask bits contain the number of (host-endian) contiguous
/// spare bits in the type representation.
/// - The SpareBitsShiftMask bits contain the (host-endian) bit offset of the
/// lowest spare bit.
DATA_VALUE_WITNESS(extraInhabitantFlags,
ExtraInhabitantFlags,
SIZE_TYPE)
BEGIN_VALUE_WITNESS_RANGE(ExtraInhabitantValueWitness,
ExtraInhabitantFlags)
END_VALUE_WITNESS_RANGE(TypeLayoutWitness,
ExtraInhabitantFlags)
/// void (*storeExtraInhabitant)(T *obj, int index, M *self);
///
/// Given an invalid object of this type, store the representation of an
/// extra inhabitant of the type. The object will remain invalid, because
/// an extra inhabitant is by definition an invalid representation of the
/// type. index must be less than numExtraInhabitants.
FUNCTION_VALUE_WITNESS(storeExtraInhabitant,
StoreExtraInhabitant,
VOID_TYPE,
(MUTABLE_VALUE_TYPE, INT_TYPE, TYPE_TYPE))
BEGIN_VALUE_WITNESS_RANGE(ExtraInhabitantValueWitnessFunction,
StoreExtraInhabitant)
/// int (*getExtraInhabitantIndex)(T *obj, M *self);
///
/// Given an invalid object of this type with an extra inhabitant
/// representation, returns the index of the extra inhabitant representation.
/// Returns -1 if the object is a valid value of the type. If non-negative,
/// the return value is the same index that can be passed to
/// storeExtraInhabitant to reproduce the representation.
FUNCTION_VALUE_WITNESS(getExtraInhabitantIndex,
GetExtraInhabitantIndex,
INT_TYPE,
(IMMUTABLE_VALUE_TYPE, TYPE_TYPE))
END_VALUE_WITNESS_RANGE(ExtraInhabitantValueWitnessFunction,
GetExtraInhabitantIndex)
END_VALUE_WITNESS_RANGE(ExtraInhabitantValueWitness,
GetExtraInhabitantIndex)
#endif /* WANT_EXTRA_INHABITANT_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 EXTRA_INHABITANT_VALUE_WITNESS
#undef NON_REQUIRED_VALUE_WITNESS
#undef REQUIRED_VALUE_WITNESS
#undef WANT_ENUM_VALUE_WITNESSES
#undef WANT_EXTRA_INHABITANT_VALUE_WITNESSES
#undef WANT_REQUIRED_VALUE_WITNESSES
// copy from https://github.com/apple/swift/blob/0ba027f04ba553c87d99bdfacdb82c468b7119c9/include/swift/IRGen/ValueWitness.h#L66-L72
enum class ValueWitness : unsigned {
#define WANT_ALL_VALUE_WITNESSES
#define VALUE_WITNESS(lowerId, upperId) upperId,
#define BEGIN_VALUE_WITNESS_RANGE(rangeId, upperId) First_##rangeId = upperId,
#define END_VALUE_WITNESS_RANGE(rangeId, upperId) Last_##rangeId = upperId,
#include "./ValueWitness.def"
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment