mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Otherwise, sometimes when the object checker emits a diagnostic and cleans up the IR, some of the cleaned up copies are copies that should have been handled by the address checker. The end result is that the address checker does not emit diagnostics for that IR. I found this problem was exascerbated when writing code for escaping closures. This commit also cleans up the passes in preparation for at a future time moving some of the transformations into the utils folder.
142 lines
5.2 KiB
C++
142 lines
5.2 KiB
C++
//===--- 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/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/CanonicalizeOSSALifetime.h"
|
|
#include "swift/SILOptimizer/Utils/InstructionDeleter.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 <utility>
|
|
|
|
using namespace swift;
|
|
using namespace swift::siloptimizer;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MARK: Top Level Entrypoint
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
|
|
class MoveOnlyAddressCheckerTesterPass : public SILFunctionTransform {
|
|
void run() override {
|
|
auto *fn = getFunction();
|
|
|
|
// Only run this pass if the move only language feature is enabled.
|
|
if (!fn->getASTContext().LangOpts.Features.contains(Feature::MoveOnly))
|
|
return;
|
|
|
|
// 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<DominanceAnalysis>();
|
|
DominanceInfo *domTree = dominanceAnalysis->get(fn);
|
|
auto *poa = getAnalysis<PostOrderAnalysis>();
|
|
|
|
DiagnosticEmitter diagnosticEmitter;
|
|
SmallSetVector<MarkMustCheckInst *, 32> moveIntroducersToProcess;
|
|
searchForCandidateAddressMarkMustChecks(fn, moveIntroducersToProcess,
|
|
diagnosticEmitter);
|
|
|
|
LLVM_DEBUG(llvm::dbgs()
|
|
<< "Emitting diagnostic when checking for mark must check inst: "
|
|
<< (diagnosticEmitter.getDiagnosticCount() ? "yes" : "no")
|
|
<< '\n');
|
|
|
|
bool madeChange = false;
|
|
unsigned diagCount = 0;
|
|
if (moveIntroducersToProcess.empty()) {
|
|
LLVM_DEBUG(llvm::dbgs() << "No move introducers found?!\n");
|
|
} else {
|
|
borrowtodestructure::IntervalMapAllocator allocator;
|
|
MoveOnlyAddressChecker checker{getFunction(), diagnosticEmitter,
|
|
allocator, domTree, poa};
|
|
madeChange = checker.check(moveIntroducersToProcess);
|
|
diagCount = checker.diagnosticEmitter.getDiagnosticCount();
|
|
}
|
|
|
|
// If we did not emit any diagnostics, emit a diagnostic if we missed any
|
|
// copies.
|
|
if (!diagCount) {
|
|
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();
|
|
}
|