@@ -363,6 +363,62 @@ static bool isInOutDefThatNeedsEndOfFunctionLiveness(SILValue value) {
363
363
return false ;
364
364
}
365
365
366
+ // ===----------------------------------------------------------------------===//
367
+ // MARK: Cleanup After Emitting Diagnostic
368
+ // ===----------------------------------------------------------------------===//
369
+
370
+ static bool cleanupAfterEmittingDiagnostic (SILFunction *fn) {
371
+ bool changed = false ;
372
+ for (auto &block : *fn) {
373
+ for (auto ii = block.begin (), ie = block.end (); ii != ie;) {
374
+ auto *inst = &*ii;
375
+ ++ii;
376
+
377
+ // Convert load [copy] -> load_borrow + explicit_copy_value.
378
+ if (auto *li = dyn_cast<LoadInst>(inst)) {
379
+ if (li->getOwnershipQualifier () == LoadOwnershipQualifier::Copy) {
380
+ SILBuilderWithScope builder (li);
381
+ auto *lbi = builder.createLoadBorrow (li->getLoc (), li->getOperand ());
382
+ auto *cvi = builder.createExplicitCopyValue (li->getLoc (), lbi);
383
+ builder.createEndBorrow (li->getLoc (), lbi);
384
+ li->replaceAllUsesWith (cvi);
385
+ li->eraseFromParent ();
386
+ changed = true ;
387
+ }
388
+ }
389
+
390
+ // Convert copy_addr !take of src to its explicit value form so we don't
391
+ // error.
392
+ if (auto *copyAddr = dyn_cast<CopyAddrInst>(inst)) {
393
+ if (!copyAddr->isTakeOfSrc ()) {
394
+ SILBuilderWithScope builder (copyAddr);
395
+ builder.createExplicitCopyAddr (
396
+ copyAddr->getLoc (), copyAddr->getSrc (), copyAddr->getDest (),
397
+ IsTake_t (copyAddr->isTakeOfSrc ()),
398
+ IsInitialization_t (copyAddr->isInitializationOfDest ()));
399
+ copyAddr->eraseFromParent ();
400
+ changed = true ;
401
+ }
402
+ }
403
+
404
+ // Convert any copy_value of move_only type to explicit copy value.
405
+ if (auto *cvi = dyn_cast<CopyValueInst>(inst)) {
406
+ if (!cvi->getOperand ()->getType ().isMoveOnly ())
407
+ continue ;
408
+ SILBuilderWithScope b (cvi);
409
+ auto *expCopy =
410
+ b.createExplicitCopyValue (cvi->getLoc (), cvi->getOperand ());
411
+ cvi->replaceAllUsesWith (expCopy);
412
+ cvi->eraseFromParent ();
413
+ changed = true ;
414
+ continue ;
415
+ }
416
+ }
417
+ }
418
+
419
+ return changed;
420
+ }
421
+
366
422
// ===----------------------------------------------------------------------===//
367
423
// MARK: Use State
368
424
// ===----------------------------------------------------------------------===//
@@ -1584,52 +1640,7 @@ bool GlobalLivenessChecker::compute() {
1584
1640
// ===----------------------------------------------------------------------===//
1585
1641
1586
1642
void MoveOnlyChecker::cleanupAfterEmittingDiagnostic () {
1587
- for (auto &block : *fn) {
1588
- for (auto ii = block.begin (), ie = block.end (); ii != ie;) {
1589
- auto *inst = &*ii;
1590
- ++ii;
1591
-
1592
- // Convert load [copy] -> load_borrow + explicit_copy_value.
1593
- if (auto *li = dyn_cast<LoadInst>(inst)) {
1594
- if (li->getOwnershipQualifier () == LoadOwnershipQualifier::Copy) {
1595
- SILBuilderWithScope builder (li);
1596
- auto *lbi = builder.createLoadBorrow (li->getLoc (), li->getOperand ());
1597
- auto *cvi = builder.createExplicitCopyValue (li->getLoc (), lbi);
1598
- builder.createEndBorrow (li->getLoc (), lbi);
1599
- li->replaceAllUsesWith (cvi);
1600
- li->eraseFromParent ();
1601
- changed = true ;
1602
- }
1603
- }
1604
-
1605
- // Convert copy_addr !take of src to its explicit value form so we don't
1606
- // error.
1607
- if (auto *copyAddr = dyn_cast<CopyAddrInst>(inst)) {
1608
- if (!copyAddr->isTakeOfSrc ()) {
1609
- SILBuilderWithScope builder (copyAddr);
1610
- builder.createExplicitCopyAddr (
1611
- copyAddr->getLoc (), copyAddr->getSrc (), copyAddr->getDest (),
1612
- IsTake_t (copyAddr->isTakeOfSrc ()),
1613
- IsInitialization_t (copyAddr->isInitializationOfDest ()));
1614
- copyAddr->eraseFromParent ();
1615
- changed = true ;
1616
- }
1617
- }
1618
-
1619
- // Convert any copy_value of move_only type to explicit copy value.
1620
- if (auto *cvi = dyn_cast<CopyValueInst>(inst)) {
1621
- if (!cvi->getOperand ()->getType ().isMoveOnly ())
1622
- continue ;
1623
- SILBuilderWithScope b (cvi);
1624
- auto *expCopy =
1625
- b.createExplicitCopyValue (cvi->getLoc (), cvi->getOperand ());
1626
- cvi->replaceAllUsesWith (expCopy);
1627
- cvi->eraseFromParent ();
1628
- changed = true ;
1629
- continue ;
1630
- }
1631
- }
1632
- }
1643
+ changed |= ::cleanupAfterEmittingDiagnostic (fn);
1633
1644
}
1634
1645
1635
1646
bool MoveOnlyChecker::searchForCandidateMarkMustChecks () {
@@ -2031,6 +2042,48 @@ bool MoveOnlyChecker::checkFunction() {
2031
2042
return changed;
2032
2043
}
2033
2044
2045
+ // ===----------------------------------------------------------------------===//
2046
+ // MARK: Missed Copy Diagnostic
2047
+ // ===----------------------------------------------------------------------===//
2048
+
2049
+ // / A small diagnostic helper that causes us to emit a diagnostic error upon any
2050
+ // / copies we did not eliminate and ask the user for a test case.
2051
+ static bool checkForMissedCopies (SILFunction *fn) {
2052
+ bool emittedDiagnostic = false ;
2053
+ DiagnosticEmitter diagnosticEmitter;
2054
+ for (auto &block : *fn) {
2055
+ for (auto &inst : block) {
2056
+ if (auto *cvi = dyn_cast<CopyValueInst>(&inst)) {
2057
+ if (cvi->getOperand ()->getType ().isMoveOnly ()) {
2058
+ diagnosticEmitter.emitCheckedMissedCopyError (cvi);
2059
+ emittedDiagnostic = true ;
2060
+ }
2061
+ continue ;
2062
+ }
2063
+
2064
+ if (auto *li = dyn_cast<LoadInst>(&inst)) {
2065
+ if (li->getOwnershipQualifier () == LoadOwnershipQualifier::Copy &&
2066
+ li->getType ().isMoveOnly ()) {
2067
+ diagnosticEmitter.emitCheckedMissedCopyError (li);
2068
+ emittedDiagnostic = true ;
2069
+ }
2070
+ continue ;
2071
+ }
2072
+
2073
+ if (auto *copyAddr = dyn_cast<CopyAddrInst>(&inst)) {
2074
+ if (!copyAddr->isTakeOfSrc () &&
2075
+ copyAddr->getSrc ()->getType ().isMoveOnly ()) {
2076
+ diagnosticEmitter.emitCheckedMissedCopyError (copyAddr);
2077
+ emittedDiagnostic = true ;
2078
+ }
2079
+ continue ;
2080
+ }
2081
+ }
2082
+ }
2083
+
2084
+ return emittedDiagnostic;
2085
+ }
2086
+
2034
2087
// ===----------------------------------------------------------------------===//
2035
2088
// Top Level Entrypoint
2036
2089
// ===----------------------------------------------------------------------===//
@@ -2058,47 +2111,15 @@ class MoveOnlyCheckerPass : public SILFunctionTransform {
2058
2111
auto *deAnalysis = getAnalysis<DeadEndBlocksAnalysis>()->get (fn);
2059
2112
auto *poa = getAnalysis<PostOrderAnalysis>();
2060
2113
2061
- if (MoveOnlyChecker (getFunction (), deAnalysis, domTree, poa)
2062
- .checkFunction ()) {
2063
- invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
2114
+ bool shouldInvalidate =
2115
+ MoveOnlyChecker (getFunction (), deAnalysis, domTree, poa)
2116
+ .checkFunction ();
2117
+ if (checkForMissedCopies (getFunction ())) {
2118
+ cleanupAfterEmittingDiagnostic (getFunction ());
2119
+ shouldInvalidate = true ;
2064
2120
}
2065
-
2066
- if (!getOptions ().VerifyAll )
2067
- return ;
2068
-
2069
- // TODO: Enable this by default when verify all is disabled and make it a
2070
- // diagnostic error saying file a bug.
2071
- for (auto &block : *getFunction ()) {
2072
- for (auto &inst : block) {
2073
- if (auto *cvi = dyn_cast<CopyValueInst>(&inst)) {
2074
- if (cvi->getOperand ()->getType ().isMoveOnly ()) {
2075
- llvm::errs () << " Should have eliminated copy at this point: "
2076
- << *cvi;
2077
- llvm::report_fatal_error (" standard compiler error" );
2078
- }
2079
- continue ;
2080
- }
2081
-
2082
- if (auto *li = dyn_cast<LoadInst>(&inst)) {
2083
- if (li->getOwnershipQualifier () == LoadOwnershipQualifier::Copy &&
2084
- li->getType ().isMoveOnly ()) {
2085
- llvm::errs () << " Should have eliminated copy at this point: "
2086
- << *li;
2087
- llvm::report_fatal_error (" standard compiler error" );
2088
- }
2089
- continue ;
2090
- }
2091
-
2092
- if (auto *copyAddr = dyn_cast<CopyAddrInst>(&inst)) {
2093
- if (!copyAddr->isTakeOfSrc () &&
2094
- copyAddr->getSrc ()->getType ().isMoveOnly ()) {
2095
- llvm::errs () << " Should have eliminated copy at this point: "
2096
- << *copyAddr;
2097
- llvm::report_fatal_error (" standard compiler error" );
2098
- }
2099
- continue ;
2100
- }
2101
- }
2121
+ if (shouldInvalidate) {
2122
+ invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
2102
2123
}
2103
2124
}
2104
2125
};
0 commit comments