@@ -30,6 +30,38 @@ struct TargetProtocolConformanceDescriptor;
30
30
template <typename Runtime>
31
31
struct TargetGenericContext ;
32
32
33
+ class GenericContextDescriptorFlags {
34
+ uint16_t Value;
35
+
36
+ public:
37
+ constexpr GenericContextDescriptorFlags () : Value(0 ) {}
38
+
39
+ explicit constexpr GenericContextDescriptorFlags (uint16_t value)
40
+ : Value(value) {}
41
+
42
+ constexpr GenericContextDescriptorFlags (bool hasTypePacks)
43
+ : GenericContextDescriptorFlags(
44
+ GenericContextDescriptorFlags ((uint16_t )0)
45
+ .withHasTypePacks(hasTypePacks)) {}
46
+
47
+ // / Whether this generic context has at least one type parameter
48
+ // / pack, in which case the generic context will have a trailing
49
+ // / GenericPackShapeHeader.
50
+ constexpr bool hasTypePacks () const {
51
+ return (Value & 0x1 ) != 0 ;
52
+ }
53
+
54
+ constexpr GenericContextDescriptorFlags
55
+ withHasTypePacks (bool hasTypePacks) const {
56
+ return GenericContextDescriptorFlags ((uint16_t )(
57
+ (Value & ~0x1 ) | (hasTypePacks ? 0x1 : 0 )));
58
+ }
59
+
60
+ constexpr uint16_t getIntValue () const {
61
+ return Value;
62
+ }
63
+ };
64
+
33
65
template <typename Runtime>
34
66
struct TargetGenericContextDescriptorHeader {
35
67
// / The number of (source-written) generic parameters, and thus
@@ -39,8 +71,8 @@ struct TargetGenericContextDescriptorHeader {
39
71
// /
40
72
// / A GenericParamDescriptor corresponds to a type metadata pointer
41
73
// / in the arguments layout when isKeyArgument() is true.
42
- // / isKeyArgument() will be false if the parameter has been unified
43
- // / unified with a different parameter or an associated type.
74
+ // / isKeyArgument() will be false if the parameter has been made
75
+ // / equivalent to a different parameter or a concrete type.
44
76
uint16_t NumParams;
45
77
46
78
// / The number of GenericRequirementDescriptors in this generic
@@ -66,18 +98,22 @@ struct TargetGenericContextDescriptorHeader {
66
98
// / hasKeyArgument()).
67
99
uint16_t NumKeyArguments;
68
100
69
- // / In principle, the size of the "extra" area of the argument
101
+ // / Originally this was the size of the "extra" area of the argument
70
102
// / layout, in words. The idea was that extra arguments would
71
103
// / include generic parameters and conformances that are not part
72
104
// / of the identity of the context; however, it's unclear why we
73
- // / would ever want such a thing. As a result, this section is
74
- // / unused, and this field is always zero. It can be repurposed
75
- // / as long as it remains zero in code which must be compatible
76
- // / with existing Swift runtimes.
77
- uint16_t NumExtraArguments ;
105
+ // / would ever want such a thing. As a result, in pre-5.8 runtimes
106
+ // / this field is always zero. New flags can only be added as long
107
+ // / as they remains zero in code which must be compatible with
108
+ // / older Swift runtimes.
109
+ GenericContextDescriptorFlags Flags ;
78
110
79
111
uint32_t getNumArguments () const {
80
- return NumKeyArguments + NumExtraArguments;
112
+ // Note: this used to be NumKeyArguments + NumExtraArguments,
113
+ // and flags was named NumExtraArguments, which is why Flags
114
+ // must remain zero when backward deploying to Swift 5.7 or
115
+ // earlier.
116
+ return NumKeyArguments;
81
117
}
82
118
83
119
// / Return the total size of the argument layout, in words.
@@ -163,7 +199,7 @@ class TargetGenericRequirementDescriptor {
163
199
return offsetof (typename std::remove_reference<decltype (*this )>::type, Type);
164
200
}
165
201
166
- // / Retreive the offset to the Type field
202
+ // / Retreive the offset to the Param field
167
203
constexpr inline auto
168
204
getParamOffset () const -> typename Runtime::StoredSize {
169
205
return offsetof (typename std::remove_reference<decltype (*this )>::type, Param);
@@ -199,6 +235,7 @@ class TargetGenericRequirementDescriptor {
199
235
case GenericRequirementKind::Protocol:
200
236
case GenericRequirementKind::SameConformance:
201
237
case GenericRequirementKind::SameType:
238
+ case GenericRequirementKind::SameShape:
202
239
return true ;
203
240
}
204
241
@@ -208,6 +245,53 @@ class TargetGenericRequirementDescriptor {
208
245
using GenericRequirementDescriptor =
209
246
TargetGenericRequirementDescriptor<InProcess>;
210
247
248
+ struct GenericPackShapeHeader {
249
+ // / The number of generic parameters and conformance requirements
250
+ // / which are packs.
251
+ // /
252
+ // / Must equal the sum of:
253
+ // / - the number of GenericParamDescriptors whose kind is
254
+ // / GenericParamKind::TypePack and isKeyArgument bits set;
255
+ // / - the number of GenericRequirementDescriptors with the
256
+ // / isPackRequirement and isKeyArgument bits set
257
+ uint16_t NumPacks;
258
+
259
+ // / The number of equivalence classes in the same-shape relation.
260
+ uint16_t NumShapeClasses;
261
+ };
262
+
263
+ enum class GenericPackKind : uint16_t {
264
+ Metadata = 0 ,
265
+ WitnessTable = 1
266
+ };
267
+
268
+ // / The GenericPackShapeHeader is followed by an array of these descriptors,
269
+ // / whose length is given by the header's NumPacks field.
270
+ // /
271
+ // / The invariant is that all pack descriptors with GenericPackKind::Metadata
272
+ // / must precede those with GenericPackKind::WitnessTable, and for each kind,
273
+ // / the pack descriptors are ordered by their Index.
274
+ // /
275
+ // / This allows us to iterate over the generic arguments array in parallel
276
+ // / with the array of pack shape descriptors. We know we have a metadata
277
+ // / or witness table when we reach the generic argument whose index is
278
+ // / stored in the next descriptor; we increment the descriptor pointer in
279
+ // / this case.
280
+ struct GenericPackShapeDescriptor {
281
+ GenericPackKind Kind;
282
+
283
+ // / The index of this metadata pack or witness table pack in the
284
+ // / generic arguments array.
285
+ uint16_t Index;
286
+
287
+ // / The equivalence class of this pack under the same-shape relation.
288
+ // /
289
+ // / Must be less than GenericPackShapeHeader::NumShapeClasses.
290
+ uint16_t ShapeClass;
291
+
292
+ uint16_t Unused;
293
+ };
294
+
211
295
// / An array of generic parameter descriptors, all
212
296
// / GenericParamDescriptor::implicit(), which is by far
213
297
// / the most common case. Some generic context storage can
@@ -243,14 +327,21 @@ class RuntimeGenericSignature {
243
327
TargetGenericContextDescriptorHeader<Runtime> Header;
244
328
const GenericParamDescriptor *Params;
245
329
const TargetGenericRequirementDescriptor<Runtime> *Requirements;
330
+ GenericPackShapeHeader PackShapeHeader;
331
+ const GenericPackShapeDescriptor *PackShapeDescriptors;
332
+
246
333
public:
247
334
RuntimeGenericSignature ()
248
- : Header{0 , 0 , 0 , 0 }, Params(nullptr ), Requirements(nullptr ) {}
335
+ : Header{0 , 0 , 0 , 0 }, Params(nullptr ), Requirements(nullptr ),
336
+ PackShapeHeader{0 , 0 }, PackShapeDescriptors(nullptr ) {}
249
337
250
338
RuntimeGenericSignature (const TargetGenericContextDescriptorHeader<Runtime> &header,
251
339
const GenericParamDescriptor *params,
252
- const TargetGenericRequirementDescriptor<Runtime> *requirements)
253
- : Header(header), Params(params), Requirements(requirements) {}
340
+ const TargetGenericRequirementDescriptor<Runtime> *requirements,
341
+ const GenericPackShapeHeader &packShapeHeader,
342
+ const GenericPackShapeDescriptor *packShapeDescriptors)
343
+ : Header(header), Params(params), Requirements(requirements),
344
+ PackShapeHeader (packShapeHeader), PackShapeDescriptors(packShapeDescriptors) {}
254
345
255
346
llvm::ArrayRef<GenericParamDescriptor> getParams () const {
256
347
return llvm::makeArrayRef (Params, Header.NumParams );
@@ -260,6 +351,14 @@ class RuntimeGenericSignature {
260
351
return llvm::makeArrayRef (Requirements, Header.NumRequirements );
261
352
}
262
353
354
+ const GenericPackShapeHeader &getGenericPackShapeHeader () const {
355
+ return PackShapeHeader;
356
+ }
357
+
358
+ llvm::ArrayRef<GenericPackShapeDescriptor> getGenericPackShapeDescriptors () const {
359
+ return llvm::makeArrayRef (PackShapeDescriptors, PackShapeHeader.NumPacks );
360
+ }
361
+
263
362
size_t getArgumentLayoutSizeInWords () const {
264
363
return Header.getArgumentLayoutSizeInWords ();
265
364
}
@@ -350,6 +449,8 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
350
449
TargetGenericContextHeaderType<Runtime>,
351
450
GenericParamDescriptor,
352
451
TargetGenericRequirementDescriptor<Runtime>,
452
+ GenericPackShapeHeader,
453
+ GenericPackShapeDescriptor,
353
454
FollowingTrailingObjects...>
354
455
{
355
456
protected:
@@ -362,6 +463,8 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
362
463
GenericContextHeaderType,
363
464
GenericParamDescriptor,
364
465
GenericRequirementDescriptor,
466
+ GenericPackShapeHeader,
467
+ GenericPackShapeDescriptor,
365
468
FollowingTrailingObjects...>;
366
469
friend TrailingObjects;
367
470
@@ -415,6 +518,23 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
415
518
return {this ->template getTrailingObjects <GenericRequirementDescriptor>(),
416
519
getGenericContextHeader ().NumRequirements };
417
520
}
521
+
522
+ GenericPackShapeHeader getGenericPackShapeHeader () const {
523
+ if (!asSelf ()->isGeneric ())
524
+ return {0 , 0 };
525
+ if (!getGenericContextHeader ().Flags .hasTypePacks ())
526
+ return {0 , 0 };
527
+ return *this ->template getTrailingObjects <GenericPackShapeHeader>();
528
+ }
529
+
530
+ llvm::ArrayRef<GenericPackShapeDescriptor> getGenericPackShapeDescriptors () const {
531
+ auto header = getGenericPackShapeHeader ();
532
+ if (header.NumPacks == 0 )
533
+ return {};
534
+
535
+ return {this ->template getTrailingObjects <GenericPackShapeDescriptor>(),
536
+ header.NumPacks };
537
+ }
418
538
419
539
// / Return the amount of space that the generic arguments take up in
420
540
// / metadata of this type.
@@ -427,7 +547,9 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
427
547
if (!asSelf ()->isGeneric ()) return RuntimeGenericSignature<Runtime>();
428
548
return {getGenericContextHeader (),
429
549
getGenericParams ().data (),
430
- getGenericRequirements ().data ()};
550
+ getGenericRequirements ().data (),
551
+ getGenericPackShapeHeader (),
552
+ getGenericPackShapeDescriptors ().data ()};
431
553
}
432
554
433
555
protected:
@@ -443,6 +565,23 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
443
565
return asSelf ()->isGeneric () ? getGenericContextHeader ().NumRequirements : 0 ;
444
566
}
445
567
568
+ size_t numTrailingObjects (OverloadToken<GenericPackShapeHeader>) const {
569
+ if (!asSelf ()->isGeneric ())
570
+ return 0 ;
571
+
572
+ return getGenericContextHeader ().Flags .hasTypePacks () ? 1 : 0 ;
573
+ }
574
+
575
+ size_t numTrailingObjects (OverloadToken<GenericPackShapeDescriptor>) const {
576
+ if (!asSelf ()->isGeneric ())
577
+ return 0 ;
578
+
579
+ if (!getGenericContextHeader ().Flags .hasTypePacks ())
580
+ return 0 ;
581
+
582
+ return getGenericPackShapeHeader ().NumPacks ;
583
+ }
584
+
446
585
#if defined(_MSC_VER) && _MSC_VER < 1920
447
586
#undef OverloadToken
448
587
#endif
0 commit comments