-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathPassManagerVerifierAnalysis.cpp
134 lines (117 loc) · 4.85 KB
/
PassManagerVerifierAnalysis.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//===--- PassManagerVerifierAnalysis.cpp ----------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 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-passmanager-verifier-analysis"
#include "swift/SILOptimizer/Analysis/PassManagerVerifierAnalysis.h"
#include "swift/Basic/Assertions.h"
#include "swift/SIL/SILModule.h"
#include "llvm/Support/CommandLine.h"
static llvm::cl::opt<bool>
EnableVerifier("enable-sil-passmanager-verifier-analysis",
llvm::cl::desc("Enable verification of the passmanagers "
"function notification infrastructure"),
llvm::cl::init(true));
using namespace swift;
PassManagerVerifierAnalysis::PassManagerVerifierAnalysis(SILModule *mod)
: SILAnalysis(SILAnalysisKind::PassManagerVerifier), mod(*mod) {
#ifndef NDEBUG
if (!EnableVerifier)
return;
for (auto &fn : *mod) {
LLVM_DEBUG(llvm::dbgs() << "PMVerifierAnalysis. Add: " << fn.getName()
<< '\n');
liveFunctionNames.insert(fn.getName());
}
#endif
}
/// Validate that the analysis is able to look up all functions and that those
/// functions are live.
void PassManagerVerifierAnalysis::invalidate() {}
/// Validate that the analysis is able to look up the given function.
void PassManagerVerifierAnalysis::invalidate(SILFunction *f,
InvalidationKind k) {}
/// If a function has not yet been seen start tracking it.
void PassManagerVerifierAnalysis::notifyAddedOrModifiedFunction(
SILFunction *f) {
#ifndef NDEBUG
if (!EnableVerifier)
return;
LLVM_DEBUG(llvm::dbgs() << "PMVerifierAnalysis. Add|Mod: " << f->getName()
<< '\n');
liveFunctionNames.insert(f->getName());
#endif
}
/// Stop tracking a function.
void PassManagerVerifierAnalysis::notifyWillDeleteFunction(SILFunction *f) {
#ifndef NDEBUG
if (!EnableVerifier)
return;
LLVM_DEBUG(llvm::dbgs() << "PMVerifierAnalysis. Delete: " << f->getName()
<< '\n');
if (liveFunctionNames.erase(f->getName()))
return;
llvm::errs()
<< "Error! Tried to delete function that analysis was not aware of: "
<< f->getName() << '\n';
llvm_unreachable("triggering standard assertion failure routine");
#endif
}
/// Make sure that when we invalidate a function table, make sure we can find
/// all functions for all witness tables.
void PassManagerVerifierAnalysis::invalidateFunctionTables() {}
/// Run the entire verification.
void PassManagerVerifierAnalysis::verifyFull() const {
#ifndef NDEBUG
if (!EnableVerifier)
return;
// We check that liveFunctionNames is in sync with the module's function list
// by going through the module's function list and attempting to remove all
// functions in the module. If we fail to remove fn, then we know that a
// function was added to the module without an appropriate message being sent
// by the pass manager.
bool foundError = false;
unsigned count = 0;
for (auto &fn : mod) {
if (liveFunctionNames.count(fn.getName())) {
++count;
continue;
}
llvm::errs() << "Found function in module that was not added to verifier: "
<< fn.getName() << '\n';
foundError = true;
}
// Ok, so now we know that function(mod) is a subset of
// liveFunctionNames. Relying on the uniqueness provided by the module's
// function list, we know that liveFunction should be exactly count in
// size. Otherwise, we must have an error. If and only if we detect this
// error, do the expensive work of finding the missing deletes. This is an
// important performance optimization to avoid a large copy on the hot path.
if (liveFunctionNames.size() != count) {
auto liveFunctionNamesCopy = llvm::StringSet<>(liveFunctionNames);
for (auto &fn : mod) {
liveFunctionNamesCopy.erase(fn.getName());
}
for (auto &iter : liveFunctionNamesCopy) {
llvm::errs() << "Missing delete message for function: " << iter.first()
<< '\n';
foundError = true;
}
}
// We assert here so we emit /all/ errors before asserting.
assert(!foundError && "triggering standard assertion failure routine");
#endif
}
//===----------------------------------------------------------------------===//
// Main Entry Point
//===----------------------------------------------------------------------===//
SILAnalysis *swift::createPassManagerVerifierAnalysis(SILModule *m) {
return new PassManagerVerifierAnalysis(m);
}