From dd0ecf67316d68940fda2733faacf73b8bd22ec6 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 3 Dec 2004 16:22:08 +0000 Subject: 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 --- lib/Transforms/IPO/StripSymbols.cpp | 84 ++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) (limited to 'lib/Transforms') 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 Operands; + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) + if (isa(C->getOperand(i)->getType()) && + C->getOperand(i)->hasOneUse()) + Operands.push_back(C->getOperand(i)); + if (GlobalVariable *GV = dyn_cast(C)) { + if (!GV->hasInternalLinkage()) return; // Don't delete non static globals. + GV->eraseFromParent(); + } + else if (!isa(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 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(FuncStart->use_back()); + Value *Arg = CI->getOperand(1); + CI->replaceAllUsesWith(RV); + CI->eraseFromParent(); + if (Arg->use_empty()) + if (GlobalVariable *GV = dyn_cast(Arg)) + DeadGlobals.push_back(GV); + } + FuncStart->eraseFromParent(); + } + if (StopPoint) { + Value *RV = UndefValue::get(StopPoint->getFunctionType()->getReturnType()); + while (!StopPoint->use_empty()) { + CallInst *CI = cast(StopPoint->use_back()); + Value *Arg = CI->getOperand(4); + CI->replaceAllUsesWith(RV); + CI->eraseFromParent(); + if (Arg->use_empty()) + if (GlobalVariable *GV = dyn_cast(Arg)) + DeadGlobals.push_back(GV); + } + StopPoint->eraseFromParent(); + } + if (RegionEnd) { + Value *RV = UndefValue::get(RegionEnd->getFunctionType()->getReturnType()); + while (!RegionEnd->use_empty()) { + CallInst *CI = cast(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; } -- cgit v1.2.3