1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
|
//===--- _SwiftCxxInteroperability.h - C++ Interop support ------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2020 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
//
//===----------------------------------------------------------------------===//
//
// Defines types and support functions required by C++ bindings generated
// by the Swift compiler that allow C++ code to call Swift APIs.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_CXX_INTEROPERABILITY_H
#define SWIFT_CXX_INTEROPERABILITY_H
#ifdef __cplusplus
#include <cstdint>
#include <stdlib.h>
#if defined(_WIN32)
#include <malloc.h>
#endif
#if !defined(SWIFT_CALL)
# define SWIFT_CALL __attribute__((swiftcall))
#endif
#if __has_attribute(transparent_stepping)
#define SWIFT_INLINE_THUNK_ATTRIBUTES \
__attribute__((transparent_stepping))
#elif __has_attribute(always_inline) && __has_attribute(nodebug)
#define SWIFT_INLINE_THUNK_ATTRIBUTES \
__attribute__((always_inline)) __attribute__((nodebug))
#else
#define SWIFT_INLINE_THUNK_ATTRIBUTES
#endif
#if defined(DEBUG) && __has_attribute(used)
// Additional 'used' attribute is used in debug mode to make inline thunks
// accessible to LLDB.
#define SWIFT_INLINE_THUNK_USED_ATTRIBUTE __attribute__((used))
#else
#define SWIFT_INLINE_THUNK_USED_ATTRIBUTE
#endif
/// The `SWIFT_INLINE_THUNK` macro is applied on the inline function thunks in
/// the header that represents a C/C++ Swift module interface generated by the
/// Swift compiler.
#define SWIFT_INLINE_THUNK \
inline SWIFT_INLINE_THUNK_ATTRIBUTES SWIFT_INLINE_THUNK_USED_ATTRIBUTE
/// The `SWIFT_INLINE_PRIVATE_HELPER` macro is applied on the helper / utility
/// functions in the header that represents a C/C++ Swift module interface
/// generated by the Swift compiler.
#define SWIFT_INLINE_PRIVATE_HELPER inline SWIFT_INLINE_THUNK_ATTRIBUTES
/// The `SWIFT_SYMBOL_MODULE` and `SWIFT_SYMBOL_MODULE_USR` macros apply
/// `external_source_symbol` Clang attributes to C++ declarations that represent
/// Swift declarations. This allows Clang to index them as external
/// declarations, using the specified Swift USR values.
#if __has_attribute(external_source_symbol)
#define SWIFT_SYMBOL_MODULE(moduleValue) \
__attribute__((external_source_symbol( \
language = "Swift", defined_in = moduleValue, generated_declaration)))
#if __has_attribute(external_source_symbol) > 1
#define SWIFT_SYMBOL_MODULE_USR(moduleValue, usrValue) \
__attribute__(( \
external_source_symbol(language = "Swift", defined_in = moduleValue, \
generated_declaration, USR = usrValue)))
#else
#define SWIFT_SYMBOL_MODULE_USR(moduleValue, usrValue) \
__attribute__((external_source_symbol( \
language = "Swift", defined_in = moduleValue, generated_declaration)))
#endif
#else
#define SWIFT_SYMBOL_MODULE_USR(moduleValue, usrValue)
#define SWIFT_SYMBOL_MODULE(moduleValue)
#endif
#if __has_attribute(swift_private)
#define SWIFT_PRIVATE_ATTR __attribute__((swift_private))
#else
#define SWIFT_PRIVATE_ATTR
#endif
namespace swift SWIFT_PRIVATE_ATTR {
namespace _impl {
extern "C" void *_Nonnull swift_retain(void *_Nonnull) noexcept;
extern "C" void swift_release(void *_Nonnull) noexcept;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreserved-identifier"
extern "C" void _swift_stdlib_reportFatalError(const char *_Nonnull prefix,
int prefixLength,
const char *_Nonnull message,
int messageLength,
uint32_t flags) noexcept;
// A dummy symbol that forces a linker error when
// C++ tries to invoke a move of a Swift value type.
extern "C" void _fatalError_Cxx_move_of_Swift_value_type_not_supported_yet();
#pragma clang diagnostic pop
SWIFT_INLINE_THUNK void *_Nonnull opaqueAlloc(size_t size,
size_t align) noexcept {
#if defined(SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_alloc) && \
defined(SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_free)
// Allow the user to provide custom allocator for heap-allocated Swift
// value types.
return SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_alloc(size, align);
#else
#if defined(_WIN32)
void *r = _aligned_malloc(size, align);
#else
if (align < sizeof(void *))
align = sizeof(void *);
void *r = nullptr;
int res = posix_memalign(&r, align, size);
(void)res;
#endif
return r;
#endif
}
SWIFT_INLINE_THUNK void opaqueFree(void *_Nonnull p) noexcept {
#if defined(SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_alloc) && \
defined(SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_free)
// Allow the user to provide custom allocator for heap-allocated Swift
// value types.
SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_free(p);
#else
#if defined(_WIN32)
_aligned_free(p);
#else
free(p);
#endif
#endif
}
/// Base class for a container for an opaque Swift value, like resilient struct.
class OpaqueStorage {
public:
SWIFT_INLINE_THUNK OpaqueStorage() noexcept : storage(nullptr) {}
SWIFT_INLINE_THUNK OpaqueStorage(size_t size, size_t alignment) noexcept
: storage(reinterpret_cast<char *>(opaqueAlloc(size, alignment))) {}
SWIFT_INLINE_THUNK OpaqueStorage(OpaqueStorage &&other) noexcept
: storage(other.storage) {
other.storage = nullptr;
}
OpaqueStorage(const OpaqueStorage &) noexcept = delete;
SWIFT_INLINE_THUNK ~OpaqueStorage() noexcept {
if (storage) {
opaqueFree(static_cast<char *_Nonnull>(storage));
}
}
SWIFT_INLINE_THUNK void operator=(OpaqueStorage &&other) noexcept {
auto temp = storage;
storage = other.storage;
other.storage = temp;
}
void operator=(const OpaqueStorage &) noexcept = delete;
SWIFT_INLINE_THUNK char *_Nonnull getOpaquePointer() noexcept {
return static_cast<char *_Nonnull>(storage);
}
SWIFT_INLINE_THUNK const char *_Nonnull getOpaquePointer() const noexcept {
return static_cast<char *_Nonnull>(storage);
}
private:
char *_Nullable storage;
};
/// Base class for a Swift reference counted class value.
class RefCountedClass {
public:
SWIFT_INLINE_THUNK ~RefCountedClass() { swift_release(_opaquePointer); }
SWIFT_INLINE_THUNK RefCountedClass(const RefCountedClass &other) noexcept
: _opaquePointer(other._opaquePointer) {
swift_retain(_opaquePointer);
}
SWIFT_INLINE_THUNK RefCountedClass(RefCountedClass &&other) noexcept
: _opaquePointer(other._opaquePointer) {
// Moving a Swift class reference is a copy
// in C++. This allows C++ to avoid liveness
// checks to see if the pointer is `null` or not,
// as C++'s move is not consuming, unlike Swift's.
swift_retain(_opaquePointer);
}
SWIFT_INLINE_THUNK RefCountedClass &
operator=(const RefCountedClass &other) noexcept {
swift_retain(other._opaquePointer);
swift_release(_opaquePointer);
_opaquePointer = other._opaquePointer;
return *this;
}
SWIFT_INLINE_THUNK RefCountedClass &
operator=(RefCountedClass &&other) noexcept {
swift_retain(other._opaquePointer);
swift_release(_opaquePointer);
_opaquePointer = other._opaquePointer;
return *this;
}
protected:
SWIFT_INLINE_THUNK RefCountedClass(void *_Nonnull ptr) noexcept
: _opaquePointer(ptr) {}
private:
void *_Nonnull _opaquePointer;
friend class _impl_RefCountedClass;
};
class _impl_RefCountedClass {
public:
static SWIFT_INLINE_THUNK void *_Nonnull getOpaquePointer(
const RefCountedClass &object) {
return object._opaquePointer;
}
static SWIFT_INLINE_THUNK void *_Nonnull &
getOpaquePointerRef(RefCountedClass &object) {
return object._opaquePointer;
}
static SWIFT_INLINE_THUNK void *_Nonnull copyOpaquePointer(
const RefCountedClass &object) {
swift_retain(object._opaquePointer);
return object._opaquePointer;
}
};
} // namespace _impl
/// Swift's Int type.
using Int = ptrdiff_t;
/// Swift's UInt type.
using UInt = size_t;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++17-extensions"
/// True if the given type is a Swift type that can be used in a generic context
/// in Swift.
template <class T>
static inline const constexpr bool isUsableInGenericContext = false;
/// Returns the type metadata for the given Swift type T.
template <class T> struct TypeMetadataTrait {
static SWIFT_INLINE_THUNK void *_Nonnull getTypeMetadata();
};
namespace _impl {
/// Type trait that returns the `_impl::_impl_<T>` class type for the given
/// class T.
template <class T> struct implClassFor {
// using type = ...;
};
/// True if the given type is a Swift value type.
template <class T> static inline const constexpr bool isValueType = false;
/// True if the given type is a Swift value type with opaque layout that can be
/// boxed.
template <class T> static inline const constexpr bool isOpaqueLayout = false;
/// True if the given type is a C++ record that was bridged to Swift, giving
/// Swift ability to work with it in a generic context.
template <class T>
static inline const constexpr bool isSwiftBridgedCxxRecord = false;
/// Returns the opaque pointer to the given value.
template <class T>
SWIFT_INLINE_THUNK const void *_Nonnull getOpaquePointer(const T &value) {
if constexpr (isOpaqueLayout<T>)
return reinterpret_cast<const OpaqueStorage &>(value).getOpaquePointer();
return reinterpret_cast<const void *>(&value);
}
template <class T>
SWIFT_INLINE_THUNK void *_Nonnull getOpaquePointer(T &value) {
if constexpr (isOpaqueLayout<T>)
return reinterpret_cast<OpaqueStorage &>(value).getOpaquePointer();
return reinterpret_cast<void *>(&value);
}
/// Helper struct that destroys any additional storage allocated (e.g. for
/// resilient value types) for a Swift value owned by C++ code after the Swift
/// value was consumed and thus the original C++ destructor is not ran.
template <class T> class ConsumedValueStorageDestroyer {
public:
SWIFT_INLINE_THUNK ConsumedValueStorageDestroyer(T &val) noexcept
: value(val) {}
SWIFT_INLINE_THUNK ~ConsumedValueStorageDestroyer() noexcept {
if constexpr (isOpaqueLayout<T>)
reinterpret_cast<OpaqueStorage &>(value).~OpaqueStorage();
}
private:
T &value;
};
} // namespace _impl
#pragma clang diagnostic pop
} // namespace swift SWIFT_PRIVATE_ATTR
#endif
#endif // SWIFT_CXX_INTEROPERABILITY_H
|