aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-08-31 00:19:58 +0000
committerChris Lattner <sabre@nondot.org>2009-08-31 00:19:58 +0000
commit5095e3d1d1caef8d573534d369e37277c623064c (patch)
treef6801c8985931a1d161538b2daa7961923a4f15d /include
parent52248ff682e13315e5be08824bdd1d340e02d610 (diff)
downloadexternal_llvm-5095e3d1d1caef8d573534d369e37277c623064c.zip
external_llvm-5095e3d1d1caef8d573534d369e37277c623064c.tar.gz
external_llvm-5095e3d1d1caef8d573534d369e37277c623064c.tar.bz2
Fix some nasty callgraph dangling pointer problems in
argpromotion and structretpromote. Basically, when replacing a function, they used the 'changeFunction' api which changes the entry in the function map (and steals/reuses the callgraph node). This has some interesting effects: first, the problem is that it doesn't update the "callee" edges in any callees of the function in the call graph. Second, this covers for a major problem in all the CGSCC pass stuff, which is that it is completely broken when functions are deleted if they *don't* reuse a CGN. (there is a cute little fixme about this though :). This patch changes the protocol that CGSCC passes must obey: now the CGSCC pass manager copies the SCC and preincrements its iterator to avoid passes invalidating it. This allows CGSCC passes to mutate the current SCC. However multiple passes may be run on that SCC, so if passes do this, they are now required to *update* the SCC to be current when they return. Other less interesting parts of this patch are that it makes passes update the CG more directly, eliminates changeFunction, and requires clients of replaceCallSite to specify the new callee CGN if they are changing it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80527 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/llvm/Analysis/CallGraph.h17
-rw-r--r--include/llvm/CallGraphSCCPass.h5
-rw-r--r--include/llvm/Transforms/IPO/InlinerPass.h2
3 files changed, 15 insertions, 9 deletions
diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h
index f405f63..59dc344 100644
--- a/include/llvm/Analysis/CallGraph.h
+++ b/include/llvm/Analysis/CallGraph.h
@@ -130,12 +130,6 @@ public:
return removeFunctionFromModule((*this)[F]);
}
- /// changeFunction - This method changes the function associated with this
- /// CallGraphNode, for use by transformations that need to change the
- /// prototype of a Function (thus they must create a new Function and move the
- /// old code over).
- void changeFunction(Function *OldF, Function *NewF);
-
/// getOrInsertFunction - This method is identical to calling operator[], but
/// it will insert a new CallGraphNode for the specified function if one does
/// not already exist.
@@ -212,6 +206,15 @@ public:
void removeAllCalledFunctions() {
CalledFunctions.clear();
}
+
+ /// stealCalledFunctionsFrom - Move all the callee information from N to this
+ /// node.
+ void stealCalledFunctionsFrom(CallGraphNode *N) {
+ assert(CalledFunctions.empty() &&
+ "Cannot steal callsite information if I already have some");
+ std::swap(CalledFunctions, N->CalledFunctions);
+ }
+
/// addCalledFunction - Add a function to the list of functions called by this
/// one.
@@ -236,7 +239,7 @@ public:
/// replaceCallSite - Make the edge in the node for Old CallSite be for
/// New CallSite instead. Note that this method takes linear time, so it
/// should be used sparingly.
- void replaceCallSite(CallSite Old, CallSite New);
+ void replaceCallSite(CallSite Old, CallSite New, CallGraphNode *NewCallee);
friend class CallGraph;
diff --git a/include/llvm/CallGraphSCCPass.h b/include/llvm/CallGraphSCCPass.h
index 85e83e5..fc9feda 100644
--- a/include/llvm/CallGraphSCCPass.h
+++ b/include/llvm/CallGraphSCCPass.h
@@ -46,7 +46,10 @@ struct CallGraphSCCPass : public Pass {
/// non-recursive (or only self-recursive) functions will have an SCC size of
/// 1, where recursive portions of the call graph will have SCC size > 1.
///
- virtual bool runOnSCC(const std::vector<CallGraphNode *> &SCC) = 0;
+ /// SCC passes that add or delete functions to the SCC are required to update
+ /// the SCC list, otherwise stale pointers may be dereferenced.
+ ///
+ virtual bool runOnSCC(std::vector<CallGraphNode *> &SCC) = 0;
/// doFinalization - This method is called after the SCC's of the program has
/// been processed, allowing the pass to do final cleanup as necessary.
diff --git a/include/llvm/Transforms/IPO/InlinerPass.h b/include/llvm/Transforms/IPO/InlinerPass.h
index bf62999..5d00f42 100644
--- a/include/llvm/Transforms/IPO/InlinerPass.h
+++ b/include/llvm/Transforms/IPO/InlinerPass.h
@@ -40,7 +40,7 @@ struct Inliner : public CallGraphSCCPass {
// Main run interface method, this implements the interface required by the
// Pass class.
- virtual bool runOnSCC(const std::vector<CallGraphNode *> &SCC);
+ virtual bool runOnSCC(std::vector<CallGraphNode *> &SCC);
// doFinalization - Remove now-dead linkonce functions at the end of
// processing to avoid breaking the SCC traversal.