Skip to content

Commit cef53c6

Browse files
authored
Merge pull request #86078 from rjmccall/vanishing-tuple-param-binding
Fix a bug with binding parameters under a vanishing tuple AP
2 parents 76c7949 + 55be004 commit cef53c6

File tree

10 files changed

+373
-237
lines changed

10 files changed

+373
-237
lines changed

include/swift/SIL/SILArgumentConvention.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ struct SILArgumentConvention {
167167
}
168168

169169
/// Returns true if \p Value is a non-aliasing indirect parameter.
170-
bool isExclusiveIndirectParameter() {
170+
bool isExclusiveIndirectParameter() const {
171171
switch (Value) {
172172
case SILArgumentConvention::Indirect_In:
173173
case SILArgumentConvention::Indirect_Out:
@@ -190,7 +190,7 @@ struct SILArgumentConvention {
190190
}
191191

192192
/// Returns true if \p Value is an indirect-out parameter.
193-
bool isIndirectOutParameter() {
193+
bool isIndirectOutParameter() const {
194194
switch (Value) {
195195
case SILArgumentConvention::Indirect_Out:
196196
case SILArgumentConvention::Pack_Out:
@@ -211,6 +211,29 @@ struct SILArgumentConvention {
211211
}
212212
llvm_unreachable("covered switch isn't covered?!");
213213
}
214+
215+
/// Returns true if \p Value is a pack parameter.
216+
bool isPackParameter() const {
217+
switch (Value) {
218+
case SILArgumentConvention::Pack_Inout:
219+
case SILArgumentConvention::Pack_Owned:
220+
case SILArgumentConvention::Pack_Guaranteed:
221+
case SILArgumentConvention::Pack_Out:
222+
return true;
223+
224+
case SILArgumentConvention::Indirect_Out:
225+
case SILArgumentConvention::Indirect_In:
226+
case SILArgumentConvention::Indirect_In_Guaranteed:
227+
case SILArgumentConvention::Indirect_Inout:
228+
case SILArgumentConvention::Indirect_InoutAliasable:
229+
case SILArgumentConvention::Indirect_In_CXX:
230+
case SILArgumentConvention::Direct_Unowned:
231+
case SILArgumentConvention::Direct_Guaranteed:
232+
case SILArgumentConvention::Direct_Owned:
233+
return false;
234+
}
235+
llvm_unreachable("covered switch isn't covered?!");
236+
}
214237
};
215238

216239
} // namespace swift

lib/SILGen/SILGenFunction.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3207,6 +3207,22 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
32073207
SILValue packExpansionIndex, SILValue packIndex)>
32083208
emitBody);
32093209

3210+
/// Emit an operation for each element of a pack expansion component of
3211+
/// a pack, automatically projecting and managing ownership of it properly
3212+
/// for each iteration.
3213+
///
3214+
/// The projection and management does not itself generate control flow and
3215+
/// so can be safely composed with further projection and management.
3216+
void emitPackForEach(SILLocation loc,
3217+
ManagedValue inputPackAddr,
3218+
CanPackType inputFormalPackType,
3219+
unsigned inputComponentIndex,
3220+
GenericEnvironment *openedElementEnv,
3221+
SILType inputEltTy,
3222+
llvm::function_ref<void(SILValue indexWithinComponent,
3223+
SILValue expansionPackIndex,
3224+
ManagedValue input)> emitBody);
3225+
32103226
/// Emit a transform on each element of a pack-expansion component
32113227
/// of a pack, write the result into a pack-expansion component of
32123228
/// another pack.

lib/SILGen/SILGenPack.cpp

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,51 @@ TuplePackExpansionInitialization::getElementAddress(SILGenFunction &SGF,
10271027
return SGF.B.createTuplePackElementAddr(loc, packIndex, TupleAddr, eltAddrTy);
10281028
}
10291029

1030+
void
1031+
SILGenFunction::emitPackForEach(SILLocation loc,
1032+
ManagedValue inputPackMV,
1033+
CanPackType inputFormalPackType,
1034+
unsigned inputComponentIndex,
1035+
GenericEnvironment *openedEnv,
1036+
SILType inputEltTy,
1037+
llvm::function_ref<void(SILValue indexWithinComponent,
1038+
SILValue packExpansionIndex,
1039+
ManagedValue inputElt)> emitBody) {
1040+
// Deactivate the cleanup on the pack expansion component, but
1041+
// remember how to clone it for the elements later.
1042+
CleanupCloner inputCloner(*this, inputPackMV);
1043+
bool inputHasCleanup = inputPackMV.hasCleanup();
1044+
auto inputPackAddr = inputPackMV.forward(*this);
1045+
1046+
emitDynamicPackLoop(loc, inputFormalPackType, inputComponentIndex, openedEnv,
1047+
[]() -> SILBasicBlock * { return nullptr; },
1048+
[&](SILValue indexWithinComponent,
1049+
SILValue packExpansionIndex,
1050+
SILValue inputPackIndex) {
1051+
// Enter a partial cleanup for the remaining elements of the input
1052+
// expansion component.
1053+
CleanupHandle remainingInputEltsCleanup = CleanupHandle::invalid();
1054+
if (inputHasCleanup) {
1055+
remainingInputEltsCleanup =
1056+
enterPartialDestroyRemainingPackCleanup(
1057+
inputPackAddr, inputFormalPackType, inputComponentIndex,
1058+
indexWithinComponent);
1059+
}
1060+
1061+
// Retrieve the input value from the pack and manage it.
1062+
auto inputEltAddr =
1063+
B.createPackElementGet(loc, inputPackIndex, inputPackAddr, inputEltTy);
1064+
ManagedValue inputElt = inputCloner.clone(inputEltAddr);
1065+
1066+
// Emit the body.
1067+
emitBody(indexWithinComponent, packExpansionIndex, inputElt);
1068+
1069+
// Deactivate the partial cleanup.
1070+
if (remainingInputEltsCleanup.isValid())
1071+
Cleanups.forwardCleanup(remainingInputEltsCleanup);
1072+
});
1073+
}
1074+
10301075
ManagedValue
10311076
SILGenFunction::emitPackTransform(SILLocation loc,
10321077
ManagedValue inputPackMV,
@@ -1046,11 +1091,7 @@ SILGenFunction::emitPackTransform(SILLocation loc,
10461091
assert((isSimpleProjection || canForwardOutput) &&
10471092
"we cannot support complex transformations that yield borrows");
10481093

1049-
CleanupCloner inputCloner(*this, inputPackMV);
1050-
bool inputHasCleanup = inputPackMV.hasCleanup();
1051-
auto inputPackAddr = inputPackMV.forward(*this);
1052-
1053-
auto inputPackTy = inputPackAddr->getType().castTo<SILPackType>();
1094+
auto inputPackTy = inputPackMV.getType().castTo<SILPackType>();
10541095
assert(inputPackTy->getNumElements() ==
10551096
inputFormalPackType->getNumElements());
10561097
auto inputComponentTy = inputPackTy->getSILElementType(inputComponentIndex);
@@ -1080,22 +1121,12 @@ SILGenFunction::emitPackTransform(SILLocation loc,
10801121
outputTupleAddr = emitTemporaryAllocation(loc, outputTupleTy);
10811122
}
10821123

1083-
emitDynamicPackLoop(loc, inputFormalPackType, inputComponentIndex, openedEnv,
1084-
[]() -> SILBasicBlock * { return nullptr; },
1085-
[&](SILValue indexWithinComponent,
1086-
SILValue packExpansionIndex,
1087-
SILValue inputPackIndex) {
1088-
// Enter a cleanup for the remaining elements of the input
1089-
// expansion component.
1090-
CleanupHandle remainingInputEltsCleanup = CleanupHandle::invalid();
1091-
if (inputHasCleanup) {
1092-
remainingInputEltsCleanup =
1093-
enterPartialDestroyRemainingPackCleanup(
1094-
inputPackAddr, inputFormalPackType, inputComponentIndex,
1095-
indexWithinComponent);
1096-
}
1097-
1098-
// Enter a cleanup for the previous elements of the output
1124+
emitPackForEach(loc, inputPackMV, inputFormalPackType, inputComponentIndex,
1125+
openedEnv, inputEltTy,
1126+
[&](SILValue indexWithinComponent,
1127+
SILValue packExpansionIndex,
1128+
ManagedValue inputElt) {
1129+
// Enter a partial cleanup for the previous elements of the output
10991130
// expansion component.
11001131
CleanupHandle previousOutputEltsCleanup = CleanupHandle::invalid();
11011132
if (outputNeedsCleanup) {
@@ -1116,16 +1147,11 @@ SILGenFunction::emitPackTransform(SILLocation loc,
11161147
outputEltInit = useBufferAsTemporary(outputEltAddr, outputEltTL);
11171148
}
11181149

1119-
// Retrieve the input value from the pack and manage it.
1120-
auto inputEltAddr =
1121-
B.createPackElementGet(loc, inputPackIndex, inputPackAddr, inputEltTy);
1122-
ManagedValue inputElt = inputCloner.clone(inputEltAddr);
1123-
11241150
// Apply the transform.
11251151
ManagedValue outputElt =
11261152
emitBody(inputElt, outputEltTy,
11271153
canForwardOutput ? SGFContext(outputEltInit.get())
1128-
: SGFContext::AllowGuaranteedPlusZero);
1154+
: SGFContext::AllowGuaranteedPlusZero);
11291155
assert(canForwardOutput == (outputElt.isInContext() ||
11301156
outputElt.isPlusOneOrTrivial(*this)) &&
11311157
"transformation produced a value of the wrong ownership");
@@ -1156,9 +1182,7 @@ SILGenFunction::emitPackTransform(SILLocation loc,
11561182
}
11571183
B.createPackElementSet(loc, outputEltAddr, outputPackIndex, outputPackAddr);
11581184

1159-
// Deactivate the partial cleanups.
1160-
if (remainingInputEltsCleanup.isValid())
1161-
Cleanups.forwardCleanup(remainingInputEltsCleanup);
1185+
// Deactivate the partial cleanup.
11621186
if (previousOutputEltsCleanup.isValid())
11631187
Cleanups.forwardCleanup(previousOutputEltsCleanup);
11641188
});

0 commit comments

Comments
 (0)