Skip to content

Commit 467b742

Browse files
committed
[move-only] Update the non-address move checker part of the optimizer to handle mark_must_check on addresses.
1 parent 7b9d4e6 commit 467b742

10 files changed

+90
-17
lines changed

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,12 +1368,14 @@ class AccessPathVisitor : public FindAccessVisitorImpl<AccessPathVisitor> {
13681368
} else {
13691369
// Ignore everything in getAccessProjectionOperand that is an access
13701370
// projection with no affect on the access path.
1371-
assert(isa<OpenExistentialAddrInst>(projectedAddr)
1372-
|| isa<InitEnumDataAddrInst>(projectedAddr)
1373-
|| isa<UncheckedTakeEnumDataAddrInst>(projectedAddr)
1371+
assert(isa<OpenExistentialAddrInst>(projectedAddr) ||
1372+
isa<InitEnumDataAddrInst>(projectedAddr) ||
1373+
isa<UncheckedTakeEnumDataAddrInst>(projectedAddr)
13741374
// project_box is not normally an access projection but we treat it
13751375
// as such when it operates on unchecked_take_enum_data_addr.
1376-
|| isa<ProjectBoxInst>(projectedAddr));
1376+
|| isa<ProjectBoxInst>(projectedAddr)
1377+
// Ignore mark_must_check, we just look through it when we see it.
1378+
|| isa<MarkMustCheckInst>(projectedAddr));
13771379
}
13781380
return sourceAddr->get();
13791381
}
@@ -1862,7 +1864,14 @@ AccessPathDefUseTraversal::visitSingleValueUser(SingleValueInstruction *svi,
18621864
return IgnoredUse;
18631865
}
18641866

1865-
// MARK: Access projections
1867+
case SILInstructionKind::MarkMustCheckInst: {
1868+
// Mark must check goes on the project_box, so it isn't a ref.
1869+
assert(!dfs.isRef());
1870+
pushUsers(svi, dfs);
1871+
return IgnoredUse;
1872+
}
1873+
1874+
// MARK: Access projections
18661875

18671876
case SILInstructionKind::StructElementAddrInst:
18681877
case SILInstructionKind::TupleElementAddrInst:

lib/SIL/Utils/OwnershipUtils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ swift::findTransitiveUsesForAddress(SILValue projectedAddress,
936936
isa<InitExistentialAddrInst>(user) || isa<InitEnumDataAddrInst>(user) ||
937937
isa<BeginAccessInst>(user) || isa<TailAddrInst>(user) ||
938938
isa<IndexAddrInst>(user) || isa<StoreBorrowInst>(user) ||
939-
isa<UncheckedAddrCastInst>(user)) {
939+
isa<UncheckedAddrCastInst>(user) || isa<MarkMustCheckInst>(user)) {
940940
transitiveResultUses(op);
941941
continue;
942942
}

lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,17 @@ bool GatherWritesVisitor::visitUse(Operand *op, AccessUseType useTy) {
169169
}
170170
return true;
171171

172+
case SILInstructionKind::ExplicitCopyAddrInst:
173+
if (cast<ExplicitCopyAddrInst>(user)->getDest() == op->get()) {
174+
writeAccumulator.push_back(op);
175+
return true;
176+
}
177+
// This operand is the copy source. Check if it is taken.
178+
if (cast<ExplicitCopyAddrInst>(user)->isTakeOfSrc()) {
179+
writeAccumulator.push_back(op);
180+
}
181+
return true;
182+
172183
case SILInstructionKind::MarkUnresolvedMoveAddrInst:
173184
if (cast<MarkUnresolvedMoveAddrInst>(user)->getDest() == op->get()) {
174185
writeAccumulator.push_back(op);

lib/SILGen/SILGenDecl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,11 @@ class LocalVariableInitialization : public SingleBufferInitialization {
376376
}
377377

378378
Addr = SGF.B.createProjectBox(decl, Box, 0);
379+
if (Addr->getType().isMoveOnly()) {
380+
// TODO: Handle no implicit copy here.
381+
Addr = SGF.B.createMarkMustCheckInst(
382+
decl, Addr, MarkMustCheckInst::CheckKind::NoImplicitCopy);
383+
}
379384

380385
// Push a cleanup to destroy the local variable. This has to be
381386
// inactive until the variable is initialized.

lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
///
3232
//===----------------------------------------------------------------------===//
3333

34+
#include "swift/SIL/SILInstruction.h"
3435
#define DEBUG_TYPE "access-enforcement-selection"
3536
#include "swift/Basic/Defer.h"
3637
#include "swift/SIL/ApplySite.h"
@@ -194,7 +195,8 @@ class SelectEnforcement {
194195

195196
private:
196197
void analyzeUsesOfBox(SingleValueInstruction *source);
197-
void analyzeProjection(ProjectBoxInst *projection);
198+
// Used for project_box and mark_must_initialize.
199+
void analyzeProjection(SingleValueInstruction *project);
198200

199201
/// Note that the given instruction is a use of the box (or a use of
200202
/// a projection from it) in which the address escapes.
@@ -237,13 +239,13 @@ void SelectEnforcement::analyzeUsesOfBox(SingleValueInstruction *source) {
237239
for (auto use : source->getUses()) {
238240
auto user = use->getUser();
239241

240-
if (auto BBI = dyn_cast<BeginBorrowInst>(user)) {
241-
analyzeUsesOfBox(BBI);
242+
if (auto bbi = dyn_cast<BeginBorrowInst>(user)) {
243+
analyzeUsesOfBox(bbi);
242244
continue;
243245
}
244246

245-
if (auto MUI = dyn_cast<MarkUninitializedInst>(user)) {
246-
analyzeUsesOfBox(MUI);
247+
if (auto mui = dyn_cast<MarkUninitializedInst>(user)) {
248+
analyzeUsesOfBox(mui);
247249
continue;
248250
}
249251

@@ -281,10 +283,16 @@ static void checkUsesOfAccess(BeginAccessInst *access) {
281283
#endif
282284
}
283285

284-
void SelectEnforcement::analyzeProjection(ProjectBoxInst *projection) {
286+
void SelectEnforcement::analyzeProjection(SingleValueInstruction *projection) {
285287
for (auto *use : projection->getUses()) {
286288
auto user = use->getUser();
287289

290+
// Look through mark must check.
291+
if (auto *mmi = dyn_cast<MarkMustCheckInst>(user)) {
292+
analyzeProjection(mmi);
293+
continue;
294+
}
295+
288296
// Collect accesses.
289297
if (auto *access = dyn_cast<BeginAccessInst>(user)) {
290298
if (access->getEnforcement() == SILAccessEnforcement::Unknown)
@@ -687,8 +695,12 @@ AccessEnforcementSelection::getAccessKindForBox(ProjectBoxInst *projection) {
687695

688696
SourceAccess AccessEnforcementSelection::getSourceAccess(SILValue address) {
689697
// Recurse through MarkUninitializedInst.
690-
if (auto *MUI = dyn_cast<MarkUninitializedInst>(address))
691-
return getSourceAccess(MUI->getOperand());
698+
if (auto *mui = dyn_cast<MarkUninitializedInst>(address))
699+
return getSourceAccess(mui->getOperand());
700+
701+
// Recurse through mark must check.
702+
if (auto *mmci = dyn_cast<MarkMustCheckInst>(address))
703+
return getSourceAccess(mmci->getOperand());
692704

693705
if (auto box = dyn_cast<ProjectBoxInst>(address))
694706
return getAccessKindForBox(box);

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,12 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
747747
continue;
748748
}
749749

750+
// Look through mark_must_check. To us, it is not interesting.
751+
if (auto *mmi = dyn_cast<MarkMustCheckInst>(User)) {
752+
collectUses(mmi, BaseEltNo);
753+
continue;
754+
}
755+
750756
// Loads are a use of the value.
751757
if (isa<LoadInst>(User)) {
752758
addElementUses(BaseEltNo, PointeeType, User, DIUseKind::Load);
@@ -1588,6 +1594,12 @@ collectDelegatingInitUses(const DIMemoryObjectInfo &TheMemory,
15881594
continue;
15891595
}
15901596

1597+
// Look through mark_must_check.
1598+
if (auto *MMCI = dyn_cast<MarkMustCheckInst>(User)) {
1599+
collectDelegatingInitUses(TheMemory, UseInfo, MMCI);
1600+
continue;
1601+
}
1602+
15911603
// Ignore end_access
15921604
if (isa<EndAccessInst>(User))
15931605
continue;

lib/SILOptimizer/Mandatory/DiagnoseInvalidEscapingCaptures.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ static bool checkNoEscapePartialApplyUse(Operand *oper, FollowUse followUses) {
148148
}
149149

150150
const ParamDecl *getParamDeclFromOperand(SILValue value) {
151+
// Look through mark must check.
152+
if (auto *mmci = dyn_cast<MarkMustCheckInst>(value))
153+
value = mmci->getOperand();
154+
151155
if (auto *arg = dyn_cast<SILArgument>(value))
152156
if (auto *decl = dyn_cast_or_null<ParamDecl>(arg->getDecl()))
153157
return decl;
@@ -263,6 +267,13 @@ static void diagnoseCaptureLoc(ASTContext &Context, DeclContext *DC,
263267
if (isIncidentalUse(user) || onlyAffectsRefCount(user))
264268
continue;
265269

270+
// Look through mark must check inst.
271+
if (auto *mmci = dyn_cast<MarkMustCheckInst>(user)) {
272+
for (auto *use : mmci->getUses())
273+
uselistInsert(use);
274+
continue;
275+
}
276+
266277
// Look through copies, borrows, and conversions.
267278
if (SingleValueInstruction *copy = getSingleValueCopyOrCast(user)) {
268279
// Only follow the copied operand. Other operands are incidental,

lib/SILOptimizer/Mandatory/MoveOnlyObjectChecker.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,13 @@ bool MoveOnlyChecker::searchForCandidateMarkMustChecks() {
299299
// We then RAUW the mark_must_check once we have emitted the error since
300300
// later passes expect that mark_must_check has been eliminated by
301301
// us. Since we are failing already, this is ok to do.
302-
diagnose(fn->getASTContext(), mmci->getLoc().getSourceLoc(),
303-
diag::sil_moveonlychecker_not_understand_mark_move);
302+
if (mmci->getType().isMoveOnlyWrapped()) {
303+
diagnose(fn->getASTContext(), mmci->getLoc().getSourceLoc(),
304+
diag::sil_moveonlychecker_not_understand_no_implicit_copy);
305+
} else {
306+
diagnose(fn->getASTContext(), mmci->getLoc().getSourceLoc(),
307+
diag::sil_moveonlychecker_not_understand_moveonly);
308+
}
304309
mmci->replaceAllUsesWith(mmci->getOperand());
305310
mmci->eraseFromParent();
306311
changed = true;

lib/SILOptimizer/Transforms/AllocBoxToStack.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#define DEBUG_TYPE "allocbox-to-stack"
14+
1415
#include "swift/AST/DiagnosticsSIL.h"
1516
#include "swift/Basic/BlotMapVector.h"
1617
#include "swift/Basic/GraphNodeWorklist.h"
@@ -591,9 +592,16 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
591592
for (auto LastRelease : FinalReleases) {
592593
SILBuilderWithScope Builder(LastRelease);
593594
if (!isa<DeallocBoxInst>(LastRelease)&& !Lowering.isTrivial()) {
595+
// If we have a mark_must_check use of our stack box, we want to destroy
596+
// that.
597+
SILValue valueToDestroy = StackBox;
598+
if (auto *mmci = StackBox->getSingleUserOfType<MarkMustCheckInst>()) {
599+
valueToDestroy = mmci;
600+
}
601+
594602
// For non-trivial types, insert destroys for each final release-like
595603
// instruction we found that isn't an explicit dealloc_box.
596-
Builder.emitDestroyAddrAndFold(Loc, StackBox);
604+
Builder.emitDestroyAddrAndFold(Loc, valueToDestroy);
597605
}
598606
Builder.createDeallocStack(Loc, ASI);
599607
}

0 commit comments

Comments
 (0)