//===--- KeyPath.h - ABI constants for key path objects ---------*- 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 // //===----------------------------------------------------------------------===// // // Constants used in the layout of key path objects. // //===----------------------------------------------------------------------===// #ifndef SWIFT_ABI_KEYPATH_H #define SWIFT_ABI_KEYPATH_H // We include the basic constants in a shim header so that it can be shared with // the Swift implementation in the standard library. #include #include #include "swift/shims/KeyPath.h" namespace swift { /// Header layout for a key path's data buffer header. class KeyPathBufferHeader { uint32_t Data; constexpr KeyPathBufferHeader(unsigned Data) : Data(Data) {} static constexpr uint32_t validateSize(uint32_t size) { return assert(size <= _SwiftKeyPathBufferHeader_SizeMask && "size too big!"), size; } public: constexpr KeyPathBufferHeader(unsigned size, bool trivialOrInstantiableInPlace, bool hasReferencePrefix) : Data((validateSize(size) & _SwiftKeyPathBufferHeader_SizeMask) | (trivialOrInstantiableInPlace ? _SwiftKeyPathBufferHeader_TrivialFlag : 0) | (hasReferencePrefix ? _SwiftKeyPathBufferHeader_HasReferencePrefixFlag : 0)) { } constexpr KeyPathBufferHeader withSize(unsigned size) const { return (Data & ~_SwiftKeyPathBufferHeader_SizeMask) | validateSize(size); } constexpr KeyPathBufferHeader withIsTrivial(bool isTrivial) const { return (Data & ~_SwiftKeyPathBufferHeader_TrivialFlag) | (isTrivial ? _SwiftKeyPathBufferHeader_TrivialFlag : 0); } constexpr KeyPathBufferHeader withIsInstantiableInPlace(bool isTrivial) const { return (Data & ~_SwiftKeyPathBufferHeader_TrivialFlag) | (isTrivial ? _SwiftKeyPathBufferHeader_TrivialFlag : 0); } constexpr KeyPathBufferHeader withHasReferencePrefix(bool hasPrefix) const { return (Data & ~_SwiftKeyPathBufferHeader_HasReferencePrefixFlag) | (hasPrefix ? _SwiftKeyPathBufferHeader_HasReferencePrefixFlag : 0); } constexpr uint32_t getData() const { return Data; } }; /// Header layout for a key path component's header. class KeyPathComponentHeader { uint32_t Data; constexpr KeyPathComponentHeader(unsigned Data) : Data(Data) {} static constexpr uint32_t validateInlineOffset(uint32_t offset) { return assert(offsetCanBeInline(offset) && "offset too big!"), offset; } static constexpr uint32_t isLetBit(bool isLet) { return isLet ? 0 : _SwiftKeyPathComponentHeader_StoredMutableFlag; } public: static constexpr bool offsetCanBeInline(unsigned offset) { return offset <= _SwiftKeyPathComponentHeader_MaximumOffsetPayload; } constexpr static KeyPathComponentHeader forStructComponentWithInlineOffset(bool isLet, unsigned offset) { return KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_StructTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | validateInlineOffset(offset) | isLetBit(isLet)); } constexpr static KeyPathComponentHeader forStructComponentWithOutOfLineOffset(bool isLet) { return KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_StructTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | _SwiftKeyPathComponentHeader_OutOfLineOffsetPayload | isLetBit(isLet)); } constexpr static KeyPathComponentHeader forStructComponentWithUnresolvedFieldOffset(bool isLet) { return KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_StructTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | _SwiftKeyPathComponentHeader_UnresolvedFieldOffsetPayload | isLetBit(isLet)); } constexpr static KeyPathComponentHeader forClassComponentWithInlineOffset(bool isLet, unsigned offset) { return KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_ClassTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | validateInlineOffset(offset) | isLetBit(isLet)); } constexpr static KeyPathComponentHeader forClassComponentWithOutOfLineOffset(bool isLet) { return KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_ClassTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | _SwiftKeyPathComponentHeader_OutOfLineOffsetPayload | isLetBit(isLet)); } constexpr static KeyPathComponentHeader forClassComponentWithUnresolvedFieldOffset(bool isLet) { return KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_ClassTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | _SwiftKeyPathComponentHeader_UnresolvedFieldOffsetPayload | isLetBit(isLet)); } constexpr static KeyPathComponentHeader forClassComponentWithUnresolvedIndirectOffset(bool isLet) { return KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_ClassTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | _SwiftKeyPathComponentHeader_UnresolvedIndirectOffsetPayload | isLetBit(isLet)); } constexpr static KeyPathComponentHeader forOptionalChain() { return KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_OptionalTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | _SwiftKeyPathComponentHeader_OptionalChainPayload); } constexpr static KeyPathComponentHeader forOptionalWrap() { return KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_OptionalTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | _SwiftKeyPathComponentHeader_OptionalWrapPayload); } constexpr static KeyPathComponentHeader forOptionalForce() { return KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_OptionalTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | _SwiftKeyPathComponentHeader_OptionalForcePayload); } enum ComputedPropertyKind { GetOnly, SettableNonmutating, SettableMutating, }; enum ComputedPropertyIDKind { Pointer, StoredPropertyIndex, VTableOffset, }; enum ComputedPropertyIDResolution { Resolved, ResolvedAbsolute, IndirectPointer, FunctionCall, }; constexpr static KeyPathComponentHeader forComputedProperty(ComputedPropertyKind kind, ComputedPropertyIDKind idKind, bool hasArguments, ComputedPropertyIDResolution resolution) { return KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_ComputedTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | (kind != GetOnly ? _SwiftKeyPathComponentHeader_ComputedSettableFlag : 0) | (kind == SettableMutating ? _SwiftKeyPathComponentHeader_ComputedMutatingFlag : 0) | (idKind == StoredPropertyIndex ? _SwiftKeyPathComponentHeader_ComputedIDByStoredPropertyFlag : 0) | (idKind == VTableOffset ? _SwiftKeyPathComponentHeader_ComputedIDByVTableOffsetFlag : 0) | (hasArguments ? _SwiftKeyPathComponentHeader_ComputedHasArgumentsFlag : 0) | (resolution == Resolved ? _SwiftKeyPathComponentHeader_ComputedIDResolved : resolution == ResolvedAbsolute ? _SwiftKeyPathComponentHeader_ComputedIDResolvedAbsolute : resolution == IndirectPointer ? _SwiftKeyPathComponentHeader_ComputedIDUnresolvedIndirectPointer : resolution == FunctionCall ? _SwiftKeyPathComponentHeader_ComputedIDUnresolvedFunctionCall : (assert(false && "invalid resolution"), 0))); } constexpr static KeyPathComponentHeader forExternalComponent(unsigned numSubstitutions) { return assert(numSubstitutions < (1u << _SwiftKeyPathComponentHeader_DiscriminatorShift) - 1u && "too many substitutions"), KeyPathComponentHeader( (_SwiftKeyPathComponentHeader_ExternalTag << _SwiftKeyPathComponentHeader_DiscriminatorShift) | numSubstitutions); } constexpr uint32_t getData() const { return Data; } }; } #endif // SWIFT_ABI_KEYPATH_H