Skip to content

Commit e39192a

Browse files
committed
---
yaml --- r: 344895 b: refs/heads/master c: ea0f2c9 h: refs/heads/master i: 344893: a0f3dcb 344891: dde4eaf 344887: 2e6c3c1 344879: beae2cf 344863: e9be8c7 344831: de08789
1 parent 2d03bcd commit e39192a

File tree

5 files changed

+71
-26
lines changed

5 files changed

+71
-26
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 008c4a0c0868e6fda6ae550cf73c3b0c63deb833
2+
refs/heads/master: ea0f2c9b067800ca0723eb2c3ec97799d4ac53e3
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/SILOptimizer/Analysis/PassManagerVerifierAnalysis.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/SIL/SILFunction.h"
1717
#include "swift/SILOptimizer/Analysis/Analysis.h"
1818
#include "llvm/ADT/DenseSet.h"
19+
#include "llvm/ADT/StringSet.h"
1920

2021
namespace swift {
2122

@@ -28,10 +29,12 @@ class PassManagerVerifierAnalysis : public SILAnalysis {
2829
LLVM_ATTRIBUTE_UNUSED
2930
SILModule &mod;
3031

31-
/// The set of "live" functions that we are tracking.
32+
/// The set of "live" functions that we are tracking. We store the names of
33+
/// the functions so that if a function is deleted we do not need to touch its
34+
/// memory to get its name.
3235
///
3336
/// All functions in mod must be in liveFunctions and vis-a-versa.
34-
llvm::DenseSet<SILFunction *> liveFunctions;
37+
llvm::StringSet<> liveFunctionNames;
3538

3639
public:
3740
PassManagerVerifierAnalysis(SILModule *mod);
@@ -58,7 +61,7 @@ class PassManagerVerifierAnalysis : public SILAnalysis {
5861
void invalidateFunctionTables() override final;
5962

6063
/// Run the entire verification.
61-
void verify() const override final;
64+
void verifyFull() const override final;
6265
};
6366

6467
} // namespace swift

trunk/lib/SILOptimizer/Analysis/PassManagerVerifierAnalysis.cpp

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ PassManagerVerifierAnalysis::PassManagerVerifierAnalysis(SILModule *mod)
3131
for (auto &fn : *mod) {
3232
LLVM_DEBUG(llvm::dbgs() << "PMVerifierAnalysis. Add: " << fn.getName()
3333
<< '\n');
34-
liveFunctions.insert(&fn);
34+
liveFunctionNames.insert(fn.getName());
3535
}
3636
#endif
3737
}
@@ -52,7 +52,7 @@ void PassManagerVerifierAnalysis::notifyAddedOrModifiedFunction(
5252
return;
5353
LLVM_DEBUG(llvm::dbgs() << "PMVerifierAnalysis. Add|Mod: " << f->getName()
5454
<< '\n');
55-
liveFunctions.insert(f);
55+
liveFunctionNames.insert(f->getName());
5656
#endif
5757
}
5858

@@ -63,9 +63,13 @@ void PassManagerVerifierAnalysis::notifyWillDeleteFunction(SILFunction *f) {
6363
return;
6464
LLVM_DEBUG(llvm::dbgs() << "PMVerifierAnalysis. Delete: " << f->getName()
6565
<< '\n');
66-
assert(liveFunctions.count(f) &&
67-
"Tried to delete function that analysis was not aware of?!");
68-
liveFunctions.erase(f);
66+
if (liveFunctionNames.erase(f->getName()))
67+
return;
68+
69+
llvm::errs()
70+
<< "Error! Tried to delete function that analysis was not aware of: "
71+
<< f->getName() << '\n';
72+
llvm_unreachable("triggering standard assertion failure routine");
6973
#endif
7074
}
7175

@@ -74,22 +78,49 @@ void PassManagerVerifierAnalysis::notifyWillDeleteFunction(SILFunction *f) {
7478
void PassManagerVerifierAnalysis::invalidateFunctionTables() {}
7579

7680
/// Run the entire verification.
77-
void PassManagerVerifierAnalysis::verify() const {
81+
void PassManagerVerifierAnalysis::verifyFull() const {
7882
#ifndef NDEBUG
7983
if (!EnableVerifier)
8084
return;
8185

82-
// We check that all functions in the module are in liveFunctions /and/ then
83-
// make sure that liveFunctions has the same number of elements. If we have
84-
// too many elements, this means we missed a delete event.
85-
unsigned funcCount = 0;
86+
// We check that liveFunctionNames is in sync with the module's function list
87+
// by going through the module's function list and attempting to remove all
88+
// functions in the module. If we fail to remove fn, then we know that a
89+
// function was added to the module without an appropriate message being sent
90+
// by the pass manager.
91+
bool foundError = false;
92+
93+
unsigned count = 0;
8694
for (auto &fn : mod) {
87-
++funcCount;
88-
assert(liveFunctions.count(&fn) &&
89-
"Found function in module that verifier is not aware of?!");
95+
if (liveFunctionNames.count(fn.getName())) {
96+
++count;
97+
continue;
98+
}
99+
llvm::errs() << "Found function in module that was not added to verifier: "
100+
<< fn.getName() << '\n';
101+
foundError = true;
90102
}
91-
assert(liveFunctions.size() == funcCount &&
92-
"Analysis has state for deleted functions?!");
103+
104+
// Ok, so now we know that function(mod) is a subset of
105+
// liveFunctionNames. Relying on the uniqueness provided by the module's
106+
// function list, we know that liveFunction should be exactly count in
107+
// size. Otherwise, we must have an error. If and only if we detect this
108+
// error, do the expensive work of finding the missing deletes. This is an
109+
// important performance optimization to avoid a large copy on the hot path.
110+
if (liveFunctionNames.size() != count) {
111+
auto liveFunctionNamesCopy = llvm::StringSet<>(liveFunctionNames);
112+
for (auto &fn : mod) {
113+
liveFunctionNamesCopy.erase(fn.getName());
114+
}
115+
for (auto &iter : liveFunctionNamesCopy) {
116+
llvm::errs() << "Missing delete message for function: " << iter.first()
117+
<< '\n';
118+
foundError = true;
119+
}
120+
}
121+
122+
// We assert here so we emit /all/ errors before asserting.
123+
assert(!foundError && "triggering standard assertion failure routine");
93124
#endif
94125
}
95126

trunk/lib/Sema/CSSolver.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,26 +1860,29 @@ static Constraint *selectBestBindingDisjunction(
18601860
// type variable.
18611861
SmallVector<Constraint *, 8> bindingDisjunctions;
18621862
for (auto *disjunction : disjunctions) {
1863-
llvm::Optional<TypeVariableType *> commonTypeVariable;
1863+
TypeVariableType *commonTypeVariable = nullptr;
18641864
if (llvm::all_of(
18651865
disjunction->getNestedConstraints(),
18661866
[&](Constraint *bindingConstraint) {
18671867
if (bindingConstraint->getKind() != ConstraintKind::Bind)
18681868
return false;
18691869

1870-
auto *tv =
1871-
bindingConstraint->getFirstType()->getAs<TypeVariableType>();
1870+
auto *tv = cs.simplifyType(bindingConstraint->getFirstType())
1871+
->getRValueType()
1872+
->getAs<TypeVariableType>();
18721873
// Only do this for simple type variable bindings, not for
18731874
// bindings like: ($T1) -> $T2 bind String -> Int
18741875
if (!tv)
18751876
return false;
18761877

1877-
if (!commonTypeVariable.hasValue())
1878-
commonTypeVariable = tv;
1879-
1880-
if (commonTypeVariable.getValue() != tv)
1878+
// If we've seen a variable before, make sure that this is
1879+
// the same one.
1880+
if (commonTypeVariable == tv)
1881+
return true;
1882+
if (commonTypeVariable)
18811883
return false;
18821884

1885+
commonTypeVariable = tv;
18831886
return true;
18841887
})) {
18851888
bindingDisjunctions.push_back(disjunction);

trunk/test/Sema/generalized_accessors.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,11 @@ struct Modify {
104104
nonmutating set {} // expected-note {{setter defined here}}
105105
}
106106
}
107+
108+
struct ImplicitlyUnwrapped {
109+
var x: Int!
110+
var y: Int? {
111+
_read { yield x }
112+
_modify { yield &x }
113+
}
114+
}

0 commit comments

Comments
 (0)