Add TopDownClosureFunctionOrder based on ClosureScopeAnalysis.

Simple utility for transfersing functions such that parent scopes are always
visited before noescape closures.

Note that recursion is disallowed. Noescape closures are not reentrant.
This commit is contained in:
Andrew Trick
2017-06-15 13:29:28 -07:00
parent 3bec7d81ac
commit 94db617471
2 changed files with 60 additions and 0 deletions

View File

@@ -14,6 +14,7 @@
#define DEBUG_TYPE "closure-scope"
#include "swift/SIL/SILModule.h"
#include "swift/SILOptimizer/Analysis/ClosureScope.h"
namespace swift {
@@ -154,4 +155,42 @@ SILAnalysis *createClosureScopeAnalysis(SILModule *M) {
return new ClosureScopeAnalysis(M);
}
void TopDownClosureFunctionOrder::visitFunctions(
std::function<void(SILFunction *)> visitor) {
auto markVisited = [&](SILFunction *F) {
bool visitOnce = visited.insert(F).second;
assert(visitOnce);
(void)visitOnce;
};
auto allScopesVisited = [&](SILFunction *closureF) {
return llvm::all_of(CSA->getClosureScopes(closureF),
[this](SILFunction *F) { return visited.count(F); });
};
for (auto &F : *CSA->getModule()) {
if (!allScopesVisited(&F)) {
closureWorklist.insert(&F);
continue;
}
markVisited(&F);
visitor(&F);
}
unsigned numClosures = closureWorklist.size();
while (numClosures) {
for (auto &closureNode : closureWorklist) {
// skip erased closures.
if (!closureNode)
continue;
auto closureF = closureNode.getValue();
if (!allScopesVisited(closureF))
continue;
markVisited(closureF);
visitor(closureF);
closureWorklist.erase(closureF);
--numClosures;
}
}
}
} // namespace swift