mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
To get the full benefit of dyld3 on Darwin platforms, pointer relocations need to be pointer-aligned, which unfortunately requires growing some key path data structures a little bit. This does tidy up some code that had to hack around our lack of unaligned load/store operations on UnsafeRawPointer, at least. While we're here, we can also simplify the identification strategy for reabstracted stored properties; we only need the property index to identify, not the absolute offset. rdar://problem/32318829
213 lines
7.3 KiB
C++
213 lines
7.3 KiB
C++
//===--- 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 <cstdint>
|
|
#include <cassert>
|
|
#include "../../../stdlib/public/SwiftShims/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;
|
|
}
|
|
|
|
public:
|
|
static constexpr bool offsetCanBeInline(unsigned offset) {
|
|
return offset <= _SwiftKeyPathComponentHeader_MaximumOffsetPayload;
|
|
}
|
|
|
|
constexpr static KeyPathComponentHeader
|
|
forStructComponentWithInlineOffset(unsigned offset) {
|
|
return KeyPathComponentHeader(
|
|
(_SwiftKeyPathComponentHeader_StructTag
|
|
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
|
|
| validateInlineOffset(offset));
|
|
}
|
|
|
|
constexpr static KeyPathComponentHeader
|
|
forStructComponentWithOutOfLineOffset() {
|
|
return KeyPathComponentHeader(
|
|
(_SwiftKeyPathComponentHeader_StructTag
|
|
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
|
|
| _SwiftKeyPathComponentHeader_OutOfLineOffsetPayload);
|
|
}
|
|
|
|
constexpr static KeyPathComponentHeader
|
|
forStructComponentWithUnresolvedFieldOffset() {
|
|
return KeyPathComponentHeader(
|
|
(_SwiftKeyPathComponentHeader_StructTag
|
|
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
|
|
| _SwiftKeyPathComponentHeader_UnresolvedFieldOffsetPayload);
|
|
}
|
|
|
|
constexpr static KeyPathComponentHeader
|
|
forClassComponentWithInlineOffset(unsigned offset) {
|
|
return KeyPathComponentHeader(
|
|
(_SwiftKeyPathComponentHeader_ClassTag
|
|
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
|
|
| validateInlineOffset(offset));
|
|
}
|
|
|
|
constexpr static KeyPathComponentHeader
|
|
forClassComponentWithOutOfLineOffset() {
|
|
return KeyPathComponentHeader(
|
|
(_SwiftKeyPathComponentHeader_ClassTag
|
|
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
|
|
| _SwiftKeyPathComponentHeader_OutOfLineOffsetPayload);
|
|
}
|
|
|
|
constexpr static KeyPathComponentHeader
|
|
forClassComponentWithUnresolvedFieldOffset() {
|
|
return KeyPathComponentHeader(
|
|
(_SwiftKeyPathComponentHeader_ClassTag
|
|
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
|
|
| _SwiftKeyPathComponentHeader_UnresolvedFieldOffsetPayload);
|
|
}
|
|
|
|
constexpr static KeyPathComponentHeader
|
|
forClassComponentWithUnresolvedIndirectOffset() {
|
|
return KeyPathComponentHeader(
|
|
(_SwiftKeyPathComponentHeader_ClassTag
|
|
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
|
|
| _SwiftKeyPathComponentHeader_UnresolvedIndirectOffsetPayload);
|
|
}
|
|
|
|
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,
|
|
};
|
|
|
|
constexpr static uint32_t
|
|
getResolutionStrategy(ComputedPropertyIDKind idKind) {
|
|
return idKind == Pointer ? _SwiftKeyPathComponentHeader_ComputedIDUnresolvedIndirectPointer
|
|
: (assert("no resolution strategy implemented" && false), 0);
|
|
}
|
|
|
|
constexpr static KeyPathComponentHeader
|
|
forComputedProperty(ComputedPropertyKind kind,
|
|
ComputedPropertyIDKind idKind,
|
|
bool hasArguments,
|
|
bool resolvedID) {
|
|
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)
|
|
| (resolvedID ? _SwiftKeyPathComponentHeader_ComputedIDResolved
|
|
: getResolutionStrategy(idKind)));
|
|
}
|
|
|
|
constexpr uint32_t getData() const { return Data; }
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|