summaryrefslogtreecommitdiff
path: root/include/llvm/Analysis/CallGraph.h
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-08-31 03:15:49 +0000
committerChris Lattner <sabre@nondot.org>2009-08-31 03:15:49 +0000
commitb374b90e81d0ce6b5d02041ba4f7b15a945b38d8 (patch)
treec25a672fec1906289c9f27809afc94e17f372657 /include/llvm/Analysis/CallGraph.h
parent2adb8306e2256a4d1bef8f21ebb6dba55a108a88 (diff)
downloadllvm-b374b90e81d0ce6b5d02041ba4f7b15a945b38d8.tar.gz
llvm-b374b90e81d0ce6b5d02041ba4f7b15a945b38d8.tar.bz2
llvm-b374b90e81d0ce6b5d02041ba4f7b15a945b38d8.tar.xz
Fix PR4834, a tricky case where the inliner would resolve an
indirect function pointer, inline it, then go to delete the body. The problem is that the callgraph had other references to the function, though the inliner had no way to know it, so we got a dangling pointer and an invalid iterator out of the deal. The fix to this is pretty simple: stop the inliner from deleting the function by knowing that there are references to it. Do this by making CallGraphNodes contain a refcount. This requires moving deletion of available_externally functions to the module-level cleanup sweep where it belongs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80533 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/Analysis/CallGraph.h')
-rw-r--r--include/llvm/Analysis/CallGraph.h40
1 files changed, 28 insertions, 12 deletions
diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h
index 59dc3449b7..bc022e3417 100644
--- a/include/llvm/Analysis/CallGraph.h
+++ b/include/llvm/Analysis/CallGraph.h
@@ -77,7 +77,7 @@ protected:
public:
static char ID; // Class identification, replacement for typeinfo
//===---------------------------------------------------------------------
- // Accessors...
+ // Accessors.
//
typedef FunctionMapTy::iterator iterator;
typedef FunctionMapTy::const_iterator const_iterator;
@@ -136,7 +136,7 @@ public:
CallGraphNode *getOrInsertFunction(const Function *F);
//===---------------------------------------------------------------------
- // Pass infrastructure interface glue code...
+ // Pass infrastructure interface glue code.
//
protected:
CallGraph() {}
@@ -163,19 +163,31 @@ class CallGraphNode {
Function *F;
typedef std::pair<CallSite,CallGraphNode*> CallRecord;
std::vector<CallRecord> CalledFunctions;
+
+ /// NumReferences - This is the number of times that this CallGraphNode occurs
+ /// in the CalledFunctions array of this or other CallGraphNodes.
+ unsigned NumReferences;
- CallGraphNode(const CallGraphNode &); // Do not implement
+ CallGraphNode(const CallGraphNode &); // DO NOT IMPLEMENT
+ void operator=(const CallGraphNode &); // DO NOT IMPLEMENT
+
+ void DropRef() { --NumReferences; }
+ void AddRef() { ++NumReferences; }
public:
typedef std::vector<CallRecord> CalledFunctionsVector;
+
+ // CallGraphNode ctor - Create a node for the specified function.
+ inline CallGraphNode(Function *f) : F(f), NumReferences(0) {}
+
//===---------------------------------------------------------------------
- // Accessor methods...
+ // Accessor methods.
//
typedef std::vector<CallRecord>::iterator iterator;
typedef std::vector<CallRecord>::const_iterator const_iterator;
- // getFunction - Return the function that this call graph node represents...
+ // getFunction - Return the function that this call graph node represents.
Function *getFunction() const { return F; }
inline iterator begin() { return CalledFunctions.begin(); }
@@ -185,9 +197,14 @@ public:
inline bool empty() const { return CalledFunctions.empty(); }
inline unsigned size() const { return (unsigned)CalledFunctions.size(); }
- // Subscripting operator - Return the i'th called function...
+ /// getNumReferences - Return the number of other CallGraphNodes in this
+ /// CallGraph that reference this node in their callee list.
+ unsigned getNumReferences() const { return NumReferences; }
+
+ // Subscripting operator - Return the i'th called function.
//
CallGraphNode *operator[](unsigned i) const {
+ assert(i < CalledFunctions.size() && "Invalid index");
return CalledFunctions[i].second;
}
@@ -204,7 +221,10 @@ public:
/// removeAllCalledFunctions - As the name implies, this removes all edges
/// from this CallGraphNode to any functions it calls.
void removeAllCalledFunctions() {
- CalledFunctions.clear();
+ while (!CalledFunctions.empty()) {
+ CalledFunctions.back().second->DropRef();
+ CalledFunctions.pop_back();
+ }
}
/// stealCalledFunctionsFrom - Move all the callee information from N to this
@@ -220,6 +240,7 @@ public:
/// one.
void addCalledFunction(CallSite CS, CallGraphNode *M) {
CalledFunctions.push_back(std::make_pair(CS, M));
+ M->AddRef();
}
/// removeCallEdgeFor - This method removes the edge in the node for the
@@ -240,11 +261,6 @@ public:
/// New CallSite instead. Note that this method takes linear time, so it
/// should be used sparingly.
void replaceCallSite(CallSite Old, CallSite New, CallGraphNode *NewCallee);
-
- friend class CallGraph;
-
- // CallGraphNode ctor - Create a node for the specified function.
- inline CallGraphNode(Function *f) : F(f) {}
};
//===----------------------------------------------------------------------===//