зеркало из https://github.com/microsoft/clang-1.git
Add new GRWorkList class that uses two queues:
- one queue (FIFO) to queue up nodes at block entrances - another queue (LIFO) to queue up other nodes - The idea is to explore basic blocks to completion, but to do a BFS exploration of blocks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61106 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
8c354758c2
Коммит
e1efd4de86
|
@ -613,7 +613,8 @@ public:
|
||||||
/// Construct a GRCoreEngine object to analyze the provided CFG using
|
/// Construct a GRCoreEngine object to analyze the provided CFG using
|
||||||
/// a DFS exploration of the exploded graph.
|
/// a DFS exploration of the exploded graph.
|
||||||
GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, SubEngineTy& subengine)
|
GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, SubEngineTy& subengine)
|
||||||
: GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), GRWorkList::MakeDFS()),
|
: GRCoreEngineImpl(new GraphTy(cfg, cd, ctx),
|
||||||
|
GRWorkList::MakeBFSBlockDFSContents()),
|
||||||
SubEngine(subengine) {}
|
SubEngine(subengine) {}
|
||||||
|
|
||||||
/// Construct a GRCoreEngine object to analyze the provided CFG and to
|
/// Construct a GRCoreEngine object to analyze the provided CFG and to
|
||||||
|
|
|
@ -69,6 +69,7 @@ public:
|
||||||
GRBlockCounter getBlockCounter() const { return CurrentCounter; }
|
GRBlockCounter getBlockCounter() const { return CurrentCounter; }
|
||||||
|
|
||||||
static GRWorkList* MakeDFS();
|
static GRWorkList* MakeDFS();
|
||||||
|
static GRWorkList* MakeBFSBlockDFSContents();
|
||||||
};
|
};
|
||||||
} // end clang namespace
|
} // end clang namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,11 +18,16 @@
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
using llvm::cast;
|
using llvm::cast;
|
||||||
using llvm::isa;
|
using llvm::isa;
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Worklist classes for exploration of reachable states.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class VISIBILITY_HIDDEN DFS : public GRWorkList {
|
class VISIBILITY_HIDDEN DFS : public GRWorkList {
|
||||||
llvm::SmallVector<GRWorkListUnit,20> Stack;
|
llvm::SmallVector<GRWorkListUnit,20> Stack;
|
||||||
|
@ -50,6 +55,48 @@ GRWorkList::~GRWorkList() {}
|
||||||
|
|
||||||
GRWorkList* GRWorkList::MakeDFS() { return new DFS(); }
|
GRWorkList* GRWorkList::MakeDFS() { return new DFS(); }
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class VISIBILITY_HIDDEN BFSBlockDFSContents : public GRWorkList {
|
||||||
|
std::queue<GRWorkListUnit> Queue;
|
||||||
|
llvm::SmallVector<GRWorkListUnit,20> Stack;
|
||||||
|
public:
|
||||||
|
virtual bool hasWork() const {
|
||||||
|
return !Queue.empty() || !Stack.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Enqueue(const GRWorkListUnit& U) {
|
||||||
|
if (isa<BlockEntrance>(U.getNode()->getLocation()))
|
||||||
|
Queue.push(U);
|
||||||
|
else
|
||||||
|
Stack.push_back(U);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual GRWorkListUnit Dequeue() {
|
||||||
|
// Process all basic blocks to completion.
|
||||||
|
if (!Stack.empty()) {
|
||||||
|
const GRWorkListUnit& U = Stack.back();
|
||||||
|
Stack.pop_back(); // This technically "invalidates" U, but we are fine.
|
||||||
|
return U;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!Queue.empty());
|
||||||
|
// Don't use const reference. The subsequent pop_back() might make it
|
||||||
|
// unsafe.
|
||||||
|
GRWorkListUnit U = Queue.front();
|
||||||
|
Queue.pop();
|
||||||
|
return U;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
GRWorkList* GRWorkList::MakeBFSBlockDFSContents() {
|
||||||
|
return new BFSBlockDFSContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Core analysis engine.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
|
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
|
||||||
bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) {
|
bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) {
|
||||||
|
|
||||||
|
@ -90,8 +137,7 @@ bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) {
|
||||||
|
|
||||||
// Dispatch on the location type.
|
// Dispatch on the location type.
|
||||||
switch (Node->getLocation().getKind()) {
|
switch (Node->getLocation().getKind()) {
|
||||||
default:
|
case ProgramPoint::BlockEdgeKind:
|
||||||
assert (isa<BlockEdge>(Node->getLocation()));
|
|
||||||
HandleBlockEdge(cast<BlockEdge>(Node->getLocation()), Node);
|
HandleBlockEdge(cast<BlockEdge>(Node->getLocation()), Node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -102,9 +148,9 @@ bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) {
|
||||||
case ProgramPoint::BlockExitKind:
|
case ProgramPoint::BlockExitKind:
|
||||||
assert (false && "BlockExit location never occur in forward analysis.");
|
assert (false && "BlockExit location never occur in forward analysis.");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProgramPoint::PostLoadKind:
|
default:
|
||||||
case ProgramPoint::PostStmtKind:
|
assert(isa<PostStmt>(Node->getLocation()));
|
||||||
HandlePostStmt(cast<PostStmt>(Node->getLocation()), WU.getBlock(),
|
HandlePostStmt(cast<PostStmt>(Node->getLocation()), WU.getBlock(),
|
||||||
WU.getIndex(), Node);
|
WU.getIndex(), Node);
|
||||||
break;
|
break;
|
||||||
|
@ -332,6 +378,18 @@ static inline ProgramPoint GetPostLoc(Stmt* S, ProgramPoint::Kind K) {
|
||||||
|
|
||||||
case ProgramPoint::PostLoadKind:
|
case ProgramPoint::PostLoadKind:
|
||||||
return PostLoad(S);
|
return PostLoad(S);
|
||||||
|
|
||||||
|
case ProgramPoint::PostUndefLocationCheckFailedKind:
|
||||||
|
return PostUndefLocationCheckFailed(S);
|
||||||
|
|
||||||
|
case ProgramPoint::PostLocationChecksSucceedKind:
|
||||||
|
return PostLocationChecksSucceed(S);
|
||||||
|
|
||||||
|
case ProgramPoint::PostOutOfBoundsCheckFailedKind:
|
||||||
|
return PostOutOfBoundsCheckFailed(S);
|
||||||
|
|
||||||
|
case ProgramPoint::PostNullCheckFailedKind:
|
||||||
|
return PostNullCheckFailed(S);
|
||||||
|
|
||||||
case ProgramPoint::PostStoreKind:
|
case ProgramPoint::PostStoreKind:
|
||||||
return PostStore(S);
|
return PostStore(S);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче