-
Notifications
You must be signed in to change notification settings - Fork 10.4k
/
Copy path_SwiftCxxInteroperability.h
319 lines (274 loc) · 10.9 KB
/
_SwiftCxxInteroperability.h
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