Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions include/swift/SIL/SILArgumentConvention.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ struct SILArgumentConvention {
}

/// Returns true if \p Value is a non-aliasing indirect parameter.
bool isExclusiveIndirectParameter() {
bool isExclusiveIndirectParameter() const {
switch (Value) {
case SILArgumentConvention::Indirect_In:
case SILArgumentConvention::Indirect_Out:
Expand All @@ -190,7 +190,7 @@ struct SILArgumentConvention {
}

/// Returns true if \p Value is an indirect-out parameter.
bool isIndirectOutParameter() {
bool isIndirectOutParameter() const {
switch (Value) {
case SILArgumentConvention::Indirect_Out:
case SILArgumentConvention::Pack_Out:
Expand All @@ -211,6 +211,29 @@ struct SILArgumentConvention {
}
llvm_unreachable("covered switch isn't covered?!");
}

/// Returns true if \p Value is a pack parameter.
bool isPackParameter() const {
switch (Value) {
case SILArgumentConvention::Pack_Inout:
case SILArgumentConvention::Pack_Owned:
case SILArgumentConvention::Pack_Guaranteed:
case SILArgumentConvention::Pack_Out:
return true;

case SILArgumentConvention::Indirect_Out:
case SILArgumentConvention::Indirect_In:
case SILArgumentConvention::Indirect_In_Guaranteed:
case SILArgumentConvention::Indirect_Inout:
case SILArgumentConvention::Indirect_InoutAliasable:
case SILArgumentConvention::Indirect_In_CXX:
case SILArgumentConvention::Direct_Unowned:
case SILArgumentConvention::Direct_Guaranteed:
case SILArgumentConvention::Direct_Owned:
return false;
}
llvm_unreachable("covered switch isn't covered?!");
}
};

} // namespace swift
Expand Down
16 changes: 16 additions & 0 deletions lib/SILGen/SILGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3207,6 +3207,22 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
SILValue packExpansionIndex, SILValue packIndex)>
emitBody);

/// Emit an operation for each element of a pack expansion component of
/// a pack, automatically projecting and managing ownership of it properly
/// for each iteration.
///
/// The projection and management does not itself generate control flow and
/// so can be safely composed with further projection and management.
void emitPackForEach(SILLocation loc,
ManagedValue inputPackAddr,
CanPackType inputFormalPackType,
unsigned inputComponentIndex,
GenericEnvironment *openedElementEnv,
SILType inputEltTy,
llvm::function_ref<void(SILValue indexWithinComponent,
SILValue expansionPackIndex,
ManagedValue input)> emitBody);

/// Emit a transform on each element of a pack-expansion component
/// of a pack, write the result into a pack-expansion component of
/// another pack.
Expand Down
84 changes: 54 additions & 30 deletions lib/SILGen/SILGenPack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,51 @@ TuplePackExpansionInitialization::getElementAddress(SILGenFunction &SGF,
return SGF.B.createTuplePackElementAddr(loc, packIndex, TupleAddr, eltAddrTy);
}

void
SILGenFunction::emitPackForEach(SILLocation loc,
ManagedValue inputPackMV,
CanPackType inputFormalPackType,
unsigned inputComponentIndex,
GenericEnvironment *openedEnv,
SILType inputEltTy,
llvm::function_ref<void(SILValue indexWithinComponent,
SILValue packExpansionIndex,
ManagedValue inputElt)> emitBody) {
// Deactivate the cleanup on the pack expansion component, but
// remember how to clone it for the elements later.
CleanupCloner inputCloner(*this, inputPackMV);
bool inputHasCleanup = inputPackMV.hasCleanup();
auto inputPackAddr = inputPackMV.forward(*this);

emitDynamicPackLoop(loc, inputFormalPackType, inputComponentIndex, openedEnv,
[]() -> SILBasicBlock * { return nullptr; },
[&](SILValue indexWithinComponent,
SILValue packExpansionIndex,
SILValue inputPackIndex) {
// Enter a partial cleanup for the remaining elements of the input
// expansion component.
CleanupHandle remainingInputEltsCleanup = CleanupHandle::invalid();
if (inputHasCleanup) {
remainingInputEltsCleanup =
enterPartialDestroyRemainingPackCleanup(
inputPackAddr, inputFormalPackType, inputComponentIndex,
indexWithinComponent);
}

// Retrieve the input value from the pack and manage it.
auto inputEltAddr =
B.createPackElementGet(loc, inputPackIndex, inputPackAddr, inputEltTy);
ManagedValue inputElt = inputCloner.clone(inputEltAddr);

// Emit the body.
emitBody(indexWithinComponent, packExpansionIndex, inputElt);

// Deactivate the partial cleanup.
if (remainingInputEltsCleanup.isValid())
Cleanups.forwardCleanup(remainingInputEltsCleanup);
});
}

ManagedValue
SILGenFunction::emitPackTransform(SILLocation loc,
ManagedValue inputPackMV,
Expand All @@ -1046,11 +1091,7 @@ SILGenFunction::emitPackTransform(SILLocation loc,
assert((isSimpleProjection || canForwardOutput) &&
"we cannot support complex transformations that yield borrows");

CleanupCloner inputCloner(*this, inputPackMV);
bool inputHasCleanup = inputPackMV.hasCleanup();
auto inputPackAddr = inputPackMV.forward(*this);

auto inputPackTy = inputPackAddr->getType().castTo<SILPackType>();
auto inputPackTy = inputPackMV.getType().castTo<SILPackType>();
assert(inputPackTy->getNumElements() ==
inputFormalPackType->getNumElements());
auto inputComponentTy = inputPackTy->getSILElementType(inputComponentIndex);
Expand Down Expand Up @@ -1080,22 +1121,12 @@ SILGenFunction::emitPackTransform(SILLocation loc,
outputTupleAddr = emitTemporaryAllocation(loc, outputTupleTy);
}

emitDynamicPackLoop(loc, inputFormalPackType, inputComponentIndex, openedEnv,
[]() -> SILBasicBlock * { return nullptr; },
[&](SILValue indexWithinComponent,
SILValue packExpansionIndex,
SILValue inputPackIndex) {
// Enter a cleanup for the remaining elements of the input
// expansion component.
CleanupHandle remainingInputEltsCleanup = CleanupHandle::invalid();
if (inputHasCleanup) {
remainingInputEltsCleanup =
enterPartialDestroyRemainingPackCleanup(
inputPackAddr, inputFormalPackType, inputComponentIndex,
indexWithinComponent);
}

// Enter a cleanup for the previous elements of the output
emitPackForEach(loc, inputPackMV, inputFormalPackType, inputComponentIndex,
openedEnv, inputEltTy,
[&](SILValue indexWithinComponent,
SILValue packExpansionIndex,
ManagedValue inputElt) {
// Enter a partial cleanup for the previous elements of the output
// expansion component.
CleanupHandle previousOutputEltsCleanup = CleanupHandle::invalid();
if (outputNeedsCleanup) {
Expand All @@ -1116,16 +1147,11 @@ SILGenFunction::emitPackTransform(SILLocation loc,
outputEltInit = useBufferAsTemporary(outputEltAddr, outputEltTL);
}

// Retrieve the input value from the pack and manage it.
auto inputEltAddr =
B.createPackElementGet(loc, inputPackIndex, inputPackAddr, inputEltTy);
ManagedValue inputElt = inputCloner.clone(inputEltAddr);

// Apply the transform.
ManagedValue outputElt =
emitBody(inputElt, outputEltTy,
canForwardOutput ? SGFContext(outputEltInit.get())
: SGFContext::AllowGuaranteedPlusZero);
: SGFContext::AllowGuaranteedPlusZero);
assert(canForwardOutput == (outputElt.isInContext() ||
outputElt.isPlusOneOrTrivial(*this)) &&
"transformation produced a value of the wrong ownership");
Expand Down Expand Up @@ -1156,9 +1182,7 @@ SILGenFunction::emitPackTransform(SILLocation loc,
}
B.createPackElementSet(loc, outputEltAddr, outputPackIndex, outputPackAddr);

// Deactivate the partial cleanups.
if (remainingInputEltsCleanup.isValid())
Cleanups.forwardCleanup(remainingInputEltsCleanup);
// Deactivate the partial cleanup.
if (previousOutputEltsCleanup.isValid())
Cleanups.forwardCleanup(previousOutputEltsCleanup);
});
Expand Down
Loading