[cfe-commits] r170829 - in /cfe/trunk: include/clang/Analysis/CallGraph.h lib/Analysis/CallGraph.cpp lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp test/Analysis/debug-CallGraph.c
Anna Zaks
ganna at apple.com
Thu Dec 20 17:48:18 PST 2012
Thanks.
Anna.
On Dec 20, 2012, at 5:30 PM, Rafael Espindola wrote:
> Author: rafael
> Date: Thu Dec 20 19:30:23 2012
> New Revision: 170829
>
> URL: http://llvm.org/viewvc/llvm-project?rev=170829&view=rev
> Log:
> Revert r170826. The output of
>
> ./bin/clang -cc1 -internal-isystem /home/espindola/llvm/build/lib/clang/3.3/include/ -analyze -analyzer-checker=debug.DumpCallGraph /home/espindola/llvm/clang/test/Analysis/debug-CallGraph.c -fblocks
>
> changes in each run.
>
> Modified:
> cfe/trunk/include/clang/Analysis/CallGraph.h
> cfe/trunk/lib/Analysis/CallGraph.cpp
> cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
> cfe/trunk/test/Analysis/debug-CallGraph.c
>
> Modified: cfe/trunk/include/clang/Analysis/CallGraph.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CallGraph.h?rev=170829&r1=170828&r2=170829&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Analysis/CallGraph.h (original)
> +++ cfe/trunk/include/clang/Analysis/CallGraph.h Thu Dec 20 19:30:23 2012
> @@ -39,9 +39,15 @@
> /// FunctionMap owns all CallGraphNodes.
> FunctionMapTy FunctionMap;
>
> - /// This is a virtual root node that has edges to all the functions.
> + /// This is a virtual root node that has edges to all the global functions -
> + /// 'main' or functions accessible from other translation units.
> CallGraphNode *Root;
>
> + /// The list of nodes that have no parent. These are unreachable from Root.
> + /// Declarations can get to this list due to impressions in the graph, for
> + /// example, we do not track functions whose addresses were taken.
> + llvm::SetVector<CallGraphNode *> ParentlessNodes;
> +
> public:
> CallGraph();
> ~CallGraph();
> @@ -85,6 +91,12 @@
> /// failing to add a call edge due to the analysis imprecision.
> typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator;
> typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator;
> + nodes_iterator parentless_begin() { return ParentlessNodes.begin(); }
> + nodes_iterator parentless_end() { return ParentlessNodes.end(); }
> + const_nodes_iterator
> + parentless_begin() const { return ParentlessNodes.begin(); }
> + const_nodes_iterator
> + parentless_end() const { return ParentlessNodes.end(); }
>
> void print(raw_ostream &os) const;
> void dump() const;
> @@ -158,6 +170,7 @@
>
> void addCallee(CallGraphNode *N, CallGraph *CG) {
> CalledFunctions.push_back(N);
> + CG->ParentlessNodes.remove(N);
> }
>
> Decl *getDecl() const { return FD; }
>
> Modified: cfe/trunk/lib/Analysis/CallGraph.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CallGraph.cpp?rev=170829&r1=170828&r2=170829&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Analysis/CallGraph.cpp (original)
> +++ cfe/trunk/lib/Analysis/CallGraph.cpp Thu Dec 20 19:30:23 2012
> @@ -141,8 +141,14 @@
> void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
> assert(D);
>
> + // Do nothing if the node already exists.
> + if (FunctionMap.find(D) != FunctionMap.end())
> + return;
> +
> // Allocate a new node, mark it as root, and process it's calls.
> CallGraphNode *Node = getOrInsertNode(D);
> + if (IsGlobal)
> + Root->addCallee(Node, this);
>
> // Process all the calls by this function as well.
> CGBuilder builder(this, Node);
> @@ -162,9 +168,9 @@
> return Node;
>
> Node = new CallGraphNode(F);
> - // Make Root node a parent of all functions to make sure all are reachable.
> + // If not root, add to the parentless list.
> if (F != 0)
> - Root->addCallee(Node, this);
> + ParentlessNodes.insert(Node);
> return Node;
> }
>
>
> Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp?rev=170829&r1=170828&r2=170829&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp Thu Dec 20 19:30:23 2012
> @@ -39,7 +39,6 @@
> #include "llvm/ADT/OwningPtr.h"
> #include "llvm/ADT/SmallPtrSet.h"
> #include "llvm/ADT/Statistic.h"
> -#include "llvm/ADT/PostOrderIterator.h"
> #include "llvm/Support/Path.h"
> #include "llvm/Support/Program.h"
> #include "llvm/Support/Timer.h"
> @@ -418,34 +417,61 @@
> }
>
> void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
> - // Build the Call Graph by adding all the top level declarations to the graph.
> + // Otherwise, use the Callgraph to derive the order.
> + // Build the Call Graph.
> + CallGraph CG;
> +
> + // Add all the top level declarations to the graph.
> // Note: CallGraph can trigger deserialization of more items from a pch
> // (though HandleInterestingDecl); triggering additions to LocalTUDecls.
> // We rely on random access to add the initially processed Decls to CG.
> - CallGraph CG;
> for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
> CG.addToCallGraph(LocalTUDecls[i]);
> }
>
> - // Walk over all of the call graph nodes in topological order, so that we
> - // analyze parents before the children. Skip the functions inlined into
> - // the previously processed functions. Use external Visited set to identify
> - // inlined functions. The topological order allows the "do not reanalyze
> - // previously inlined function" performance heuristic to be triggered more
> - // often.
> + // Find the top level nodes - children of root + the unreachable (parentless)
> + // nodes.
> + llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions;
> + for (CallGraph::nodes_iterator TI = CG.parentless_begin(),
> + TE = CG.parentless_end(); TI != TE; ++TI) {
> + TopLevelFunctions.push_back(*TI);
> + NumFunctionTopLevel++;
> + }
> + CallGraphNode *Entry = CG.getRoot();
> + for (CallGraphNode::iterator I = Entry->begin(),
> + E = Entry->end(); I != E; ++I) {
> + TopLevelFunctions.push_back(*I);
> + NumFunctionTopLevel++;
> + }
> +
> + // Make sure the nodes are sorted in order reverse of their definition in the
> + // translation unit. This step is very important for performance. It ensures
> + // that we analyze the root functions before the externally available
> + // subroutines.
> + std::deque<CallGraphNode*> BFSQueue;
> + for (llvm::SmallVector<CallGraphNode*, 24>::reverse_iterator
> + TI = TopLevelFunctions.rbegin(), TE = TopLevelFunctions.rend();
> + TI != TE; ++TI)
> + BFSQueue.push_back(*TI);
> +
> + // BFS over all of the functions, while skipping the ones inlined into
> + // the previously processed functions. Use external Visited set, which is
> + // also modified when we inline a function.
> SetOfConstDecls Visited;
> SetOfConstDecls VisitedAsTopLevel;
> - llvm::ReversePostOrderTraversal<clang::CallGraph*> RPOT(&CG);
> - for (llvm::ReversePostOrderTraversal<clang::CallGraph*>::rpo_iterator
> - I = RPOT.begin(); I != RPOT.end(); ++I) {
> - NumFunctionTopLevel++;
> + while(!BFSQueue.empty()) {
> + CallGraphNode *N = BFSQueue.front();
> + BFSQueue.pop_front();
> +
> + // Push the children into the queue.
> + for (CallGraphNode::const_iterator CI = N->begin(),
> + CE = N->end(); CI != CE; ++CI) {
> + if (!shouldSkipFunction((*CI)->getDecl(), Visited, VisitedAsTopLevel))
> + BFSQueue.push_back(*CI);
> + }
>
> - CallGraphNode *N = *I;
> Decl *D = N->getDecl();
> -
> - // Skip the abstract root node.
> - if (!D)
> - continue;
> + assert(D);
>
> // Skip the functions which have been processed already or previously
> // inlined.
>
> Modified: cfe/trunk/test/Analysis/debug-CallGraph.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/debug-CallGraph.c?rev=170829&r1=170828&r2=170829&view=diff
> ==============================================================================
> --- cfe/trunk/test/Analysis/debug-CallGraph.c (original)
> +++ cfe/trunk/test/Analysis/debug-CallGraph.c Thu Dec 20 19:30:23 2012
> @@ -1,9 +1,9 @@
> -// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCallGraph %s -fblocks 2>&1 | FileCheck %s
> +// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCallGraph %s 2>&1 | FileCheck %s
>
> static void mmm(int y) {
> if (y != 0)
> y++;
> - y = y/y;
> + y = y/0;
> }
>
> static int foo(int x, int y) {
> @@ -17,17 +17,5 @@
> foo(1,2);
> }
>
> -void bbb(int y) {
> - int x = (y > 2);
> - ^ {
> - foo(x, y);
> - }();
> -}
> -
> // CHECK:--- Call graph Dump ---
> -// CHECK: Function: < root > calls: mmm foo aaa < > bbb
> -// CHECK: Function: bbb calls: < >
> -// CHECK: Function: mmm calls:
> -// CHECK: Function: aaa calls: foo
> -// CHECK: Function: foo calls: mmm
> -// CHECK: Function: < > calls: foo
> +// CHECK: Function: < root > calls: aaa
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list