Skip to content

Commit 00e78cb

Browse files
committed
Handle vanishing and variadic tuple results in reabstraction thunks.
Fixes rdar://110391963
1 parent cc5bea1 commit 00e78cb

8 files changed

+2148
-340
lines changed

lib/SILGen/Cleanup.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,3 +499,35 @@ CleanupCloner::cloneForRemainingPackComponents(SILValue packAddr,
499499
firstComponentIndex);
500500
return ManagedValue(packAddr, cleanup);
501501
}
502+
503+
ManagedValue
504+
CleanupCloner::cloneForRemainingTupleComponents(SILValue tupleAddr,
505+
CanPackType inducedPackType,
506+
unsigned firstComponentIndex) const {
507+
if (isLValue) {
508+
return ManagedValue::forLValue(tupleAddr);
509+
}
510+
511+
if (!hasCleanup) {
512+
return ManagedValue::forUnmanaged(tupleAddr);
513+
}
514+
515+
assert(!writebackBuffer.has_value());
516+
bool isTrivial = true;
517+
auto tupleTy = tupleAddr->getType().castTo<TupleType>();
518+
for (auto eltTy : tupleTy.getElementTypes().slice(firstComponentIndex)) {
519+
if (!SILType::getPrimitiveObjectType(eltTy).isTrivial(SGF.F)) {
520+
isTrivial = false;
521+
break;
522+
}
523+
}
524+
525+
if (isTrivial)
526+
return ManagedValue::forUnmanaged(tupleAddr);
527+
528+
auto cleanup =
529+
SGF.enterDestroyRemainingTupleElementsCleanup(tupleAddr,
530+
inducedPackType,
531+
firstComponentIndex);
532+
return ManagedValue(tupleAddr, cleanup);
533+
}

lib/SILGen/Cleanup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ class CleanupCloner {
349349
ManagedValue cloneForRemainingPackComponents(SILValue packAddr,
350350
CanPackType formalPackType,
351351
unsigned firstComponentIndex) const;
352+
ManagedValue cloneForRemainingTupleComponents(SILValue tupleAddr,
353+
CanPackType inducedPackType,
354+
unsigned firstComponentIndex) const;
352355

353356
static void
354357
getClonersForRValue(SILGenFunction &SGF, const RValue &rvalue,

lib/SILGen/SILGenFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant,
990990

991991
// Get the lowered AST types:
992992
// - the original type
993-
auto origFormalType = AbstractionPattern(constantInfo.LoweredType);
993+
auto origFormalType = AbstractionPattern(subs, constantInfo.LoweredType);
994994

995995
// - the substituted type
996996
auto substFormalType = expectedType;

lib/SILGen/SILGenFunction.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2494,6 +2494,13 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
24942494
unsigned componentIndex,
24952495
SILValue currentIndexWithinComponent);
24962496

2497+
/// Enter a cleanup to destroy all of the components in a tuple starting
2498+
/// at a particular component index.
2499+
CleanupHandle
2500+
enterDestroyRemainingTupleElementsCleanup(SILValue addr,
2501+
CanPackType inducedPackType,
2502+
unsigned componentIndex);
2503+
24972504
/// Copy the elements of a pack, which must consist of a single pack expansion,
24982505
/// into a tuple value having the same pack expansion and its sole element type.
24992506
void copyPackElementsToTuple(SILLocation loc, SILValue tupleAddr, SILValue pack,
@@ -2714,6 +2721,19 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
27142721
CanPackType formalPackType,
27152722
unsigned firstComponentIndex = 0);
27162723

2724+
/// Emit instructions to destroy a suffix of a tuple value.
2725+
///
2726+
/// \param tupleAddr - the address of the overall tuple value
2727+
/// \param inducedPackType - a pack type with the same shape as the
2728+
/// element types of the overall tuple value; can be null if the
2729+
/// tuple type doesn't contain pack expansions
2730+
/// \param componentIndex - the index of the first component to
2731+
/// destroy in the tuple
2732+
void emitDestroyRemainingTupleElements(SILLocation loc,
2733+
SILValue tupleAddr,
2734+
CanPackType inducedPackType,
2735+
unsigned componentIndex);
2736+
27172737
/// Emit a loop which destroys a prefix of a pack expansion component
27182738
/// of a tuple value.
27192739
///

lib/SILGen/SILGenPack.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
325366
void 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+
524603
void SILGenFunction::copyPackElementsToTuple(SILLocation loc,
525604
SILValue tupleAddr,
526605
SILValue pack,

0 commit comments

Comments
 (0)