diff --git a/clang/AST/CFG.cpp b/clang/AST/CFG.cpp index 3be5f7cd4bab..befd84020d05 100644 --- a/clang/AST/CFG.cpp +++ b/clang/AST/CFG.cpp @@ -21,10 +21,12 @@ #include "llvm/Support/GraphWriter.h" #include "llvm/Support/Streams.h" #include "llvm/Support/Compiler.h" +#include #include #include #include + using namespace clang; namespace { @@ -1030,8 +1032,21 @@ unsigned CFG::getNumBlkExprs() { } } +typedef std::set > BlkEdgeSetTy; + +const std::pair* +CFG::getBlockEdgeImpl(const CFGBlock* B1, const CFGBlock* B2) { + + BlkEdgeSetTy*& p = reinterpret_cast(BlkEdgeSet); + if (!p) p = new BlkEdgeSetTy(); + + return &*(p->insert(std::make_pair(const_cast(B1), + const_cast(B2))).first); +} + CFG::~CFG() { delete reinterpret_cast(BlkExprMap); + delete reinterpret_cast(BlkEdgeSet); } //===----------------------------------------------------------------------===// diff --git a/clang/Analysis/LiveVariables.cpp b/clang/Analysis/LiveVariables.cpp index 92186537c7b1..5634c3c966a5 100644 --- a/clang/Analysis/LiveVariables.cpp +++ b/clang/Analysis/LiveVariables.cpp @@ -172,7 +172,7 @@ typedef DataflowSolver Solver; // External interface to run Liveness analysis. //===----------------------------------------------------------------------===// -void LiveVariables::runOnCFG(const CFG& cfg) { +void LiveVariables::runOnCFG(CFG& cfg) { Solver S(*this); S.runOnCFG(cfg); } diff --git a/clang/include/clang/AST/CFG.h b/clang/include/clang/AST/CFG.h index 6cf66029af28..28e73f3ba674 100644 --- a/clang/include/clang/AST/CFG.h +++ b/clang/include/clang/AST/CFG.h @@ -22,11 +22,11 @@ #include namespace clang { - class Stmt; class Expr; class CFG; class PrinterHelper; + class BlockEdge; /// CFGBlock - Represents a single basic block in a source-level CFG. /// It consists of: @@ -273,7 +273,7 @@ public: //===--------------------------------------------------------------------===// CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0), - BlkExprMap(NULL) {}; + BlkExprMap(NULL), BlkEdgeSet(NULL) {}; ~CFG(); @@ -287,6 +287,22 @@ private: // opaque pointer to prevent inclusion of DenseMap.h. Map from expressions // to integers to record block-level expressions. void* BlkExprMap; + + // opaque pointer to prevent inclusion of . This records a set of + // CFGBlock edges for using with ProgramPoint. These edges represent + // the edges that cannot be succinctly represented, and in practice this + // set should be small. + void* BlkEdgeSet; + + friend class BlockEdge; + + /// getBlockEdgeImpl - Utility method used by the class BlockEdge. The CFG + /// stores a set of interned std::pair that can + /// be used by BlockEdge to refer to edges that cannot be represented + /// by a single pointer. + const std::pair* getBlockEdgeImpl(const CFGBlock* B1, + const CFGBlock* B2); + }; } // end namespace clang diff --git a/clang/include/clang/Analysis/Analyses/LiveVariables.h b/clang/include/clang/Analysis/Analyses/LiveVariables.h index 08de82d0a84d..33516e78aad8 100644 --- a/clang/include/clang/Analysis/Analyses/LiveVariables.h +++ b/clang/include/clang/Analysis/Analyses/LiveVariables.h @@ -92,7 +92,7 @@ public: /// a given CFG. This is intended to be called by the dataflow solver. void InitializeValues(const CFG& cfg); - void runOnCFG(const CFG& cfg); + void runOnCFG(CFG& cfg); void runOnAllBlocks(const CFG& cfg, ObserverTy& Obs); }; diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h index 5852023db2b1..215fa3bad3bc 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h @@ -69,12 +69,12 @@ template <> struct ItrTraits { static StmtItr StmtBegin(const CFGBlock* B) { return B->begin(); } static StmtItr StmtEnd(const CFGBlock* B) { return B->end(); } - static BlkBlkEdge PrevEdge(const CFGBlock* B, const CFGBlock* PrevBlk) { - return BlkBlkEdge(PrevBlk,B); + static BlockEdge PrevEdge(CFG& cfg, const CFGBlock* B, const CFGBlock* Prev) { + return BlockEdge(cfg,Prev,B); } - static BlkBlkEdge NextEdge(const CFGBlock* B, const CFGBlock* NextBlk) { - return BlkBlkEdge(B,NextBlk); + static BlockEdge NextEdge(CFG& cfg, const CFGBlock* B, const CFGBlock* Next) { + return BlockEdge(cfg,B,Next); } }; @@ -92,12 +92,12 @@ template <> struct ItrTraits { static StmtItr StmtBegin(const CFGBlock* B) { return B->rbegin(); } static StmtItr StmtEnd(const CFGBlock* B) { return B->rend(); } - static BlkBlkEdge PrevEdge(const CFGBlock* B, const CFGBlock* PrevBlk) { - return BlkBlkEdge(B,PrevBlk); + static BlockEdge PrevEdge(CFG& cfg, const CFGBlock* B, const CFGBlock* Prev) { + return BlockEdge(cfg,B,Prev); } - static BlkBlkEdge NextEdge(const CFGBlock* B, const CFGBlock* NextBlk) { - return BlkBlkEdge(NextBlk,B); + static BlockEdge NextEdge(CFG& cfg, const CFGBlock* B, const CFGBlock* Next) { + return BlockEdge(cfg,Next,B); } }; } // end namespace dataflow @@ -140,7 +140,7 @@ public: ~DataflowSolver() {} /// runOnCFG - Computes dataflow values for all blocks in a CFG. - void runOnCFG(const CFG& cfg) { + void runOnCFG(CFG& cfg) { // Set initial dataflow values and boundary conditions. D.InitializeValues(cfg); // Solve the dataflow equations. This will populate D.EdgeDataMap @@ -180,14 +180,14 @@ private: /// SolveDataflowEquations - Perform the actual worklist algorithm /// to compute dataflow values. - void SolveDataflowEquations(const CFG& cfg) { + void SolveDataflowEquations(CFG& cfg) { EnqueueFirstBlock(cfg,AnalysisDirTag()); while (!WorkList.isEmpty()) { const CFGBlock* B = WorkList.dequeue(); - ProcessMerge(B); + ProcessMerge(cfg,B); ProcessBlock(B); - UpdateEdges(B,TF.getVal()); + UpdateEdges(cfg,B,TF.getVal()); } } @@ -199,7 +199,7 @@ private: WorkList.enqueue(&cfg.getExit()); } - void ProcessMerge(const CFGBlock* B) { + void ProcessMerge(CFG& cfg, const CFGBlock* B) { // Merge dataflow values from all predecessors of this block. ValTy& V = TF.getVal(); V.resetValues(D.getAnalysisData()); @@ -210,7 +210,8 @@ private: for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){ - typename EdgeDataMapTy::iterator EI = M.find(ItrTraits::PrevEdge(B,*I)); + typename EdgeDataMapTy::iterator EI = + M.find(ItrTraits::PrevEdge(cfg,B,*I)); if (EI != M.end()) { if (firstMerge) { @@ -236,13 +237,13 @@ private: /// block, update the dataflow value associated with the block's /// outgoing/incoming edges (depending on whether we do a // forward/backward analysis respectively) - void UpdateEdges(const CFGBlock* B, ValTy& V) { + void UpdateEdges(CFG& cfg, const CFGBlock* B, ValTy& V) { for (NextBItr I=ItrTraits::NextBegin(B), E=ItrTraits::NextEnd(B); I!=E; ++I) - UpdateEdgeValue(ItrTraits::NextEdge(B,*I),V,*I); + UpdateEdgeValue(ItrTraits::NextEdge(cfg,B,*I),V,*I); } /// UpdateEdgeValue - Update the value associated with a given edge. - void UpdateEdgeValue(BlkBlkEdge E, ValTy& V, const CFGBlock* TargetBlock) { + void UpdateEdgeValue(BlockEdge E, ValTy& V, const CFGBlock* TargetBlock) { EdgeDataMapTy& M = D.getEdgeDataMap(); typename EdgeDataMapTy::iterator I = M.find(E); @@ -261,8 +262,7 @@ private: DFValuesTy& D; DataflowWorkListTy WorkList; TransferFuncsTy TF; -}; - +}; } // end namespace clang #endif diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h b/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h index 8d7d1629c834..acf684705c00 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h @@ -48,7 +48,7 @@ public: typedef typename ValueTypes::ValTy ValTy; typedef typename ValueTypes::AnalysisDataTy AnalysisDataTy; typedef _AnalysisDirTag AnalysisDirTag; - typedef llvm::DenseMap EdgeDataMapTy; + typedef llvm::DenseMap EdgeDataMapTy; typedef llvm::DenseMap BlockDataMapTy; //===--------------------------------------------------------------------===// @@ -80,13 +80,13 @@ public: /// getEdgeData - Retrieves the dataflow values associated with a /// CFG edge. - ValTy& getEdgeData(const BlkBlkEdge& E) { + ValTy& getEdgeData(const BlockEdge& E) { typename EdgeDataMapTy::iterator I = EdgeDataMap.find(E); assert (I != EdgeDataMap.end() && "No data associated with Edge."); return I->second; } - const ValTy& getEdgeData(const BlkBlkEdge& E) const { + const ValTy& getEdgeData(const BlockEdge& E) const { return reinterpret_cast(this)->getEdgeData(E); } diff --git a/clang/include/clang/Analysis/ProgramEdge.h b/clang/include/clang/Analysis/ProgramEdge.h index 1c10196c2807..8438e5602fa7 100644 --- a/clang/include/clang/Analysis/ProgramEdge.h +++ b/clang/include/clang/Analysis/ProgramEdge.h @@ -1,4 +1,4 @@ -//==- ProgramEdge.h - Program Points for Path-Sensitive Analysis --*- C++ -*-=// +//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-// // // The LLVM Compiler Infrastructure // @@ -7,13 +7,13 @@ // //===----------------------------------------------------------------------===// // -// This file defines the interface ProgramEdge, which identifies a distinct -// location in a function based on edges within its CFG. +// This file defines the interface ProgramPoint, which identifies a +// distinct location in a function. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_PATHSENS_PROGRAM_POINT -#define LLVM_CLANG_ANALYSIS_PATHSENS_PROGRAM_POINT +#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT +#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT #include "llvm/Support/DataTypes.h" #include "llvm/ADT/DenseMap.h" @@ -21,178 +21,137 @@ namespace clang { + class CFG; class CFGBlock; class Stmt; -class ProgramEdge { - uintptr_t Src, Dst; +class ProgramPoint { public: - enum EdgeKind { BExprBlk=0, BlkBExpr=1, BExprBExpr=2, BlkBlk=3, - BExprSExpr=4, SExprSExpr=5, SExprBExpr=6, Infeasible=7 }; - - static bool classof(const ProgramEdge*) { return true; } - - unsigned getKind() const { return (((unsigned) Src & 0x3) << 2) | - ((unsigned) Dst & 0x3); } - - void* RawSrc() const { return reinterpret_cast(Src & ~0x3); } - void* RawDst() const { return reinterpret_cast(Dst & ~0x3); } - - bool operator==(const ProgramEdge & RHS) const { - // comparing pointer values canoncalizes "NULL" edges where both pointers - // are NULL without having to worry about edgekind. We can otherwise - // ignore edgekind because no CFGBlock* or Stmt* will have the same value. - return RawSrc() == RHS.RawSrc() && RawDst() == RHS.RawDst(); - } - - bool operator!=(const ProgramEdge& RHS) const { - return RawSrc() != RHS.RawSrc() || RawDst() != RHS.RawDst(); - } - - unsigned getHashValue() const { - uintptr_t v1 = reinterpret_cast(RawSrc()); - uintptr_t v2 = reinterpret_cast(RawDst()); - return static_cast( (v1 >> 4) ^ (v1 >> 9) ^ - (v2 >> 5) ^ (v2 >> 10) ); - } - + enum Kind { BlockEntranceKind=0, PostStmtKind=1, BlockExitKind=2, + BlockEdgeSrcKind=3, BlockEdgeDstKind=4, BlockEdgeAuxKind=5 }; protected: + uintptr_t Data; + + ProgramPoint(const void* Ptr, Kind k) { + assert ((reinterpret_cast(const_cast(Ptr)) & 0x7) == 0 + && "Address must have at least an 8-byte alignment."); + + Data = reinterpret_cast(const_cast(Ptr)) & k; + } - ProgramEdge(const void* src, const void* dst, EdgeKind k) { - assert (k >= BExprBlk && k <= BlkBlk); - Src = reinterpret_cast(const_cast(src)) | (k >> 2); - Dst = reinterpret_cast(const_cast(dst)) | (k & 0x3); + ProgramPoint() : Data(0) {} + +public: + unsigned getKind() const { return Data & 0x5; } + void* getRawPtr() const { return reinterpret_cast(Data & ~0x7); } + void* getRawData() const { return reinterpret_cast(Data); } + + static bool classof(const ProgramPoint*) { return true; } + bool operator==(const ProgramPoint & RHS) const { return Data == RHS.Data; } + bool operator!=(const ProgramPoint& RHS) const { return Data != RHS.Data; } +}; + +class BlockEntrance : public ProgramPoint { +public: + BlockEntrance(const CFGBlock* B) : ProgramPoint(B, BlockEntranceKind) {} + + CFGBlock* getBlock() const { + return reinterpret_cast(getRawPtr()); + } + + Stmt* getFirstStmt() const { + CFGBlock* B = getBlock(); + return B->empty() ? NULL : B->front(); + } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == BlockEntranceKind; } }; -class BExprBlkEdge : public ProgramEdge { +class BlockExit : public ProgramPoint { public: - BExprBlkEdge(const Stmt* S,const CFGBlock* B) - : ProgramEdge(S,B,BExprBlk) {} + BlockExit(const CFGBlock* B) : ProgramPoint(B, BlockExitKind) {} - Stmt* Src() const { return reinterpret_cast(RawSrc()); } - CFGBlock* Dst() const { return reinterpret_cast(RawDst()); } + CFGBlock* getBlock() const { + return reinterpret_cast(getRawPtr()); + } + + Stmt* getLastStmt() const { + CFGBlock* B = getBlock(); + return B->empty() ? NULL : B->back(); + } - static bool classof(const ProgramEdge* E) { - return E->getKind() == BExprBlk; + Stmt* getTerminator() const { + return getBlock()->getTerminator(); + } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == BlockExitKind; } }; -class BlkBExprEdge : public ProgramEdge { -public: - BlkBExprEdge(const CFGBlock* B, const Stmt* S) - : ProgramEdge(B,S,BlkBExpr) {} - - CFGBlock* Src() const { return reinterpret_cast(RawSrc()); } - Stmt* Dst() const { return reinterpret_cast(RawDst()); } - static bool classof(const ProgramEdge* E) { - return E->getKind() == BlkBExpr; - } -}; - -class BExprBExprEdge : public ProgramEdge { +class PostStmt : public ProgramPoint { public: - BExprBExprEdge(const Stmt* S1, const Stmt* S2) - : ProgramEdge(S1,S2,BExprBExpr) {} + PostStmt(const Stmt* S) : ProgramPoint(S, PostStmtKind) {} - Stmt* Src() const { return reinterpret_cast(RawSrc()); } - Stmt* Dst() const { return reinterpret_cast(RawDst()); } - - static bool classof(const ProgramEdge* E) { - return E->getKind() == BExprBExpr; - } -}; - -class BExprSExprEdge : public ProgramEdge { -public: - BExprSExprEdge(const Stmt* S1, const Expr* S2) - : ProgramEdge(S1,S2,BExprSExpr) {} - - Stmt* Src() const { return reinterpret_cast(RawSrc()); } - Expr* Dst() const { return reinterpret_cast(RawDst()); } - - static bool classof(const ProgramEdge* E) { - return E->getKind() == BExprSExpr; - } -}; - -class SExprSExprEdge : public ProgramEdge { -public: - SExprSExprEdge(const Expr* S1, const Expr* S2) - : ProgramEdge(S1,S2,SExprSExpr) {} - - Expr* Src() const { return reinterpret_cast(RawSrc()); } - Expr* Dst() const { return reinterpret_cast(RawDst()); } - - static bool classof(const ProgramEdge* E) { - return E->getKind() == SExprSExpr; - } -}; + Stmt* getStmt() const { return (Stmt*) getRawPtr(); } -class SExprBExprEdge : public ProgramEdge { -public: - SExprBExprEdge(const Expr* S1, const Stmt* S2) - : ProgramEdge(S1,S2,SExprBExpr) {} - - Expr* Src() const { return reinterpret_cast(RawSrc()); } - Stmt* Dst() const { return reinterpret_cast(RawDst()); } - - static bool classof(const ProgramEdge* E) { - return E->getKind() == SExprBExpr; + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostStmtKind; } }; + +class BlockEdge : public ProgramPoint { + typedef std::pair BPair; +public: + BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2); -class BlkBlkEdge : public ProgramEdge { -public: - BlkBlkEdge(const CFGBlock* B1, const CFGBlock* B2) - : ProgramEdge(B1,B2,BlkBlk) {} + CFGBlock* getSrc() const; + CFGBlock* getDst() const; - CFGBlock* Src() const { return reinterpret_cast(RawSrc()); } - CFGBlock* Dst() const { return reinterpret_cast(RawDst()); } - - static bool classof(const ProgramEdge* E) { - return E->getKind() == BlkBlk; + static bool classof(const ProgramPoint* Location) { + unsigned k = Location->getKind(); + return k >= BlockEdgeSrcKind && k <= BlockEdgeAuxKind; } }; -class InfeasibleEdge : public ProgramEdge { -public: - InfeasibleEdge(Stmt* S) : ProgramEdge(S,NULL,Infeasible) {} - - Stmt* getStmt() const { return reinterpret_cast(RawSrc()); } - - static bool classof(const ProgramEdge* E) { - return E->getKind() == Infeasible; - } -}; + } // end namespace clang namespace llvm { // Traits specialization for DenseMap -template <> struct DenseMapInfo { +template <> struct DenseMapInfo { - static inline clang::ProgramEdge getEmptyKey() { - return clang::BlkBlkEdge(0, 0); + static inline clang::ProgramPoint getEmptyKey() { + uintptr_t x = + reinterpret_cast(DenseMapInfo::getEmptyKey()) & ~0x7; + + return clang::BlockEntrance(reinterpret_cast(x)); } - static inline clang::ProgramEdge getTombstoneKey() { - return clang::BlkBlkEdge(reinterpret_cast(-1), - reinterpret_cast(-1)); + static inline clang::ProgramPoint getTombstoneKey() { + uintptr_t x = + reinterpret_cast(DenseMapInfo::getTombstoneKey()) & ~0x7; + + return clang::BlockEntrance(reinterpret_cast(x)); } - static unsigned getHashValue(const clang::ProgramEdge& E) { - return E.getHashValue(); + static unsigned getHashValue(const clang::ProgramPoint& Loc) { + return DenseMapInfo::getHashValue(Loc.getRawData()); } - static bool isEqual(const clang::ProgramEdge& LHS, - const clang::ProgramEdge& RHS) { - return LHS == RHS; + static bool isEqual(const clang::ProgramPoint& L, + const clang::ProgramPoint& R) { + return L == R; } - static bool isPod() { return true; } + static bool isPod() { + return true; + } }; } // end namespace llvm