mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Previously, we would emit a "compiler doesn't understand error" since we would detect the escape and fail. That is the correct behavior here if the partial_apply is not already identified as escaping by an earlier pass. But in the case where we see that the partial_apply's callee was marked with semantics::NO_MOVEONLY_DIAGNOSTICS, then we: 1. Suppress the "compiler doesn't understand error" for this specific mark_must_check. 2. Suppress function wide the "copy of noncopyable type" error. Since we stopped processing the mark_must_check that was passed to the partial_apply, we may have left copies of noncopyable types on that mark_must_check value. This is ok since the user will get the error, will recompile, and if any further show up after they fix the inout escaping issue, they will be emitted appropriately.
140 lines
5.1 KiB
C++
140 lines
5.1 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().supportsMoveOnlyTypes())
|
|
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(fn);
|
|
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;
|
|
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);
|
|
}
|
|
|
|
// 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();
|
|
}
|