Skip to content

Commit 0640f33

Browse files
authored
Merge pull request #31539 from gottesmm/pr-88ca78b6938c98c9da3c1f7a88d81fac297d0ee2
[ownership] Add new pass OwnershipVerifierTextualErrorDumper and use it in ownership verifier FileCheck tests instead of SILVerifier.
2 parents 94a7af4 + 82b08c5 commit 0640f33

12 files changed

+135
-27
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,13 @@ class SILFunction
10521052
/// invariants.
10531053
void verify(bool SingleFunction = true) const;
10541054

1055+
/// Run the SIL ownership verifier to check for ownership invariant failures.
1056+
///
1057+
/// NOTE: The ownership verifier is always run when performing normal IR
1058+
/// verification, so this verification can be viewed as a subset of
1059+
/// SILFunction::verify.
1060+
void verifyOwnership(DeadEndBlocks *deadEndBlocks = nullptr) const;
1061+
10551062
/// Verify that all non-cond-br critical edges have been split.
10561063
///
10571064
/// This is a fast subset of the checks performed in the SILVerifier.

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ PASS(UsePrespecialized, "use-prespecialized",
314314
"Use Pre-Specialized Functions")
315315
PASS(OwnershipDumper, "ownership-dumper",
316316
"Print Ownership information for Testing")
317+
PASS(OwnershipVerifierTextualErrorDumper, "ownership-verifier-textual-error-dumper",
318+
"Run ownership verification on all functions, emitting FileCheck-able textual errors instead of asserting")
317319
PASS(SemanticARCOpts, "semantic-arc-opts",
318320
"Semantic ARC Optimization")
319321
PASS(SimplifyUnreachableContainingBlocks, "simplify-unreachable-containing-blocks",

lib/SIL/Verifier/SILOwnershipVerifier.cpp

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -882,12 +882,41 @@ void SILInstruction::verifyOperandOwnership() const {
882882
}
883883
}
884884

885+
static void verifySILValueHelper(const SILFunction *f, SILValue value,
886+
DeadEndBlocks *deadEndBlocks) {
887+
assert(!isa<SILUndef>(value) &&
888+
"We assume we are always passed arguments or instruction results");
889+
890+
// If the given function has unqualified ownership or we have been asked by
891+
// the user not to verify this function, there is nothing to verify.
892+
if (!f->hasOwnership() || !f->shouldVerifyOwnership())
893+
return;
894+
895+
using BehaviorKind = LinearLifetimeChecker::ErrorBehaviorKind;
896+
Optional<LinearLifetimeChecker::ErrorBuilder> errorBuilder;
897+
if (IsSILOwnershipVerifierTestingEnabled) {
898+
errorBuilder.emplace(*f, BehaviorKind::PrintMessageAndReturnFalse);
899+
} else {
900+
errorBuilder.emplace(*f, BehaviorKind::PrintMessageAndAssert);
901+
}
902+
903+
SmallPtrSet<SILBasicBlock *, 32> liveBlocks;
904+
if (deadEndBlocks) {
905+
SILValueOwnershipChecker(*deadEndBlocks, value, *errorBuilder, liveBlocks)
906+
.check();
907+
} else {
908+
DeadEndBlocks deadEndBlocks(f);
909+
SILValueOwnershipChecker(deadEndBlocks, value, *errorBuilder, liveBlocks)
910+
.check();
911+
}
912+
}
913+
885914
void SILValue::verifyOwnership(DeadEndBlocks *deadEndBlocks) const {
886915
if (DisableOwnershipVerification)
887916
return;
888917

889918
// Do not validate SILUndef values.
890-
if (isa<SILUndef>(Value))
919+
if (isa<SILUndef>(*this))
891920
return;
892921

893922
#ifdef NDEBUG
@@ -898,8 +927,8 @@ void SILValue::verifyOwnership(DeadEndBlocks *deadEndBlocks) const {
898927
// that if we run into something that we do not understand, we do not assert
899928
// in user code even tohugh we aren't going to actually verify (the default
900929
// behavior when -sil-verify-all is disabled).
901-
auto *Mod = Value->getModule();
902-
if (!Mod || !Mod->getOptions().VerifyAll)
930+
auto *mod = Value->getModule();
931+
if (!mod || !mod->getOptions().VerifyAll)
903932
return;
904933
#endif
905934

@@ -911,31 +940,51 @@ void SILValue::verifyOwnership(DeadEndBlocks *deadEndBlocks) const {
911940
}
912941
}
913942

943+
// If we are testing the verifier, bail so we only print errors once when
944+
// performing a full verification a function at a time by the
945+
// OwnershipVerifierStateDumper pass, instead of additionally in the
946+
// SILBuilder and in the actual SIL verifier that may be run by sil-opt.
947+
if (IsSILOwnershipVerifierTestingEnabled)
948+
return;
949+
914950
// Since we do not have SILUndef, we now know that getFunction() should return
915951
// a real function. Assert in case this assumption is no longer true.
916-
SILFunction *f = (*this)->getFunction();
952+
auto *f = (*this)->getFunction();
917953
assert(f && "Instructions and arguments should have a function");
954+
verifySILValueHelper(f, *this, deadEndBlocks);
955+
}
956+
957+
void SILFunction::verifyOwnership(DeadEndBlocks *deadEndBlocks) const {
958+
if (DisableOwnershipVerification)
959+
return;
960+
961+
#ifdef NDEBUG
962+
// When compiling without asserts enabled, only verify ownership if
963+
// -sil-verify-all is set.
964+
//
965+
// NOTE: We purposely return if we do can not look up a module here to ensure
966+
// that if we run into something that we do not understand, we do not assert
967+
// in user code even tohugh we aren't going to actually verify (the default
968+
// behavior when -sil-verify-all is disabled).
969+
auto *mod = getParent();
970+
if (!mod || !mod->getOptions().VerifyAll)
971+
return;
972+
#endif
918973

919974
// If the given function has unqualified ownership or we have been asked by
920975
// the user not to verify this function, there is nothing to verify.
921-
if (!f->hasOwnership() || !f->shouldVerifyOwnership())
976+
if (!hasOwnership() || !shouldVerifyOwnership())
922977
return;
923978

924-
using BehaviorKind = LinearLifetimeChecker::ErrorBehaviorKind;
925-
Optional<LinearLifetimeChecker::ErrorBuilder> errorBuilder;
926-
if (IsSILOwnershipVerifierTestingEnabled) {
927-
errorBuilder.emplace(*f, BehaviorKind::PrintMessageAndReturnFalse);
928-
} else {
929-
errorBuilder.emplace(*f, BehaviorKind::PrintMessageAndAssert);
930-
}
979+
for (auto &block : *this) {
980+
for (auto *arg : block.getArguments()) {
981+
verifySILValueHelper(this, arg, deadEndBlocks);
982+
}
931983

932-
SmallPtrSet<SILBasicBlock *, 32> liveBlocks;
933-
if (deadEndBlocks) {
934-
SILValueOwnershipChecker(*deadEndBlocks, *this, *errorBuilder, liveBlocks)
935-
.check();
936-
} else {
937-
DeadEndBlocks deadEndBlocks(f);
938-
SILValueOwnershipChecker(deadEndBlocks, *this, *errorBuilder, liveBlocks)
939-
.check();
984+
for (auto &inst : block) {
985+
for (auto result : inst.getResults()) {
986+
verifySILValueHelper(this, result, deadEndBlocks);
987+
}
988+
}
940989
}
941990
}

lib/SILOptimizer/UtilityPasses/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ silopt_register_sources(
3131
SimplifyUnreachableContainingBlocks.cpp
3232
StripDebugInfo.cpp
3333
OwnershipDumper.cpp
34+
OwnershipVerifierTextualErrorDumper.cpp
3435
)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===--- OwnershipVerifierStateDumper.cpp ---------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
///
13+
/// \file
14+
///
15+
/// This is a simple utility pass that verifies the ownership of all SILValue in
16+
/// a module with a special flag set that causes the verifier to emit textual
17+
/// errors instead of asserting. This is done one function at a time so that we
18+
/// can number the errors as we emit them so in FileCheck tests, we can be 100%
19+
/// sure we exactly matched the number of errors.
20+
///
21+
//===----------------------------------------------------------------------===//
22+
23+
#include "swift/SIL/BasicBlockUtils.h"
24+
#include "swift/SIL/SILFunction.h"
25+
#include "swift/SIL/SILInstruction.h"
26+
#include "swift/SILOptimizer/PassManager/Passes.h"
27+
#include "swift/SILOptimizer/PassManager/Transforms.h"
28+
29+
using namespace swift;
30+
31+
//===----------------------------------------------------------------------===//
32+
// Top Level Entrypoint
33+
//===----------------------------------------------------------------------===//
34+
35+
namespace {
36+
37+
class OwnershipVerifierTextualErrorDumper : public SILFunctionTransform {
38+
void run() override {
39+
SILFunction *f = getFunction();
40+
DeadEndBlocks deadEndBlocks(f);
41+
f->verifyOwnership(&deadEndBlocks);
42+
}
43+
};
44+
45+
} // end anonymous namespace
46+
47+
SILTransform *swift::createOwnershipVerifierTextualErrorDumper() {
48+
return new OwnershipVerifierTextualErrorDumper();
49+
}

test/SIL/ownership-verifier/arguments.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -module-name Swift -sil-ownership-verifier-enable-testing -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
1+
// RUN: %target-sil-opt -module-name Swift -sil-ownership-verifier-enable-testing -ownership-verifier-textual-error-dumper -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
22
// REQUIRES: asserts
33

44
// This is a test that verifies ownership behavior around arguments that should

test/SIL/ownership-verifier/borrow_scope_introducing_operands.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -enable-sil-verify-all=0 -o /dev/null %s 2>&1 | %FileCheck %s
1+
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -ownership-verifier-textual-error-dumper -enable-sil-verify-all=0 -o /dev/null %s 2>&1 | %FileCheck %s
22
// REQUIRES: asserts
33

44
// This file tests that when we emit an error, it is a true negative. This is

test/SIL/ownership-verifier/disable_verifier_using_semantic_tag.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
1+
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -ownership-verifier-textual-error-dumper -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
22
// REQUIRES: asserts
33

44
// This test makes sure that the ownership verifier can be disabled on specific

test/SIL/ownership-verifier/interior_pointer.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
1+
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -ownership-verifier-textual-error-dumper -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
22
// REQUIRES: asserts
33

44
sil_stage canonical

test/SIL/ownership-verifier/leaks.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -module-name Swift -sil-ownership-verifier-enable-testing -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
1+
// RUN: %target-sil-opt -module-name Swift -sil-ownership-verifier-enable-testing -ownership-verifier-textual-error-dumper -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
22
// REQUIRES: asserts
33

44
// This file is meant to contain dataflow tests that are true leaks. It is

test/SIL/ownership-verifier/over_consume.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -enable-sil-verify-all=0 -o /dev/null 2>&1 %s | %FileCheck %s
1+
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -ownership-verifier-textual-error-dumper -enable-sil-verify-all=0 -o /dev/null %s 2>&1 | %FileCheck %s
22
// REQUIRES: asserts
33

44
sil_stage canonical

test/SIL/ownership-verifier/subobject_borrowing.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -enable-sil-verify-all=0 -o /dev/null 2>&1 %s | %FileCheck %s
1+
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -ownership-verifier-textual-error-dumper -enable-sil-verify-all=0 -o /dev/null %s 2>&1 | %FileCheck %s
22
// REQUIRES: asserts
33

44
sil_stage canonical

0 commit comments

Comments
 (0)