|
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