//===--- MoveOnlyAddressCheckerTester.cpp ---------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "sil-move-only-checker" #include "swift/AST/AccessScope.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticsSIL.h" #include "swift/Basic/Assertions.h" #include "swift/Basic/Debug.h" #include "swift/Basic/Defer.h" #include "swift/Basic/FrozenMultiMap.h" #include "swift/Basic/SmallBitVector.h" #include "swift/SIL/ApplySite.h" #include "swift/SIL/BasicBlockBits.h" #include "swift/SIL/BasicBlockData.h" #include "swift/SIL/BasicBlockDatastructures.h" #include "swift/SIL/BasicBlockUtils.h" #include "swift/SIL/Consumption.h" #include "swift/SIL/DebugUtils.h" #include "swift/SIL/FieldSensitivePrunedLiveness.h" #include "swift/SIL/InstructionUtils.h" #include "swift/SIL/MemAccessUtils.h" #include "swift/SIL/OwnershipUtils.h" #include "swift/SIL/PrunedLiveness.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILArgumentConvention.h" #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILUndef.h" #include "swift/SIL/SILValue.h" #include "swift/SILOptimizer/Analysis/ClosureScope.h" #include "swift/SILOptimizer/Analysis/DeadEndBlocksAnalysis.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" #include "swift/SILOptimizer/Analysis/NonLocalAccessBlockAnalysis.h" #include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SILOptimizer/Utils/InstructionDeleter.h" #include "swift/SILOptimizer/Utils/OSSACanonicalizeOwned.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "MoveOnlyAddressCheckerUtils.h" #include "MoveOnlyBorrowToDestructureUtils.h" #include "MoveOnlyDiagnostics.h" #include "MoveOnlyObjectCheckerUtils.h" #include "MoveOnlyUtils.h" #include using namespace swift; using namespace swift::siloptimizer; //===----------------------------------------------------------------------===// // MARK: Top Level Entrypoint //===----------------------------------------------------------------------===// namespace { class MoveOnlyAddressCheckerTesterPass : public SILFunctionTransform { void run() override { auto *fn = getFunction(); // Don't rerun diagnostics on deserialized functions. if (getFunction()->wasDeserializedCanonical()) return; assert(fn->getModule().getStage() == SILStage::Raw && "Should only run on Raw SIL"); LLVM_DEBUG(llvm::dbgs() << "===> MoveOnly Addr Checker. Visiting: " << fn->getName() << '\n'); auto *dominanceAnalysis = getAnalysis(); DominanceInfo *domTree = dominanceAnalysis->get(fn); auto *poa = getAnalysis(); auto *deba = getAnalysis(); DiagnosticEmitter diagnosticEmitter(fn); llvm::SmallSetVector moveIntroducersToProcess; searchForCandidateAddressMarkUnresolvedNonCopyableValueInsts( fn, getAnalysis(), moveIntroducersToProcess, diagnosticEmitter); LLVM_DEBUG(llvm::dbgs() << "Emitting diagnostic when checking for mark must check inst: " << (diagnosticEmitter.getDiagnosticCount() ? "yes" : "no") << '\n'); bool madeChange = false; if (moveIntroducersToProcess.empty()) { LLVM_DEBUG(llvm::dbgs() << "No move introducers found?!\n"); } else { borrowtodestructure::IntervalMapAllocator allocator; MoveOnlyAddressChecker checker{ getFunction(), diagnosticEmitter, allocator, domTree, poa, deba}; madeChange = checker.completeLifetimes(); madeChange |= checker.check(moveIntroducersToProcess); } // If we did not emit any diagnostics, emit a diagnostic if we missed any // copies. if (!diagnosticEmitter.emittedDiagnostic()) { emitCheckerMissedCopyOfNonCopyableTypeErrors(getFunction(), diagnosticEmitter); } // Then cleanup any copies we left behind for either reason and emit an // error. madeChange |= cleanupNonCopyableCopiesAfterEmittingDiagnostic(getFunction()); if (madeChange) { invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions); } } }; } // anonymous namespace SILTransform *swift::createMoveOnlyAddressChecker() { return new MoveOnlyAddressCheckerTesterPass(); }