2828#include " swift/SIL/SILInstruction.h"
2929#include " swift/SILOptimizer/Analysis/Analysis.h"
3030#include " swift/SILOptimizer/Analysis/DeadEndBlocksAnalysis.h"
31+ #include " swift/Basic/BlotSetVector.h"
32+ #include " swift/Basic/FrozenMultiMap.h"
3133#include " swift/SILOptimizer/Analysis/PostOrderAnalysis.h"
3234#include " swift/SILOptimizer/PassManager/Passes.h"
3335#include " swift/SILOptimizer/PassManager/Transforms.h"
3739using namespace swift ;
3840using namespace swift ::siloptimizer;
3941
40- using namespace swift ;
41- using namespace swift ::siloptimizer;
42-
4342namespace {
4443using AvailableValues = BorrowToDestructureTransform::AvailableValues;
4544}
@@ -202,8 +201,8 @@ void BorrowToDestructureTransform::checkDestructureUsesOnBoundary() const {
202201 for (auto *use : destructureNeedingUses) {
203202 LLVM_DEBUG (llvm::dbgs ()
204203 << " DestructureNeedingUse: " << *use->getUser ());
205- auto destructureUse = *TypeTreeLeafTypeRange::get (use->get (), mmci);
206- if (liveness.isWithinBoundary (use->getUser (), destructureUse )) {
204+ auto destructureUseSpan = *TypeTreeLeafTypeRange::get (use->get (), mmci);
205+ if (liveness.isWithinBoundary (use->getUser (), destructureUseSpan )) {
207206 LLVM_DEBUG (llvm::dbgs () << " Within boundary! Emitting error!\n " );
208207 // Emit an error. We have a use after free.
209208 //
@@ -217,7 +216,7 @@ void BorrowToDestructureTransform::checkDestructureUsesOnBoundary() const {
217216 liveness.getNumSubElements ());
218217 liveness.computeBoundary (boundary);
219218 diagnosticEmitter.emitObjectDestructureNeededWithinBorrowBoundary (
220- mmci, use->getUser (), destructureUse , boundary);
219+ mmci, use->getUser (), destructureUseSpan , boundary);
221220 return ;
222221 } else {
223222 LLVM_DEBUG (llvm::dbgs () << " On boundary! No error!\n " );
@@ -1338,12 +1337,20 @@ static bool runTransform(SILFunction *fn,
13381337 auto *mmci = moveIntroducersToProcess.back ();
13391338 moveIntroducersToProcess = moveIntroducersToProcess.drop_back ();
13401339
1340+ unsigned currentDiagnosticCount = diagnosticEmitter.getDiagnosticCount ();
1341+
13411342 StackList<BeginBorrowInst *> borrowWorklist (mmci->getFunction ());
13421343
13431344 // If we failed to gather borrows due to the transform not understanding
1344- // part of the SIL, fail and return false.
1345- if (!BorrowToDestructureTransform::gatherBorrows (mmci, borrowWorklist))
1346- return madeChange;
1345+ // part of the SIL, emit a diagnostic, RAUW the mark must check, and
1346+ // continue.
1347+ if (!BorrowToDestructureTransform::gatherBorrows (mmci, borrowWorklist)) {
1348+ diagnosticEmitter.emitCheckerDoesntUnderstandDiagnostic (mmci);
1349+ mmci->replaceAllUsesWith (mmci->getOperand ());
1350+ mmci->eraseFromParent ();
1351+ madeChange = true ;
1352+ continue ;
1353+ }
13471354
13481355 // If we do not have any borrows to process, continue and process the next
13491356 // instruction.
@@ -1360,29 +1367,43 @@ static bool runTransform(SILFunction *fn,
13601367 poa, discoveredBlocks);
13611368
13621369 // Attempt to gather uses. Return if we saw something that we did not
1363- // understand. Return made change so we invalidate as appropriate.
1364- if (!transform.gatherUses (borrowWorklist))
1365- return madeChange;
1370+ // understand. Emit a compiler did not understand diagnostic, RAUW the mmci
1371+ // so later passes do not see it, and set madeChange to true.
1372+ if (!transform.gatherUses (borrowWorklist)) {
1373+ diagnosticEmitter.emitCheckerDoesntUnderstandDiagnostic (mmci);
1374+ mmci->replaceAllUsesWith (mmci->getOperand ());
1375+ mmci->eraseFromParent ();
1376+ madeChange = true ;
1377+ continue ;
1378+ }
13661379
13671380 // Next make sure that any destructure needing instructions are on the
13681381 // boundary in a per bit field sensitive manner.
13691382 transform.checkDestructureUsesOnBoundary ();
13701383
1371- // If we emitted any diagnostic, break out. We return true since we actually
1372- // succeeded in our processing by finding the error. We only return false if
1373- // we want to tell the rest of the checker that there was an internal
1374- // compiler error that we need to emit a "compiler doesn't understand
1375- // error".
1376- if (diagnosticEmitter.emittedAnyDiagnostics ())
1377- return madeChange;
1384+ // If we emitted any diagnostic, set madeChange to true, eliminate our mmci,
1385+ // and continue.
1386+ if (currentDiagnosticCount != diagnosticEmitter.getDiagnosticCount ()) {
1387+ mmci->replaceAllUsesWith (mmci->getOperand ());
1388+ mmci->eraseFromParent ();
1389+ madeChange = true ;
1390+ continue ;
1391+ }
13781392
13791393 // At this point, we know that all of our destructure requiring uses are on
13801394 // the boundary of our live range. Now we need to do the rewriting.
13811395 transform.blockToAvailableValues .emplace (transform.liveness );
13821396 transform.rewriteUses ();
13831397
13841398 // Now that we have done our rewritting, we need to do a few cleanups.
1399+ //
1400+ // NOTE: We do not eliminate our mark_must_check since we want later passes
1401+ // to do additional checking upon the mark_must_check including making sure
1402+ // that our destructures do not need cause the need for additional copies to
1403+ // be inserted. We only eliminate the mark_must_check if we emitted a
1404+ // diagnostic of some sort.
13851405 transform.cleanup (borrowWorklist);
1406+ madeChange = true ;
13861407 }
13871408
13881409 return madeChange;
@@ -1405,8 +1426,9 @@ class MoveOnlyBorrowToDestructureTransformPass : public SILFunctionTransform {
14051426 assert (fn->getModule ().getStage () == SILStage::Raw &&
14061427 " Should only run on Raw SIL" );
14071428
1408- LLVM_DEBUG (llvm::dbgs () << " ===> MoveOnly Object Checker. Visiting: "
1409- << fn->getName () << ' \n ' );
1429+ LLVM_DEBUG (llvm::dbgs ()
1430+ << " ===> MoveOnlyBorrowToDestructureTransform. Visiting: "
1431+ << fn->getName () << ' \n ' );
14101432
14111433 auto *postOrderAnalysis = getAnalysis<PostOrderAnalysis>();
14121434
@@ -1419,14 +1441,22 @@ class MoveOnlyBorrowToDestructureTransformPass : public SILFunctionTransform {
14191441 invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
14201442 }
14211443
1422- if (emitter.emittedAnyDiagnostics ())
1444+ if (emitter.emittedAnyDiagnostics ()) {
1445+ if (cleanupSILAfterEmittingObjectMoveOnlyDiagnostics (fn))
1446+ invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
14231447 return ;
1448+ }
14241449
14251450 auto introducers = llvm::makeArrayRef (moveIntroducersToProcess.begin (),
14261451 moveIntroducersToProcess.end ());
14271452 if (runTransform (fn, introducers, postOrderAnalysis, emitter)) {
14281453 invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
14291454 }
1455+
1456+ if (emitter.emittedAnyDiagnostics ()) {
1457+ if (cleanupSILAfterEmittingObjectMoveOnlyDiagnostics (fn))
1458+ invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
1459+ }
14301460 }
14311461};
14321462
0 commit comments