@@ -49,15 +49,96 @@ static void diagnose(ASTContext &Context, SourceLoc loc, Diag<T...> diag,
4949void Initialization::_anchor () {}
5050void SILDebuggerClient::anchor () {}
5151
52+ static void copyOrInitPackExpansionInto (SILGenFunction &SGF,
53+ SILLocation loc,
54+ SILValue tupleAddr,
55+ CanPackType formalPackType,
56+ unsigned componentIndex,
57+ CleanupHandle componentCleanup,
58+ Initialization *expansionInit,
59+ bool isInit) {
60+ auto expansionTy = tupleAddr->getType ().getTupleElementType (componentIndex);
61+ assert (expansionTy.is <PackExpansionType>());
62+
63+ auto opening = SGF.createOpenedElementValueEnvironment (expansionTy);
64+ auto openedEnv = opening.first ;
65+ auto eltTy = opening.second ;
66+
67+ assert (expansionInit);
68+ assert (expansionInit->canPerformPackExpansionInitialization ());
69+
70+ // Exit the component-wide cleanup for the expansion component.
71+ if (componentCleanup.isValid ())
72+ SGF.Cleanups .forwardCleanup (componentCleanup);
73+
74+ SGF.emitDynamicPackLoop (loc, formalPackType, componentIndex, openedEnv,
75+ [&](SILValue indexWithinComponent,
76+ SILValue packExpansionIndex,
77+ SILValue packIndex) {
78+ expansionInit->performPackExpansionInitialization (SGF, loc,
79+ indexWithinComponent,
80+ [&](Initialization *eltInit) {
81+ // Project the current tuple element.
82+ auto eltAddr =
83+ SGF.B .createTuplePackElementAddr (loc, packIndex, tupleAddr, eltTy);
84+
85+ SILValue elt = eltAddr;
86+ if (!eltTy.isAddressOnly (SGF.F )) {
87+ elt = SGF.B .emitLoadValueOperation (loc, elt,
88+ LoadOwnershipQualifier::Take);
89+ }
90+
91+ // Enter a cleanup for the current element, which we need to consume
92+ // on this iteration of the loop, and the remaining elements in the
93+ // expansion component, which we need to destroy if we throw from
94+ // the initialization.
95+ CleanupHandle eltCleanup = CleanupHandle::invalid ();
96+ CleanupHandle tailCleanup = CleanupHandle::invalid ();
97+ if (componentCleanup.isValid ()) {
98+ eltCleanup = SGF.enterDestroyCleanup (elt);
99+ tailCleanup = SGF.enterPartialDestroyRemainingTupleCleanup (tupleAddr,
100+ formalPackType, componentIndex, indexWithinComponent);
101+ }
102+
103+ auto eltMV = ManagedValue (elt, eltCleanup);
104+
105+ // Perform the initialization. If this doesn't consume the
106+ // element value, that's fine, we'll just destroy it as part of
107+ // leaving the iteration.
108+ eltInit->copyOrInitValueInto (SGF, loc, eltMV, isInit);
109+
110+ // Deactivate the tail cleanup before continuing the loop.
111+ if (tailCleanup.isValid ())
112+ SGF.Cleanups .forwardCleanup (tailCleanup);
113+ });
114+ });
115+
116+ expansionInit->finishInitialization (SGF);
117+ }
118+
52119void TupleInitialization::copyOrInitValueInto (SILGenFunction &SGF,
53120 SILLocation loc,
54121 ManagedValue value, bool isInit) {
55- // Process all values before initialization all at once to ensure all cleanups
56- // are setup on all tuple elements before a potential early exit.
122+ auto sourceType = value.getType ().castTo <TupleType>();
123+ assert (sourceType->getNumElements () == SubInitializations.size ());
124+
125+ // We have to emit a different pattern when there are pack expansions.
126+ // Fortunately, we can assume this doesn't happen with objects because
127+ // tuples contain pack expansions are address-only.
128+ auto containsPackExpansion = sourceType.containsPackExpansionType ();
129+
130+ CanPackType formalPackType;
131+ if (containsPackExpansion)
132+ formalPackType = FormalTupleType.getInducedPackType ();
133+
134+ // Process all values before initialization all at once to ensure
135+ // all cleanups are setup on all tuple elements before a potential
136+ // early exit.
57137 SmallVector<ManagedValue, 8 > destructuredValues;
58138
59- // In the object case, emit a destructure operation and return .
139+ // In the object case, destructure the tuple .
60140 if (value.getType ().isObject ()) {
141+ assert (!containsPackExpansion);
61142 SGF.B .emitDestructureValueOperation (loc, value, destructuredValues);
62143 } else {
63144 // In the address case, we forward the underlying value and store it
@@ -67,11 +148,23 @@ void TupleInitialization::copyOrInitValueInto(SILGenFunction &SGF,
67148 CleanupCloner cloner (SGF, value);
68149 SILValue v = value.forward (SGF);
69150
70- auto sourceType = value.getType ().castTo <TupleType>();
71151 auto sourceSILType = value.getType ();
72- for (unsigned i : range (sourceType->getNumElements ())) {
152+ for (auto i : range (sourceType->getNumElements ())) {
73153 SILType fieldTy = sourceSILType.getTupleElementType (i);
74- SILValue elt = SGF.B .createTupleElementAddr (loc, v, i, fieldTy);
154+ if (containsPackExpansion && fieldTy.is <PackExpansionType>()) {
155+ destructuredValues.push_back (
156+ cloner.cloneForTuplePackExpansionComponent (v, formalPackType, i));
157+ continue ;
158+ }
159+
160+ SILValue elt;
161+ if (containsPackExpansion) {
162+ auto packIndex = SGF.B .createScalarPackIndex (loc, i, formalPackType);
163+ elt = SGF.B .createTuplePackElementAddr (loc, packIndex, v, fieldTy);
164+ } else {
165+ elt = SGF.B .createTupleElementAddr (loc, v, i, fieldTy);
166+ }
167+
75168 if (!fieldTy.isAddressOnly (SGF.F )) {
76169 elt = SGF.B .emitLoadValueOperation (loc, elt,
77170 LoadOwnershipQualifier::Take);
@@ -80,7 +173,24 @@ void TupleInitialization::copyOrInitValueInto(SILGenFunction &SGF,
80173 }
81174 }
82175
83- for (unsigned i : indices (destructuredValues)) {
176+ assert (destructuredValues.size () == SubInitializations.size ());
177+
178+ for (auto i : indices (destructuredValues)) {
179+ if (containsPackExpansion) {
180+ bool isPackExpansion =
181+ (destructuredValues[i].getValue () == value.getValue ());
182+ assert (isPackExpansion ==
183+ isa<PackExpansionType>(sourceType.getElementType (i)));
184+ if (isPackExpansion) {
185+ auto packAddr = destructuredValues[i].getValue ();
186+ auto componentCleanup = destructuredValues[i].getCleanup ();
187+ copyOrInitPackExpansionInto (SGF, loc, packAddr, formalPackType,
188+ i, componentCleanup,
189+ SubInitializations[i].get (), isInit);
190+ continue ;
191+ }
192+ }
193+
84194 SubInitializations[i]->copyOrInitValueInto (SGF, loc, destructuredValues[i],
85195 isInit);
86196 SubInitializations[i]->finishInitialization (SGF);
@@ -148,8 +258,7 @@ splitSingleBufferIntoTupleElements(SILGenFunction &SGF, SILLocation loc,
148258 // type for the tuple elements below.
149259 CanPackType inducedPackType;
150260 if (hasExpansion) {
151- inducedPackType =
152- tupleType.getInducedPackType (0 , tupleType->getNumElements ());
261+ inducedPackType = tupleType.getInducedPackType ();
153262 }
154263
155264 // Destructure the buffer into per-element buffers.
@@ -1250,7 +1359,8 @@ struct InitializationForPattern
12501359 // Bind a tuple pattern by aggregating the component variables into a
12511360 // TupleInitialization.
12521361 InitializationPtr visitTuplePattern (TuplePattern *P) {
1253- TupleInitialization *init = new TupleInitialization ();
1362+ TupleInitialization *init = new TupleInitialization (
1363+ cast<TupleType>(P->getType ()->getCanonicalType ()));
12541364 for (auto &elt : P->getElements ())
12551365 init->SubInitializations .push_back (visit (elt.getPattern ()));
12561366 return InitializationPtr (init);
0 commit comments