@@ -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+
10301075ManagedValue
10311076SILGenFunction::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