|
18 | 18 | #define SWIFT_ABI_METADATA_H
|
19 | 19 |
|
20 | 20 | #include <atomic>
|
21 |
| -#include <cassert> |
22 |
| -#include <climits> |
23 |
| -#include <cstddef> |
24 |
| -#include <cstdint> |
25 | 21 | #include <iterator>
|
26 | 22 | #include <string>
|
27 | 23 | #include <type_traits>
|
|
35 | 31 | #include "swift/ABI/System.h"
|
36 | 32 | #include "swift/ABI/TargetLayout.h"
|
37 | 33 | #include "swift/ABI/TrailingObjects.h"
|
| 34 | +#include "swift/ABI/ValueWitnessTable.h" |
38 | 35 | #include "swift/Basic/Malloc.h"
|
39 | 36 | #include "swift/Basic/FlaggedPointer.h"
|
40 | 37 | #include "swift/Basic/RelativePointer.h"
|
@@ -147,201 +144,6 @@ struct MetadataDependency {
|
147 | 144 |
|
148 | 145 | template <typename Runtime> struct TargetProtocolConformanceDescriptor;
|
149 | 146 |
|
150 |
| -/// Storage for an arbitrary value. In C/C++ terms, this is an |
151 |
| -/// 'object', because it is rooted in memory. |
152 |
| -/// |
153 |
| -/// The context dictates what type is actually stored in this object, |
154 |
| -/// and so this type is intentionally incomplete. |
155 |
| -/// |
156 |
| -/// An object can be in one of two states: |
157 |
| -/// - An uninitialized object has a completely unspecified state. |
158 |
| -/// - An initialized object holds a valid value of the type. |
159 |
| -struct OpaqueValue; |
160 |
| - |
161 |
| -/// A fixed-size buffer for local values. It is capable of owning |
162 |
| -/// (possibly in side-allocated memory) the storage necessary |
163 |
| -/// to hold a value of an arbitrary type. Because it is fixed-size, |
164 |
| -/// it can be allocated in places that must be agnostic to the |
165 |
| -/// actual type: for example, within objects of existential type, |
166 |
| -/// or for local variables in generic functions. |
167 |
| -/// |
168 |
| -/// The context dictates its type, which ultimately means providing |
169 |
| -/// access to a value witness table by which the value can be |
170 |
| -/// accessed and manipulated. |
171 |
| -/// |
172 |
| -/// A buffer can directly store three pointers and is pointer-aligned. |
173 |
| -/// Three pointers is a sweet spot for Swift, because it means we can |
174 |
| -/// store a structure containing a pointer, a size, and an owning |
175 |
| -/// object, which is a common pattern in code due to ARC. In a GC |
176 |
| -/// environment, this could be reduced to two pointers without much loss. |
177 |
| -/// |
178 |
| -/// A buffer can be in one of three states: |
179 |
| -/// - An unallocated buffer has a completely unspecified state. |
180 |
| -/// - An allocated buffer has been initialized so that it |
181 |
| -/// owns uninitialized value storage for the stored type. |
182 |
| -/// - An initialized buffer is an allocated buffer whose value |
183 |
| -/// storage has been initialized. |
184 |
| -template <typename Runtime> |
185 |
| -struct TargetValueBuffer { |
186 |
| - TargetPointer<Runtime, void> PrivateData[NumWords_ValueBuffer]; |
187 |
| -}; |
188 |
| -using ValueBuffer = TargetValueBuffer<InProcess>; |
189 |
| - |
190 |
| -/// Can a value with the given size and alignment be allocated inline? |
191 |
| -constexpr inline bool canBeInline(bool isBitwiseTakable, size_t size, |
192 |
| - size_t alignment) { |
193 |
| - return isBitwiseTakable && size <= sizeof(ValueBuffer) && |
194 |
| - alignment <= alignof(ValueBuffer); |
195 |
| -} |
196 |
| - |
197 |
| -template <class T> |
198 |
| -constexpr inline bool canBeInline(bool isBitwiseTakable) { |
199 |
| - return canBeInline(isBitwiseTakable, sizeof(T), alignof(T)); |
200 |
| -} |
201 |
| - |
202 |
| -template <typename Runtime> struct TargetValueWitnessTable; |
203 |
| -using ValueWitnessTable = TargetValueWitnessTable<InProcess>; |
204 |
| - |
205 |
| -template <typename Runtime> class TargetValueWitnessTypes; |
206 |
| -using ValueWitnessTypes = TargetValueWitnessTypes<InProcess>; |
207 |
| - |
208 |
| -template <typename Runtime> |
209 |
| -class TargetValueWitnessTypes { |
210 |
| -public: |
211 |
| - using StoredPointer = typename Runtime::StoredPointer; |
212 |
| - |
213 |
| -// Note that, for now, we aren't strict about 'const'. |
214 |
| -#define WANT_ALL_VALUE_WITNESSES |
215 |
| -#define DATA_VALUE_WITNESS(lowerId, upperId, type) |
216 |
| -#define FUNCTION_VALUE_WITNESS(lowerId, upperId, returnType, paramTypes) \ |
217 |
| - typedef returnType (*lowerId ## Unsigned) paramTypes; \ |
218 |
| - typedef TargetSignedPointer<Runtime, lowerId ## Unsigned \ |
219 |
| - __ptrauth_swift_value_witness_function_pointer( \ |
220 |
| - SpecialPointerAuthDiscriminators::upperId)> lowerId; |
221 |
| -#define MUTABLE_VALUE_TYPE TargetPointer<Runtime, OpaqueValue> |
222 |
| -#define IMMUTABLE_VALUE_TYPE ConstTargetPointer<Runtime, OpaqueValue> |
223 |
| -#define MUTABLE_BUFFER_TYPE TargetPointer<Runtime, ValueBuffer> |
224 |
| -#define IMMUTABLE_BUFFER_TYPE ConstTargetPointer<Runtime, ValueBuffer> |
225 |
| -#define TYPE_TYPE ConstTargetPointer<Runtime, Metadata> |
226 |
| -#define SIZE_TYPE StoredSize |
227 |
| -#define INT_TYPE int |
228 |
| -#define UINT_TYPE unsigned |
229 |
| -#define VOID_TYPE void |
230 |
| -#include "swift/ABI/ValueWitness.def" |
231 |
| - |
232 |
| - // Handle the data witnesses explicitly so we can use more specific |
233 |
| - // types for the flags enums. |
234 |
| - typedef size_t size; |
235 |
| - typedef size_t stride; |
236 |
| - typedef ValueWitnessFlags flags; |
237 |
| - typedef uint32_t extraInhabitantCount; |
238 |
| -}; |
239 |
| - |
240 |
| -struct TypeLayout; |
241 |
| - |
242 |
| -/// A value-witness table. A value witness table is built around |
243 |
| -/// the requirements of some specific type. The information in |
244 |
| -/// a value-witness table is intended to be sufficient to lay out |
245 |
| -/// and manipulate values of an arbitrary type. |
246 |
| -template <typename Runtime> struct TargetValueWitnessTable { |
247 |
| - // For the meaning of all of these witnesses, consult the comments |
248 |
| - // on their associated typedefs, above. |
249 |
| - |
250 |
| -#define WANT_ONLY_REQUIRED_VALUE_WITNESSES |
251 |
| -#define VALUE_WITNESS(LOWER_ID, UPPER_ID) \ |
252 |
| - typename TargetValueWitnessTypes<Runtime>::LOWER_ID LOWER_ID; |
253 |
| -#define FUNCTION_VALUE_WITNESS(LOWER_ID, UPPER_ID, RET, PARAMS) \ |
254 |
| - typename TargetValueWitnessTypes<Runtime>::LOWER_ID LOWER_ID; |
255 |
| - |
256 |
| -#include "swift/ABI/ValueWitness.def" |
257 |
| - |
258 |
| - using StoredSize = typename Runtime::StoredSize; |
259 |
| - |
260 |
| - /// Is the external type layout of this type incomplete? |
261 |
| - bool isIncomplete() const { |
262 |
| - return flags.isIncomplete(); |
263 |
| - } |
264 |
| - |
265 |
| - /// Would values of a type with the given layout requirements be |
266 |
| - /// allocated inline? |
267 |
| - static bool isValueInline(bool isBitwiseTakable, StoredSize size, |
268 |
| - StoredSize alignment) { |
269 |
| - return (isBitwiseTakable && size <= sizeof(TargetValueBuffer<Runtime>) && |
270 |
| - alignment <= alignof(TargetValueBuffer<Runtime>)); |
271 |
| - } |
272 |
| - |
273 |
| - /// Are values of this type allocated inline? |
274 |
| - bool isValueInline() const { |
275 |
| - return flags.isInlineStorage(); |
276 |
| - } |
277 |
| - |
278 |
| - /// Is this type POD? |
279 |
| - bool isPOD() const { |
280 |
| - return flags.isPOD(); |
281 |
| - } |
282 |
| - |
283 |
| - /// Is this type bitwise-takable? |
284 |
| - bool isBitwiseTakable() const { |
285 |
| - return flags.isBitwiseTakable(); |
286 |
| - } |
287 |
| - |
288 |
| - /// Return the size of this type. Unlike in C, this has not been |
289 |
| - /// padded up to the alignment; that value is maintained as |
290 |
| - /// 'stride'. |
291 |
| - StoredSize getSize() const { |
292 |
| - return size; |
293 |
| - } |
294 |
| - |
295 |
| - /// Return the stride of this type. This is the size rounded up to |
296 |
| - /// be a multiple of the alignment. |
297 |
| - StoredSize getStride() const { |
298 |
| - return stride; |
299 |
| - } |
300 |
| - |
301 |
| - /// Return the alignment required by this type, in bytes. |
302 |
| - StoredSize getAlignment() const { |
303 |
| - return flags.getAlignment(); |
304 |
| - } |
305 |
| - |
306 |
| - /// The alignment mask of this type. An offset may be rounded up to |
307 |
| - /// the required alignment by adding this mask and masking by its |
308 |
| - /// bit-negation. |
309 |
| - /// |
310 |
| - /// For example, if the type needs to be 8-byte aligned, the value |
311 |
| - /// of this witness is 0x7. |
312 |
| - StoredSize getAlignmentMask() const { |
313 |
| - return flags.getAlignmentMask(); |
314 |
| - } |
315 |
| - |
316 |
| - /// The number of extra inhabitants, that is, bit patterns that do not form |
317 |
| - /// valid values of the type, in this type's binary representation. |
318 |
| - unsigned getNumExtraInhabitants() const { |
319 |
| - return extraInhabitantCount; |
320 |
| - } |
321 |
| - |
322 |
| - /// Assert that this value witness table is an enum value witness table |
323 |
| - /// and return it as such. |
324 |
| - /// |
325 |
| - /// This has an awful name because it's supposed to be internal to |
326 |
| - /// this file. Code outside this file should use LLVM's cast/dyn_cast. |
327 |
| - /// We don't want to use those here because we need to avoid accidentally |
328 |
| - /// introducing ABI dependencies on LLVM structures. |
329 |
| - const struct EnumValueWitnessTable *_asEVWT() const; |
330 |
| - |
331 |
| - /// Get the type layout record within this value witness table. |
332 |
| - const TypeLayout *getTypeLayout() const { |
333 |
| - return reinterpret_cast<const TypeLayout *>(&size); |
334 |
| - } |
335 |
| - |
336 |
| - /// Check whether this metadata is complete. |
337 |
| - bool checkIsComplete() const; |
338 |
| - |
339 |
| - /// "Publish" the layout of this type to other threads. All other stores |
340 |
| - /// to the value witness table (including its extended header) should have |
341 |
| - /// happened before this is called. |
342 |
| - void publishLayout(const TypeLayout &layout); |
343 |
| -}; |
344 |
| - |
345 | 147 | /// The header before a metadata object which appears on all type
|
346 | 148 | /// metadata. Note that heap metadata are not necessarily type
|
347 | 149 | /// metadata, even for objects of a heap type: for example, objects of
|
|
0 commit comments