CoreEngine.h revision f24af5bc2e01ca8e7396ed997378a77fddfa521e
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//==- GREngine.h - Path-Sensitive Dataflow Engine ------------------*- C++ -*-// 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// The LLVM Compiler Infrastructure 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// License. See LICENSE.TXT for details. 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===----------------------------------------------------------------------===// 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This file defines a generic engine for intraprocedural, path-sensitive, 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// dataflow analysis via graph reachability engine. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===----------------------------------------------------------------------===// 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef LLVM_CLANG_ANALYSIS_GRENGINE 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define LLVM_CLANG_ANALYSIS_GRENGINE 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "clang/Analysis/PathSensitive/ExplodedGraph.h" 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "clang/Analysis/PathSensitive/GRWorkList.h" 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "llvm/ADT/OwningPtr.h" 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace clang { 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class CFG; 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class GRNodeBuilderImpl; 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class GRWorkList; 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class GREngineImpl { 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)protected: 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) friend class GRNodeBuilderImpl; 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu typedef llvm::DenseMap<Stmt*,Stmt*> ParentMapTy; 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3476c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) /// cfg - The control-flow graph of the function being analyzed. 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) CFG& cfg; 3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /// G - The simulation graph. Each node is a (location,state) pair. 385267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) llvm::OwningPtr<ExplodedGraphImpl> G; 395267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 40f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// ParentMap - A lazily populated map from a Stmt* to its parent Stmt*. 41f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu void* ParentMap; 42591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /// CurrentBlkExpr - The current Block-level expression being processed. 4451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) /// This is used when lazily populating ParentMap. 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Stmt* CurrentBlkExpr; 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /// WList - A set of queued nodes that need to be processed by the 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /// worklist algorithm. It is up to the implementation of WList to decide 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /// the order that nodes are processed. 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GRWorkList* WList; 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void GenerateNode(const ProgramPoint& Loc, void* State, 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ExplodedNodeImpl* Pred = NULL); 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /// getInitialState - Gets the void* representing the initial 'state' 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /// of the analysis. This is simply a wrapper (implemented 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /// in GREngine) that performs type erasure on the initial 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /// state returned by the checker object. 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual void* getInitialState() = 0; 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void HandleBlockEdge(const BlockEdge& E, ExplodedNodeImpl* Pred); 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void HandleBlockEntrance(const BlockEntrance& E, ExplodedNodeImpl* Pred); 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void HandleBlockExit(const BlockExit& E, ExplodedNodeImpl* Pred); 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void HandlePostStmt(const PostStmt& S, CFGBlock* B, 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned StmtIdx, ExplodedNodeImpl *Pred); 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual void* ProcessEOP(CFGBlock* Blk, void* State) = 0; 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual void ProcessStmt(Stmt* S, GRNodeBuilderImpl& Builder) = 0; 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual void ProcessTerminator(Stmt* Terminator, CFGBlock* B, 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ExplodedNodeImpl* Pred) = 0; 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private: 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GREngineImpl(const GREngineImpl&); // Do not implement. 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GREngineImpl& operator=(const GREngineImpl&); 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)protected: 79d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) GREngineImpl(CFG& c, ExplodedGraphImpl* g, GRWorkList* wl) 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : cfg(c), G(g), WList(wl) {} 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /// ExecuteWorkList - Run the worklist algorithm for a maximum number of 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /// steps. Returns true if there is still simulation state on the worklist. 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool ExecuteWorkList(unsigned Steps = 1000000); 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 87323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) virtual ~GREngineImpl() {} 881e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}; 89323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 90323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)class GRNodeBuilderImpl { 911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) GREngineImpl& Eng; 921e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) CFGBlock& B; 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const unsigned Idx; 941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) ExplodedNodeImpl* LastNode; 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool HasGeneratedNode; 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool Populated; 9710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 98591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch typedef llvm::SmallPtrSet<ExplodedNodeImpl*,5> DeferredTy; 9910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch DeferredTy Deferred; 100591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 101591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch void GenerateAutoTransition(ExplodedNodeImpl* N); 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GRNodeBuilderImpl(CFGBlock* b, unsigned idx, 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ExplodedNodeImpl* N, GREngineImpl* e); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 107323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) ~GRNodeBuilderImpl(); 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const ExplodedGraphImpl& getGraph() const { return *Eng.G; } 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) inline ExplodedNodeImpl* getLastNode() { 112323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) return LastNode ? (LastNode->isInfeasible() ? NULL : LastNode) : NULL; 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ExplodedNodeImpl* generateNodeImpl(Stmt* S, void* State, 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ExplodedNodeImpl* Pred); 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 118323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) inline ExplodedNodeImpl* generateNodeImpl(Stmt* S, void* State) { 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ExplodedNodeImpl* N = getLastNode(); 120591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch assert (N && "Predecessor of new node is infeasible."); 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return generateNodeImpl(S, State, N); 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 124 Stmt* getStmt() const { return B[Idx]; } 125 126 CFGBlock* getBlock() const { return &B; } 127}; 128 129template<typename CHECKER> 130class GRNodeBuilder { 131 typedef CHECKER CheckerTy; 132 typedef typename CheckerTy::StateTy StateTy; 133 typedef ExplodedGraph<CheckerTy> GraphTy; 134 typedef typename GraphTy::NodeTy NodeTy; 135 136 GRNodeBuilderImpl& NB; 137 138public: 139 const GraphTy& getGraph() const { 140 return static_cast<const GraphTy&>(NB.getGraph()); 141 } 142 143 NodeTy* getLastNode() const { 144 return static_cast<NodeTy*>(NB.getLastNode()); 145 } 146 147 NodeTy* generateNode(Stmt* S, StateTy State, NodeTy* Pred) { 148 void *state = GRTrait<StateTy>::toPtr(State); 149 return static_cast<NodeTy*>(NB.generateNodeImpl(S, state, Pred)); 150 } 151 152 NodeTy* generateNode(Stmt* S, StateTy State) { 153 void *state = GRTrait<StateTy>::toPtr(State); 154 return static_cast<NodeTy*>(NB.generateNodeImpl(S, state)); 155 } 156}; 157 158 159template<typename CHECKER> 160class GREngine : public GREngineImpl { 161public: 162 typedef CHECKER CheckerTy; 163 typedef typename CheckerTy::StateTy StateTy; 164 typedef ExplodedGraph<CheckerTy> GraphTy; 165 typedef typename GraphTy::NodeTy NodeTy; 166 167protected: 168 // A local reference to the checker that avoids an indirect access 169 // via the Graph. 170 CheckerTy* Checker; 171 172 173 virtual void* getInitialState() { 174 return GRTrait<StateTy>::toPtr(getCheckerState()->getInitialState()); 175 } 176 177 virtual void* ProcessEOP(CFGBlock* Blk, void* State) { 178 // FIXME: Perform dispatch to adjust state. 179 return State; 180 } 181 182 virtual void ProcessStmt(Stmt* S, GRNodeBuilderImpl& BuilderImpl) { 183 GRNodeBuilder<CHECKER> Builder(BuilderImpl); 184 Checker->ProcessStmt(S, Builder); 185 } 186 187 virtual void ProcessTerminator(Stmt* Terminator, CFGBlock* B, 188 ExplodedNodeImpl* Pred) { 189 // FIXME: Dispatch. 190 } 191 192 193public: 194 /// Construct a GREngine object to analyze the provided CFG using 195 /// a DFS exploration of the exploded graph. 196 GREngine(CFG& Cfg) 197 : GREngineImpl(cfg, new GraphTy(), GRWorkList::MakeDFS()), 198 Checker(static_cast<GraphTy*>(G.get())->getCheckerState()) {} 199 200 /// Construct a GREngine object to analyze the provided CFG and to 201 /// use the provided worklist object to execute the worklist algorithm. 202 /// The GREngine object assumes ownership of 'wlist'. 203 GREngine(CFG& cfg, GRWorkList* wlist) 204 : GREngineImpl(cfg, new GraphTy(), wlist), 205 Checker(static_cast<GraphTy*>(G.get())->getCheckerState()) {} 206 207 virtual ~GREngine() {} 208 209 /// getGraph - Returns the exploded graph. 210 GraphTy& getGraph() { 211 return *static_cast<GraphTy*>(G.get()); 212 } 213 214 /// getCheckerState - Returns the internal checker state. 215 CheckerTy& getCheckerState() { 216 return *Checker; 217 } 218 219 /// takeGraph - Returns the exploded graph. Ownership of the graph is 220 /// transfered to the caller. 221 GraphTy* takeGraph() { 222 return static_cast<GraphTy*>(G.take()); 223 } 224}; 225 226} // end clang namespace 227 228#endif 229