diff options
author | Chris Lattner <sabre@nondot.org> | 2004-12-03 16:22:08 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2004-12-03 16:22:08 +0000 |
commit | dd0ecf67316d68940fda2733faacf73b8bd22ec6 (patch) | |
tree | e48aab8d80d21ec120911b30290ad7754d350c38 /lib | |
parent | 82bd0c51d7606067718ed85389f3a283de74823d (diff) | |
download | llvm-dd0ecf67316d68940fda2733faacf73b8bd22ec6.tar.gz llvm-dd0ecf67316d68940fda2733faacf73b8bd22ec6.tar.bz2 llvm-dd0ecf67316d68940fda2733faacf73b8bd22ec6.tar.xz |
Implement stripping of debug symbols, making the --strip-debug options in
gccas/gccld more than just a noop.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@18456 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Transforms/IPO/StripSymbols.cpp | 84 |
1 files changed, 82 insertions, 2 deletions
diff --git a/lib/Transforms/IPO/StripSymbols.cpp b/lib/Transforms/IPO/StripSymbols.cpp index f611d9cf0a..03ea55b414 100644 --- a/lib/Transforms/IPO/StripSymbols.cpp +++ b/lib/Transforms/IPO/StripSymbols.cpp @@ -23,9 +23,12 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/IPO.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" #include "llvm/Module.h" -#include "llvm/SymbolTable.h" #include "llvm/Pass.h" +#include "llvm/SymbolTable.h" using namespace llvm; namespace { @@ -47,6 +50,26 @@ ModulePass *llvm::createStripSymbolsPass(bool OnlyDebugInfo) { return new StripSymbols(OnlyDebugInfo); } +static void RemoveDeadConstant(Constant *C) { + assert(C->use_empty() && "Constant is not dead!"); + std::vector<Constant*> Operands; + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) + if (isa<DerivedType>(C->getOperand(i)->getType()) && + C->getOperand(i)->hasOneUse()) + Operands.push_back(C->getOperand(i)); + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) { + if (!GV->hasInternalLinkage()) return; // Don't delete non static globals. + GV->eraseFromParent(); + } + else if (!isa<Function>(C)) + C->destroyConstant(); + + // If the constant referenced anything, see if we can delete it as well. + while (!Operands.empty()) { + RemoveDeadConstant(Operands.back()); + Operands.pop_back(); + } +} bool StripSymbols::runOnModule(Module &M) { // If we're not just stripping debug info, strip all symbols from the @@ -63,6 +86,63 @@ bool StripSymbols::runOnModule(Module &M) { } } - // FIXME: implement stripping of debug info. + // Strip debug info in the module if it exists. To do this, we remove + // llvm.dbg.func.start, llvm.dbg.stoppoint, and llvm.dbg.region.end calls, and + // any globals they point to if now dead. + Function *FuncStart = M.getNamedFunction("llvm.dbg.func.start"); + Function *StopPoint = M.getNamedFunction("llvm.dbg.stoppoint"); + Function *RegionEnd = M.getNamedFunction("llvm.dbg.region.end"); + if (!FuncStart && !StopPoint && !RegionEnd) + return true; + + std::vector<GlobalVariable*> DeadGlobals; + + // Remove all of the calls to the debugger intrinsics, and remove them from + // the module. + if (FuncStart) { + Value *RV = UndefValue::get(StopPoint->getFunctionType()->getReturnType()); + while (!FuncStart->use_empty()) { + CallInst *CI = cast<CallInst>(FuncStart->use_back()); + Value *Arg = CI->getOperand(1); + CI->replaceAllUsesWith(RV); + CI->eraseFromParent(); + if (Arg->use_empty()) + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg)) + DeadGlobals.push_back(GV); + } + FuncStart->eraseFromParent(); + } + if (StopPoint) { + Value *RV = UndefValue::get(StopPoint->getFunctionType()->getReturnType()); + while (!StopPoint->use_empty()) { + CallInst *CI = cast<CallInst>(StopPoint->use_back()); + Value *Arg = CI->getOperand(4); + CI->replaceAllUsesWith(RV); + CI->eraseFromParent(); + if (Arg->use_empty()) + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg)) + DeadGlobals.push_back(GV); + } + StopPoint->eraseFromParent(); + } + if (RegionEnd) { + Value *RV = UndefValue::get(RegionEnd->getFunctionType()->getReturnType()); + while (!RegionEnd->use_empty()) { + CallInst *CI = cast<CallInst>(RegionEnd->use_back()); + CI->replaceAllUsesWith(RV); + CI->eraseFromParent(); + } + RegionEnd->eraseFromParent(); + } + + // Finally, delete any internal globals that were only used by the debugger + // intrinsics. + while (!DeadGlobals.empty()) { + GlobalVariable *GV = DeadGlobals.back(); + DeadGlobals.pop_back(); + if (GV->hasInternalLinkage()) + RemoveDeadConstant(GV); + } + return true; } |