@@ -407,10 +407,10 @@ class alignas(1 << TypeAlignInBits) TypeBase
407407 ID : 32
408408 );
409409
410- SWIFT_INLINE_BITFIELD (SILFunctionType, TypeBase, NumSILExtInfoBits+1 +3 +1 +2 +1 +1 ,
410+ SWIFT_INLINE_BITFIELD (SILFunctionType, TypeBase, NumSILExtInfoBits+1 +4 +1 +2 +1 +1 ,
411411 ExtInfoBits : NumSILExtInfoBits,
412412 HasClangTypeInfo : 1 ,
413- CalleeConvention : 3 ,
413+ CalleeConvention : 4 ,
414414 HasErrorResult : 1 ,
415415 CoroutineKind : 2 ,
416416 HasInvocationSubs : 1 ,
@@ -451,7 +451,17 @@ class alignas(1 << TypeAlignInBits) TypeBase
451451 SWIFT_INLINE_BITFIELD_FULL (PackType, TypeBase, 32 ,
452452 : NumPadBits,
453453
454- // / The number of elements of the tuple.
454+ // / The number of elements of the pack.
455+ Count : 32
456+ );
457+
458+ SWIFT_INLINE_BITFIELD_FULL (SILPackType, TypeBase, 1 +32 ,
459+ // / Whether elements of the pack are addresses.
460+ ElementIsAddress : 1 ,
461+
462+ : NumPadBits,
463+
464+ // / The number of elements of the pack
455465 Count : 32
456466 );
457467
@@ -3777,9 +3787,24 @@ enum class ParameterConvention : uint8_t {
37773787 // / This argument is passed directly. Its type is non-trivial, and the caller
37783788 // / guarantees its validity for the entirety of the call.
37793789 Direct_Guaranteed,
3790+
3791+ // / This argument is a value pack of mutable references to storage,
3792+ // / which the function is being given exclusive access to. The elements
3793+ // / must be passed indirectly.
3794+ Pack_Inout,
3795+
3796+ // / This argument is a value pack, and ownership of the elements is being
3797+ // / transferred into this function. Whether the elements are passed
3798+ // / indirectly is recorded in the pack type.
3799+ Pack_Owned,
3800+
3801+ // / This argument is a value pack, and ownership of the elements is not
3802+ // / being transferred into this function. Whether the elements are passed
3803+ // / indirectly is recorded in the pack type.
3804+ Pack_Guaranteed,
37803805};
37813806// Check that the enum values fit inside Bits.SILFunctionType.
3782- static_assert (unsigned (ParameterConvention::Direct_Guaranteed ) < (1 <<3 ),
3807+ static_assert (unsigned (ParameterConvention::Pack_Guaranteed ) < (1 <<4 ),
37833808 " fits in Bits.SILFunctionType" );
37843809
37853810// Does this parameter convention require indirect storage? This reflects a
@@ -3796,6 +3821,9 @@ inline bool isIndirectFormalParameter(ParameterConvention conv) {
37963821 case ParameterConvention::Direct_Unowned:
37973822 case ParameterConvention::Direct_Guaranteed:
37983823 case ParameterConvention::Direct_Owned:
3824+ case ParameterConvention::Pack_Inout:
3825+ case ParameterConvention::Pack_Owned:
3826+ case ParameterConvention::Pack_Guaranteed:
37993827 return false ;
38003828 }
38013829 llvm_unreachable (" covered switch isn't covered?!" );
@@ -3804,13 +3832,16 @@ inline bool isConsumedParameter(ParameterConvention conv) {
38043832 switch (conv) {
38053833 case ParameterConvention::Indirect_In:
38063834 case ParameterConvention::Direct_Owned:
3835+ case ParameterConvention::Pack_Owned:
38073836 return true ;
38083837
38093838 case ParameterConvention::Indirect_Inout:
38103839 case ParameterConvention::Indirect_InoutAliasable:
38113840 case ParameterConvention::Direct_Unowned:
38123841 case ParameterConvention::Direct_Guaranteed:
38133842 case ParameterConvention::Indirect_In_Guaranteed:
3843+ case ParameterConvention::Pack_Inout:
3844+ case ParameterConvention::Pack_Guaranteed:
38143845 return false ;
38153846 }
38163847 llvm_unreachable (" bad convention kind" );
@@ -3823,11 +3854,34 @@ inline bool isGuaranteedParameter(ParameterConvention conv) {
38233854 switch (conv) {
38243855 case ParameterConvention::Direct_Guaranteed:
38253856 case ParameterConvention::Indirect_In_Guaranteed:
3857+ case ParameterConvention::Pack_Guaranteed:
3858+ return true ;
3859+
3860+ case ParameterConvention::Indirect_Inout:
3861+ case ParameterConvention::Indirect_InoutAliasable:
3862+ case ParameterConvention::Indirect_In:
3863+ case ParameterConvention::Direct_Unowned:
3864+ case ParameterConvention::Direct_Owned:
3865+ case ParameterConvention::Pack_Inout:
3866+ case ParameterConvention::Pack_Owned:
3867+ return false ;
3868+ }
3869+ llvm_unreachable (" bad convention kind" );
3870+ }
3871+
3872+ // / Returns true if conv indicates a pack parameter.
3873+ inline bool isPackParameter (ParameterConvention conv) {
3874+ switch (conv) {
3875+ case ParameterConvention::Pack_Guaranteed:
3876+ case ParameterConvention::Pack_Inout:
3877+ case ParameterConvention::Pack_Owned:
38263878 return true ;
38273879
3880+ case ParameterConvention::Indirect_In_Guaranteed:
38283881 case ParameterConvention::Indirect_Inout:
38293882 case ParameterConvention::Indirect_InoutAliasable:
38303883 case ParameterConvention::Indirect_In:
3884+ case ParameterConvention::Direct_Guaranteed:
38313885 case ParameterConvention::Direct_Unowned:
38323886 case ParameterConvention::Direct_Owned:
38333887 return false ;
@@ -3906,6 +3960,10 @@ class SILParameterInfo {
39063960 || getConvention () == ParameterConvention::Indirect_InoutAliasable;
39073961 }
39083962
3963+ bool isPack () const {
3964+ return isPackParameter (getConvention ());
3965+ }
3966+
39093967 // / True if this parameter is consumed by the callee, either
39103968 // / indirectly or directly.
39113969 bool isConsumed () const {
@@ -4027,11 +4085,18 @@ enum class ResultConvention : uint8_t {
40274085 // / The type must be a class or class existential type, and this
40284086 // / must be the only return value.
40294087 Autoreleased,
4088+
4089+ // / This value is a pack that is returned indirectly by passing a
4090+ // / pack address (which may or may not be further indirected,
4091+ // / depending on the pact type). The callee is responsible for
4092+ // / leaving an initialized object in each element of the pack.
4093+ Pack,
40304094};
40314095
40324096// Does this result require indirect storage for the purpose of reabstraction?
40334097inline bool isIndirectFormalResult (ResultConvention convention) {
4034- return convention == ResultConvention::Indirect;
4098+ return convention == ResultConvention::Indirect ||
4099+ convention == ResultConvention::Pack;
40354100}
40364101
40374102// / The differentiability of a SIL function type result.
@@ -5138,6 +5203,97 @@ class SILTokenType final : public TypeBase {
51385203};
51395204DEFINE_EMPTY_CAN_TYPE_WRAPPER (SILTokenType, Type)
51405205
5206+ // / A lowered pack type which structurally carries lowered information
5207+ // / about the pack elements.
5208+ // /
5209+ // / A value pack is basically treated as a unique-ownership, unmovable
5210+ // / reference-semantics aggregate in SIL: ownership of the pack as a whole
5211+ // / is communicated with normal borrows of the pack, and packs can only
5212+ // / be created locally and forwarded as arguments rather than being moved
5213+ // / in any more complex way.
5214+ class SILPackType final : public TypeBase, public llvm::FoldingSetNode,
5215+ private llvm::TrailingObjects<SILPackType, CanType> {
5216+ public:
5217+ // / Type structure not reflected in the pack element type list.
5218+ // /
5219+ // / In the design of this, we considered storing ownership here,
5220+ // / but ended up just with the one bit.
5221+ struct ExtInfo {
5222+ bool ElementIsAddress;
5223+
5224+ ExtInfo (bool elementIsAddress) : ElementIsAddress(elementIsAddress) {}
5225+ };
5226+
5227+ private:
5228+ friend TrailingObjects;
5229+ friend class ASTContext ;
5230+ SILPackType (const ASTContext &ctx, RecursiveTypeProperties properties,
5231+ ExtInfo info, ArrayRef<CanType> elements)
5232+ : TypeBase (TypeKind::SILPack, &ctx, properties) {
5233+ Bits.SILPackType .Count = elements.size ();
5234+ Bits.SILPackType .ElementIsAddress = info.ElementIsAddress ;
5235+ memcpy (getTrailingObjects<CanType>(), elements.data (),
5236+ elements.size () * sizeof (CanType));
5237+ }
5238+
5239+ public:
5240+ static CanTypeWrapper<SILPackType> get (const ASTContext &ctx,
5241+ ExtInfo info,
5242+ ArrayRef<CanType> elements);
5243+
5244+ ExtInfo getExtInfo () const {
5245+ return { isElementAddress () };
5246+ }
5247+
5248+ bool isElementAddress () const {
5249+ return Bits.SILPackType .ElementIsAddress ;
5250+ }
5251+
5252+ // / Retrieves the number of elements in this pack.
5253+ unsigned getNumElements () const { return Bits.SILPackType .Count ; }
5254+
5255+ // / Retrieves the type of the elements in the pack.
5256+ ArrayRef<CanType> getElementTypes () const {
5257+ return {getTrailingObjects<CanType>(), getNumElements ()};
5258+ }
5259+
5260+ // / Returns the type of the element at the given \p index.
5261+ // / This is a lowered SIL type.
5262+ CanType getElementType (unsigned index) const {
5263+ return getTrailingObjects<CanType>()[index];
5264+ }
5265+
5266+ SILType getSILElementType (unsigned index) const ; // in SILType.h
5267+
5268+ // / Return the reduced shape of this pack. For consistency with
5269+ // / general shape-handling routines, we produce an AST pack type
5270+ // / as the shape, not a SIL pack type.
5271+ CanTypeWrapper<PackType> getReducedShape () const ;
5272+
5273+ bool containsPackExpansionType () const ;
5274+
5275+ void Profile (llvm::FoldingSetNodeID &ID) const {
5276+ Profile (ID, getExtInfo (), getElementTypes ());
5277+ }
5278+ static void Profile (llvm::FoldingSetNodeID &ID,
5279+ ExtInfo info,
5280+ ArrayRef<CanType> elements);
5281+
5282+ // Implement isa/cast/dyncast/etc.
5283+ static bool classof (const TypeBase *T) {
5284+ return T->getKind () == TypeKind::SILPack;
5285+ }
5286+ };
5287+ BEGIN_CAN_TYPE_WRAPPER (SILPackType, Type)
5288+ CanType getElementType(unsigned elementNo) const {
5289+ return getPointer ()->getElementType (elementNo);
5290+ }
5291+
5292+ ArrayRef<CanType> getElementTypes () const {
5293+ return getPointer ()->getElementTypes ();
5294+ }
5295+ END_CAN_TYPE_WRAPPER (SILPackType, Type)
5296+
51415297// / A type with a special syntax that is always sugar for a library type. The
51425298// / library type may have multiple base types. For unary syntax sugar, see
51435299// / UnarySyntaxSugarType.
@@ -6654,6 +6810,8 @@ class PackExpansionType : public TypeBase, public llvm::FoldingSetNode {
66546810 const ASTContext *ctx);
66556811};
66566812BEGIN_CAN_TYPE_WRAPPER (PackExpansionType, Type)
6813+ static CanPackExpansionType get (CanType pattern, CanType countType);
6814+
66576815 CanType getPatternType () const {
66586816 return CanType (getPointer ()->getPatternType ());
66596817 }
0 commit comments