@@ -207,6 +207,36 @@ class PartialDestroyRemainingTupleCleanup : public Cleanup {
207207 }
208208};
209209
210+ // / Cleanup to destroy the remaining elements in a tuple following a
211+ // / particular value.
212+ class DestroyRemainingTupleElementsCleanup : public Cleanup {
213+ SILValue Addr;
214+ unsigned ComponentIndex;
215+ CanPackType InducedPackType;
216+ public:
217+ DestroyRemainingTupleElementsCleanup (SILValue tupleAddr,
218+ CanPackType inducedPackType,
219+ unsigned componentIndex)
220+ : Addr(tupleAddr), ComponentIndex(componentIndex),
221+ InducedPackType (inducedPackType) {}
222+
223+ void emit (SILGenFunction &SGF, CleanupLocation l,
224+ ForUnwind_t forUnwind) override {
225+ SGF.emitDestroyRemainingTupleElements (l, Addr, InducedPackType,
226+ ComponentIndex);
227+ }
228+
229+ void dump (SILGenFunction &) const override {
230+ #ifndef NDEBUG
231+ llvm::errs () << " DestroyRemainingTupleElementsCleanup\n "
232+ << " State:" << getState () << " \n "
233+ << " Addr:" << Addr << " \n "
234+ << " InducedPackType:" << InducedPackType << " \n "
235+ << " ComponentIndex:" << ComponentIndex << " \n " ;
236+ #endif
237+ }
238+ };
239+
210240// / An ASTWalker to emit tuple values in `MaterializePackExpr` nodes.
211241// /
212242// / Materialized packs are emitted inside a pack expansion context before
@@ -322,6 +352,17 @@ SILGenFunction::enterPartialDestroyRemainingTupleCleanup(SILValue addr,
322352 return Cleanups.getTopCleanup ();
323353}
324354
355+ CleanupHandle
356+ SILGenFunction::enterDestroyRemainingTupleElementsCleanup (SILValue addr,
357+ CanPackType formalPackType,
358+ unsigned componentIndex) {
359+ Cleanups.pushCleanup <DestroyRemainingTupleElementsCleanup>(addr,
360+ formalPackType,
361+ componentIndex);
362+ return Cleanups.getTopCleanup ();
363+ }
364+
365+
325366void SILGenFunction::emitDestroyPack (SILLocation loc, SILValue packAddr,
326367 CanPackType formalPackType,
327368 unsigned firstComponentIndex) {
@@ -521,6 +562,44 @@ void SILGenFunction::emitPartialDestroyRemainingTuple(SILLocation loc,
521562 });
522563}
523564
565+ void SILGenFunction::emitDestroyRemainingTupleElements (
566+ SILLocation loc, SILValue tupleAddr,
567+ CanPackType inducedPackType, unsigned firstComponentIndex) {
568+ auto tupleTy = tupleAddr->getType ().castTo <TupleType>();
569+ bool containsExpansions = tupleTy->containsPackExpansionType ();
570+ assert (!containsExpansions || inducedPackType);
571+
572+ // Destroy each of the elements of the pack.
573+ for (auto componentIndex :
574+ range (firstComponentIndex, tupleTy->getNumElements ())) {
575+ auto eltTy = tupleAddr->getType ().getTupleElementType (componentIndex);
576+
577+ // We can skip this if the whole thing is trivial.
578+ auto &eltTL = getTypeLowering (eltTy);
579+ if (eltTL.isTrivial ()) continue ;
580+
581+ // If it's an expansion component, emit a "partial"-destroy loop.
582+ if (auto expansion = eltTy.getAs <PackExpansionType>()) {
583+ emitPartialDestroyRemainingTuple (loc, tupleAddr, inducedPackType,
584+ componentIndex, /* limit*/ nullptr );
585+
586+ // If it's a scalar component, project and destroy it.
587+ } else {
588+ SILValue eltAddr;
589+ if (containsExpansions) {
590+ auto packIndex =
591+ B.createScalarPackIndex (loc, componentIndex, inducedPackType);
592+ eltAddr =
593+ B.createTuplePackElementAddr (loc, packIndex, tupleAddr, eltTy);
594+ } else {
595+ eltAddr =
596+ B.createTupleElementAddr (loc, tupleAddr, componentIndex, eltTy);
597+ }
598+ B.createDestroyAddr (loc, eltAddr);
599+ }
600+ }
601+ }
602+
524603void SILGenFunction::copyPackElementsToTuple (SILLocation loc,
525604 SILValue tupleAddr,
526605 SILValue pack,
0 commit comments