mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
This is a type that has ownership of a reference while allowing access to the
spare bits inside the pointer, but which can also safely hold an ObjC tagged pointer
reference (with no spare bits of course). It additionally blesses one
Foundation-coordinated bit with the meaning of "has swift refcounting" in order
to get a faster short-circuit to native refcounting. It supports the following
builtin operations:
- Builtin.castToBridgeObject<T>(ref: T, bits: Builtin.Word) ->
Builtin.BridgeObject
Creates a BridgeObject that contains the bitwise-OR of the bit patterns of
"ref" and "bits". It is the user's responsibility to ensure "bits" doesn't
interfere with the reference identity of the resulting value. In other words,
it is undefined behavior unless:
castReferenceFromBridgeObject(castToBridgeObject(ref, bits)) === ref
This means "bits" must be zero if "ref" is a tagged pointer. If "ref" is a real
object pointer, "bits" must not have any non-spare bits set (unless they're
already set in the pointer value). The native discriminator bit may only be set
if the object is Swift-refcounted.
- Builtin.castReferenceFromBridgeObject<T>(bo: Builtin.BridgeObject) -> T
Extracts the reference from a BridgeObject.
- Builtin.castBitPatternFromBridgeObject(bo: Builtin.BridgeObject) -> Builtin.Word
Presents the bit pattern of a BridgeObject as a Word.
BridgeObject's bits are set up as follows on the various platforms:
i386, armv7:
No ObjC tagged pointers
Swift native refcounting flag bit: 0x0000_0001
Other available spare bits: 0x0000_0002
x86_64:
Reserved for ObjC tagged pointers: 0x8000_0000_0000_0001
Swift native refcounting flag bit: 0x0000_0000_0000_0002
Other available spare bits: 0x7F00_0000_0000_0004
arm64:
Reserved for ObjC tagged pointers: 0x8000_0000_0000_0000
Swift native refcounting flag bit: 0x4000_0000_0000_0000
Other available spare bits: 0x3F00_0000_0000_0007
TODO: BridgeObject doesn't present any extra inhabitants. It ought to at least provide null as an extra inhabitant for Optional.
Swift SVN r22880
185 lines
6.8 KiB
C++
185 lines
6.8 KiB
C++
//===--- KnownMetadata.cpp - Swift Language ABI Known Metadata Objects ----===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Definitions of some builtin metadata objects.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/Runtime/Metadata.h"
|
|
#include "swift/Runtime/HeapObject.h"
|
|
#include "MetadataImpl.h"
|
|
#include "Private.h"
|
|
#include <cstring>
|
|
#include <climits>
|
|
|
|
using namespace swift;
|
|
using namespace metadataimpl;
|
|
|
|
/// Copy a value from one object to another based on the size in the
|
|
/// given type metadata.
|
|
OpaqueValue *swift::swift_copyPOD(OpaqueValue *dest, OpaqueValue *src,
|
|
const Metadata *type) {
|
|
return (OpaqueValue*) memcpy(dest, src, type->getValueWitnesses()->size);
|
|
}
|
|
|
|
/// A function which does a naive copy.
|
|
template <class T> static T *copy(T *dest, T *src, const Metadata *self) {
|
|
*dest = *src;
|
|
return dest;
|
|
}
|
|
|
|
#define POD_VALUE_WITNESS_TABLE(TYPE, SIZE) { \
|
|
(value_witness_types::destroyBuffer*) &doNothing, \
|
|
(value_witness_types::initializeBufferWithCopyOfBuffer*) ©<TYPE>, \
|
|
(value_witness_types::projectBuffer*) &projectBuffer, \
|
|
(value_witness_types::deallocateBuffer*) &doNothing, \
|
|
(value_witness_types::destroy*) &doNothing, \
|
|
(value_witness_types::initializeBufferWithCopy*) ©<TYPE>, \
|
|
(value_witness_types::initializeWithCopy*) ©<TYPE>, \
|
|
(value_witness_types::assignWithCopy*) ©<TYPE>, \
|
|
(value_witness_types::initializeBufferWithTake*) ©<TYPE>, \
|
|
(value_witness_types::initializeWithTake*) ©<TYPE>, \
|
|
(value_witness_types::assignWithTake*) ©<TYPE>, \
|
|
(value_witness_types::allocateBuffer*) &projectBuffer, \
|
|
(value_witness_types::initializeBufferWithTakeOfBuffer*) ©<TYPE>, \
|
|
(value_witness_types::size) (SIZE), \
|
|
ValueWitnessFlags().withAlignment(SIZE).withPOD(true) \
|
|
.withInlineStorage(true), \
|
|
(value_witness_types::stride) (SIZE) \
|
|
}
|
|
|
|
namespace {
|
|
// A type sized and aligned the way Swift wants Int128 (and Float80/Float128)
|
|
// to be sized and aligned.
|
|
struct alignas(16) int128_like {
|
|
char data[16];
|
|
};
|
|
}
|
|
|
|
// We use explicit sizes and alignments here just in case the C ABI
|
|
// under-aligns any or all of them.
|
|
const ValueWitnessTable swift::_TWVBi8_ =
|
|
ValueWitnessTableForBox<NativeBox<uint8_t, 1>>::table;
|
|
const ValueWitnessTable swift::_TWVBi16_ =
|
|
ValueWitnessTableForBox<NativeBox<uint16_t, 2>>::table;
|
|
const ValueWitnessTable swift::_TWVBi32_ =
|
|
ValueWitnessTableForBox<NativeBox<uint32_t, 4>>::table;
|
|
const ValueWitnessTable swift::_TWVBi64_ =
|
|
ValueWitnessTableForBox<NativeBox<uint64_t, 8>>::table;
|
|
const ValueWitnessTable swift::_TWVBi128_ =
|
|
ValueWitnessTableForBox<NativeBox<int128_like, 16>>::table;
|
|
|
|
/// Store an invalid pointer value as an extra inhabitant of a heap object.
|
|
void swift::swift_storeHeapObjectExtraInhabitant(HeapObject **dest,
|
|
int index) {
|
|
using namespace heap_object_abi;
|
|
|
|
// This must be consistent with the storeHeapObjectExtraInhabitant
|
|
// implementation in IRGen's GenType.cpp.
|
|
|
|
// FIXME: We could use high spare bits to produce extra inhabitants, but we
|
|
// probably won't need to.
|
|
*dest = (HeapObject*)((uintptr_t)index << ObjCReservedLowBits);
|
|
}
|
|
|
|
/// Return the extra inhabitant index for an invalid pointer value, or -1 if
|
|
/// the pointer is valid.
|
|
int swift::swift_getHeapObjectExtraInhabitantIndex(HeapObject * const* src) {
|
|
using namespace heap_object_abi;
|
|
|
|
// This must be consistent with the getHeapObjectExtraInhabitant
|
|
// implementation in IRGen's GenType.cpp.
|
|
|
|
uintptr_t val = (uintptr_t)*src;
|
|
|
|
// Return -1 for valid pointers.
|
|
// FIXME: We could use high spare bits to produce extra inhabitants, but we
|
|
// probably won't need to.
|
|
if (val >= LeastValidPointerValue)
|
|
return -1;
|
|
|
|
#if SWIFT_OBJC_INTEROP
|
|
// Return -1 for ObjC tagged pointers.
|
|
// FIXME: This check is unnecessary for known-Swift types.
|
|
if (isObjCTaggedPointer((const void*) val))
|
|
return -1;
|
|
#endif
|
|
|
|
return (int)(val >> ObjCReservedLowBits);
|
|
}
|
|
|
|
|
|
/// The basic value-witness table for Swift object pointers.
|
|
const ExtraInhabitantsValueWitnessTable swift::_TWVBo =
|
|
ValueWitnessTableForBox<SwiftRetainableBox>::table;
|
|
|
|
/// The value-witness table for pointer-aligned unmanaged pointer types.
|
|
const ExtraInhabitantsValueWitnessTable swift::_TWVMBo =
|
|
ValueWitnessTableForBox<PointerPointerBox>::table;
|
|
|
|
#if SWIFT_OBJC_INTEROP
|
|
/*** Objective-C pointers ****************************************************/
|
|
|
|
// This section can reasonably be suppressed in builds that don't
|
|
// need to support Objective-C.
|
|
|
|
/// The basic value-witness table for ObjC object pointers.
|
|
const ExtraInhabitantsValueWitnessTable swift::_TWVBO =
|
|
ValueWitnessTableForBox<ObjCRetainableBox>::table;
|
|
#endif
|
|
|
|
/// The value-witness table for BridgeObject.
|
|
const ValueWitnessTable swift::_TWVBb =
|
|
ValueWitnessTableForBox<BridgeObjectBox>::table;
|
|
|
|
/*** Functions ***************************************************************/
|
|
|
|
/// The basic value-witness table for function types.
|
|
const ValueWitnessTable swift::_TWVFT_T_ =
|
|
ValueWitnessTableForBox<AggregateBox<NativeBox<void*>,
|
|
SwiftRetainableBox>>::table;
|
|
|
|
/*** Empty tuples ************************************************************/
|
|
|
|
/// The basic value-witness table for empty types.
|
|
const ValueWitnessTable swift::_TWVT_ =
|
|
ValueWitnessTableForBox<AggregateBox<>>::table;
|
|
|
|
/*** Known metadata **********************************************************/
|
|
|
|
// Define some builtin opaque metadata.
|
|
#define OPAQUE_METADATA(TYPE) \
|
|
const FullOpaqueMetadata swift::_TMd##TYPE = { \
|
|
{ &_TWV##TYPE }, \
|
|
{ { MetadataKind::Opaque } } \
|
|
};
|
|
OPAQUE_METADATA(Bi8_)
|
|
OPAQUE_METADATA(Bi16_)
|
|
OPAQUE_METADATA(Bi32_)
|
|
OPAQUE_METADATA(Bi64_)
|
|
OPAQUE_METADATA(Bi128_)
|
|
OPAQUE_METADATA(Bo)
|
|
OPAQUE_METADATA(Bb)
|
|
#if SWIFT_OBJC_INTEROP
|
|
OPAQUE_METADATA(BO)
|
|
#endif
|
|
|
|
/// The standard metadata for the empty tuple.
|
|
const FullMetadata<TupleTypeMetadata> swift::_TMdT_ = {
|
|
{ &_TWVT_ }, // ValueWitnesses
|
|
{
|
|
{ MetadataKind::Tuple }, // Kind
|
|
0, // NumElements
|
|
nullptr // Labels
|
|
}
|
|
};
|