@@ -30,6 +30,38 @@ struct TargetProtocolConformanceDescriptor;
3030template <typename Runtime>
3131struct TargetGenericContext ;
3232
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+
3365template <typename Runtime>
3466struct TargetGenericContextDescriptorHeader {
3567 // / The number of (source-written) generic parameters, and thus
@@ -39,8 +71,8 @@ struct TargetGenericContextDescriptorHeader {
3971 // /
4072 // / A GenericParamDescriptor corresponds to a type metadata pointer
4173 // / 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.
4476 uint16_t NumParams;
4577
4678 // / The number of GenericRequirementDescriptors in this generic
@@ -66,18 +98,22 @@ struct TargetGenericContextDescriptorHeader {
6698 // / hasKeyArgument()).
6799 uint16_t NumKeyArguments;
68100
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
70102 // / layout, in words. The idea was that extra arguments would
71103 // / include generic parameters and conformances that are not part
72104 // / 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 ;
78110
79111 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;
81117 }
82118
83119 // / Return the total size of the argument layout, in words.
@@ -163,7 +199,7 @@ class TargetGenericRequirementDescriptor {
163199 return offsetof (typename std::remove_reference<decltype (*this )>::type, Type);
164200 }
165201
166- // / Retreive the offset to the Type field
202+ // / Retreive the offset to the Param field
167203 constexpr inline auto
168204 getParamOffset () const -> typename Runtime::StoredSize {
169205 return offsetof (typename std::remove_reference<decltype (*this )>::type, Param);
@@ -199,6 +235,7 @@ class TargetGenericRequirementDescriptor {
199235 case GenericRequirementKind::Protocol:
200236 case GenericRequirementKind::SameConformance:
201237 case GenericRequirementKind::SameType:
238+ case GenericRequirementKind::SameShape:
202239 return true ;
203240 }
204241
@@ -208,6 +245,53 @@ class TargetGenericRequirementDescriptor {
208245using GenericRequirementDescriptor =
209246 TargetGenericRequirementDescriptor<InProcess>;
210247
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+
211295// / An array of generic parameter descriptors, all
212296// / GenericParamDescriptor::implicit(), which is by far
213297// / the most common case. Some generic context storage can
@@ -243,14 +327,21 @@ class RuntimeGenericSignature {
243327 TargetGenericContextDescriptorHeader<Runtime> Header;
244328 const GenericParamDescriptor *Params;
245329 const TargetGenericRequirementDescriptor<Runtime> *Requirements;
330+ GenericPackShapeHeader PackShapeHeader;
331+ const GenericPackShapeDescriptor *PackShapeDescriptors;
332+
246333public:
247334 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 ) {}
249337
250338 RuntimeGenericSignature (const TargetGenericContextDescriptorHeader<Runtime> &header,
251339 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) {}
254345
255346 llvm::ArrayRef<GenericParamDescriptor> getParams () const {
256347 return llvm::makeArrayRef (Params, Header.NumParams );
@@ -260,6 +351,14 @@ class RuntimeGenericSignature {
260351 return llvm::makeArrayRef (Requirements, Header.NumRequirements );
261352 }
262353
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+
263362 size_t getArgumentLayoutSizeInWords () const {
264363 return Header.getArgumentLayoutSizeInWords ();
265364 }
@@ -350,6 +449,8 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
350449 TargetGenericContextHeaderType<Runtime>,
351450 GenericParamDescriptor,
352451 TargetGenericRequirementDescriptor<Runtime>,
452+ GenericPackShapeHeader,
453+ GenericPackShapeDescriptor,
353454 FollowingTrailingObjects...>
354455{
355456protected:
@@ -362,6 +463,8 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
362463 GenericContextHeaderType,
363464 GenericParamDescriptor,
364465 GenericRequirementDescriptor,
466+ GenericPackShapeHeader,
467+ GenericPackShapeDescriptor,
365468 FollowingTrailingObjects...>;
366469 friend TrailingObjects;
367470
@@ -415,6 +518,23 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
415518 return {this ->template getTrailingObjects <GenericRequirementDescriptor>(),
416519 getGenericContextHeader ().NumRequirements };
417520 }
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+ }
418538
419539 // / Return the amount of space that the generic arguments take up in
420540 // / metadata of this type.
@@ -427,7 +547,9 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
427547 if (!asSelf ()->isGeneric ()) return RuntimeGenericSignature<Runtime>();
428548 return {getGenericContextHeader (),
429549 getGenericParams ().data (),
430- getGenericRequirements ().data ()};
550+ getGenericRequirements ().data (),
551+ getGenericPackShapeHeader (),
552+ getGenericPackShapeDescriptors ().data ()};
431553 }
432554
433555protected:
@@ -443,6 +565,23 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
443565 return asSelf ()->isGeneric () ? getGenericContextHeader ().NumRequirements : 0 ;
444566 }
445567
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+
446585#if defined(_MSC_VER) && _MSC_VER < 1920
447586#undef OverloadToken
448587#endif
0 commit comments