diff options
author | Alexey Samsonov <samsonov@google.com> | 2012-10-09 08:13:15 +0000 |
---|---|---|
committer | Alexey Samsonov <samsonov@google.com> | 2012-10-09 08:13:15 +0000 |
commit | e97a3a4b4fccbe6283b616af93ab0117d3a7fee9 (patch) | |
tree | afe233298f0be8fd15476c640cc05e3c131a0c85 /lib/Transforms/IPO | |
parent | 6765834754cbb3cb0f15b4b15e98c5e73fa50066 (diff) | |
download | llvm-e97a3a4b4fccbe6283b616af93ab0117d3a7fee9.tar.gz llvm-e97a3a4b4fccbe6283b616af93ab0117d3a7fee9.tar.bz2 llvm-e97a3a4b4fccbe6283b616af93ab0117d3a7fee9.tar.xz |
Fix PR14016.
DeadArgumentElimination pass can replace one LLVM function with another,
invalidating a pointer stored in debug info metadata entry for this function.
To fix this, we collect debug info descriptors for functions before
running a DeadArgumentElimination pass and "patch" pointers in metadata nodes
if we replace a function.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165490 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/IPO')
-rw-r--r-- | lib/Transforms/IPO/DeadArgumentElimination.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index 13ff465c53..29053a09e0 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -21,7 +21,9 @@ #include "llvm/Transforms/IPO.h" #include "llvm/CallingConv.h" #include "llvm/Constant.h" +#include "llvm/DebugInfo.h" #include "llvm/DerivedTypes.h" +#include "llvm/DIBuilder.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" #include "llvm/LLVMContext.h" @@ -121,6 +123,15 @@ namespace { typedef SmallVector<RetOrArg, 5> UseVector; + // Map each LLVM function to corresponding metadata with debug info. If + // the function is replaced with another one, we should patch the pointer + // to LLVM function in metadata. + // As the code generation for module is finished (and DIBuilder is + // finalized) we assume that subprogram descriptors won't be changed, and + // they are stored in map for short duration anyway. + typedef std::map<Function*, DISubprogram> FunctionDIMap; + FunctionDIMap FunctionDIs; + protected: // DAH uses this to specify a different ID. explicit DAE(char &ID) : ModulePass(ID) {} @@ -141,6 +152,7 @@ namespace { unsigned RetValNum = 0); Liveness SurveyUses(const Value *V, UseVector &MaybeLiveUses); + void CollectFunctionDIs(Module &M); void SurveyFunction(const Function &F); void MarkValue(const RetOrArg &RA, Liveness L, const UseVector &MaybeLiveUses); @@ -180,6 +192,31 @@ INITIALIZE_PASS(DAH, "deadarghaX0r", ModulePass *llvm::createDeadArgEliminationPass() { return new DAE(); } ModulePass *llvm::createDeadArgHackingPass() { return new DAH(); } +/// CollectFunctionDIs - Map each function in the module to its debug info +/// descriptor. +void DAE::CollectFunctionDIs(Module &M) { + FunctionDIs.clear(); + + for (Module::named_metadata_iterator I = M.named_metadata_begin(), + E = M.named_metadata_end(); I != E; ++I) { + NamedMDNode &NMD = *I; + for (unsigned i = 0, n = NMD.getNumOperands(); i < n; ++i) { + MDNode *Node = NMD.getOperand(i); + if (DIDescriptor(Node).isCompileUnit()) { + DICompileUnit CU(Node); + const DIArray &SPs = CU.getSubprograms(); + for (unsigned i = 0, n = SPs.getNumElements(); i < n; ++i) { + DISubprogram SP(SPs.getElement(i)); + if (SP.Verify()) { + if (Function *F = SP.getFunction()) + FunctionDIs[F] = SP; + } + } + } + } + } +} + /// DeleteDeadVarargs - If this is an function that takes a ... list, and if /// llvm.vastart is never called, the varargs list is dead for the function. bool DAE::DeleteDeadVarargs(Function &Fn) { @@ -284,6 +321,11 @@ bool DAE::DeleteDeadVarargs(Function &Fn) { I2->takeName(I); } + // Patch the pointer to LLVM function in debug info descriptor. + FunctionDIMap::iterator DI = FunctionDIs.find(&Fn); + if (DI != FunctionDIs.end()) + DI->second.replaceFunction(NF); + // Finally, nuke the old function. Fn.eraseFromParent(); return true; @@ -952,6 +994,11 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { BB->getInstList().erase(RI); } + // Patch the pointer to LLVM function in debug info descriptor. + FunctionDIMap::iterator DI = FunctionDIs.find(F); + if (DI != FunctionDIs.end()) + DI->second.replaceFunction(NF); + // Now that the old function is dead, delete it. F->eraseFromParent(); @@ -961,6 +1008,9 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { bool DAE::runOnModule(Module &M) { bool Changed = false; + // Collect debug info descriptors for functions. + CollectFunctionDIs(M); + // First pass: Do a simple check to see if any functions can have their "..." // removed. We can do this if they never call va_start. This loop cannot be // fused with the next loop, because deleting a function invalidates |