mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[move-only] Implement escaping closure semantics.
NOTE: A few of the test patterns need to be made better, but this patch series is large enough, I want to get it into tree and iterate.
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#define DEBUG_TYPE "allocbox-to-stack"
|
||||
|
||||
#include "swift/AST/DiagnosticsSIL.h"
|
||||
#include "swift/AST/SemanticAttrs.h"
|
||||
#include "swift/Basic/BlotMapVector.h"
|
||||
#include "swift/Basic/GraphNodeWorklist.h"
|
||||
#include "swift/SIL/ApplySite.h"
|
||||
@@ -524,7 +525,8 @@ static void replaceProjectBoxUsers(SILValue heapBox, SILValue stackBox) {
|
||||
}
|
||||
}
|
||||
|
||||
static void hoistMarkMustCheckInsts(SingleValueInstruction *stackBox) {
|
||||
static void hoistMarkMustCheckInsts(SILValue stackBox,
|
||||
MarkMustCheckInst::CheckKind checkKind) {
|
||||
StackList<Operand *> worklist(stackBox->getFunction());
|
||||
|
||||
for (auto *use : stackBox->getUses()) {
|
||||
@@ -559,15 +561,17 @@ static void hoistMarkMustCheckInsts(SingleValueInstruction *stackBox) {
|
||||
mmci->eraseFromParent();
|
||||
}
|
||||
|
||||
SILBuilderWithScope builder(stackBox);
|
||||
builder.insertAfter(stackBox, [&](SILBuilder &b) {
|
||||
auto *undef = SILUndef::get(stackBox->getType(), stackBox->getModule());
|
||||
auto *mmci = b.createMarkMustCheckInst(
|
||||
stackBox->getLoc(), undef,
|
||||
MarkMustCheckInst::CheckKind::ConsumableAndAssignable);
|
||||
stackBox->replaceAllUsesWith(mmci);
|
||||
mmci->setOperand(stackBox);
|
||||
});
|
||||
auto *next = stackBox->getNextInstruction();
|
||||
auto loc = next->getLoc();
|
||||
if (isa<TermInst>(next))
|
||||
loc = RegularLocation::getDiagnosticsOnlyLocation(loc, next->getModule());
|
||||
SILBuilderWithScope builder(next);
|
||||
|
||||
auto *undef = SILUndef::get(stackBox->getType(), *stackBox->getModule());
|
||||
|
||||
auto *mmci = builder.createMarkMustCheckInst(loc, undef, checkKind);
|
||||
stackBox->replaceAllUsesWith(mmci);
|
||||
mmci->setOperand(stackBox);
|
||||
}
|
||||
|
||||
/// rewriteAllocBoxAsAllocStack - Replace uses of the alloc_box with a
|
||||
@@ -639,7 +643,8 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
|
||||
// alloc_stack and convert them to [consumable_but_not_assignable]. This is
|
||||
// because we are semantically converting from escaping semantics to
|
||||
// non-escaping semantics.
|
||||
hoistMarkMustCheckInsts(StackBox);
|
||||
hoistMarkMustCheckInsts(
|
||||
StackBox, MarkMustCheckInst::CheckKind::ConsumableAndAssignable);
|
||||
|
||||
assert(ABI->getBoxType()->getLayout()->getFields().size() == 1
|
||||
&& "promoting multi-field box not implemented");
|
||||
@@ -1016,6 +1021,24 @@ specializeApplySite(SILOptFunctionBuilder &FuncBuilder, ApplySite Apply,
|
||||
Cloner.populateCloned();
|
||||
ClonedFn = Cloner.getCloned();
|
||||
pass.T->addFunctionToPassManagerWorklist(ClonedFn, F);
|
||||
|
||||
// Set the moveonly ignore flag so we do not emit an error on the original
|
||||
// function even though it is still around.
|
||||
F->addSemanticsAttr(semantics::NO_MOVEONLY_DIAGNOSTICS);
|
||||
|
||||
// If any of our promoted callee arg indices were originally noncopyable let
|
||||
// boxes, convert them from having escaping to having non-escaping
|
||||
// semantics.
|
||||
for (unsigned index : PromotedCalleeArgIndices) {
|
||||
if (F->getArgument(index)->getType().isBoxedNonCopyableType(*F)) {
|
||||
auto boxType = F->getArgument(index)->getType().castTo<SILBoxType>();
|
||||
bool isMutable = boxType->getLayout()->getFields()[0].isMutable();
|
||||
auto checkKind =
|
||||
isMutable ? MarkMustCheckInst::CheckKind::AssignableButNotConsumable
|
||||
: MarkMustCheckInst::CheckKind::NoConsumeOrAssign;
|
||||
hoistMarkMustCheckInsts(ClonedFn->getArgument(index), checkKind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now create the new ApplySite using the cloned function.
|
||||
|
||||
Reference in New Issue
Block a user