Files
swift-mirror/lib/PrintAsClang/_SwiftCxxInteroperability.h

320 lines
11 KiB
C++

//===--- _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