llvm-6502/lib/Transforms/IPO/StripSymbols.cpp
Reid Spencer 9133fe2895 Apply the VISIBILITY_HIDDEN field to the remaining anonymous classes in
the Transforms library. This reduces debug library size by 132 KB, debug
binary size by 376 KB, and reduces link time for llvm tools slightly.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33939 91177308-0d34-0410-b5e6-96231b3b80d8
2007-02-05 23:32:05 +00:00

182 lines
6.3 KiB
C++

//===- StripSymbols.cpp - Strip symbols and debug info from a module ------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements stripping symbols out of symbol tables.
//
// Specifically, this allows you to strip all of the symbols out of:
// * All functions in a module
// * All non-essential symbols in a module (all function symbols + all module
// scope symbols)
// * Debug information.
//
// Notice that:
// * This pass makes code much less readable, so it should only be used in
// situations where the 'strip' utility would be used (such as reducing
// code size, and making it harder to reverse engineer code).
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;
namespace {
class VISIBILITY_HIDDEN StripSymbols : public ModulePass {
bool OnlyDebugInfo;
public:
StripSymbols(bool ODI = false) : OnlyDebugInfo(ODI) {}
virtual bool runOnModule(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}
};
RegisterPass<StripSymbols> X("strip", "Strip all symbols from a module");
}
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
// functions and the names from any internal globals.
if (!OnlyDebugInfo) {
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I)
if (I->hasInternalLinkage())
I->setName(""); // Internal symbols can't participate in linkage
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
if (I->hasInternalLinkage())
I->setName(""); // Internal symbols can't participate in linkage
I->getValueSymbolTable().strip();
}
// Remove all names from types.
M.getTypeSymbolTable().strip();
}
// 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.getFunction("llvm.dbg.func.start");
Function *StopPoint = M.getFunction("llvm.dbg.stoppoint");
Function *RegionStart = M.getFunction("llvm.dbg.region.start");
Function *RegionEnd = M.getFunction("llvm.dbg.region.end");
Function *Declare = M.getFunction("llvm.dbg.declare");
if (!FuncStart && !StopPoint && !RegionStart && !RegionEnd && !Declare)
return true;
std::vector<GlobalVariable*> DeadGlobals;
// Remove all of the calls to the debugger intrinsics, and remove them from
// the module.
if (FuncStart) {
while (!FuncStart->use_empty()) {
CallInst *CI = cast<CallInst>(FuncStart->use_back());
Value *Arg = CI->getOperand(1);
assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
CI->eraseFromParent();
if (Arg->use_empty())
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg))
DeadGlobals.push_back(GV);
}
FuncStart->eraseFromParent();
}
if (StopPoint) {
while (!StopPoint->use_empty()) {
CallInst *CI = cast<CallInst>(StopPoint->use_back());
Value *Arg = CI->getOperand(3);
assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
CI->eraseFromParent();
if (Arg->use_empty())
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg))
DeadGlobals.push_back(GV);
}
StopPoint->eraseFromParent();
}
if (RegionStart) {
while (!RegionStart->use_empty()) {
CallInst *CI = cast<CallInst>(RegionStart->use_back());
Value *Arg = CI->getOperand(1);
assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
CI->eraseFromParent();
if (Arg->use_empty())
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg))
DeadGlobals.push_back(GV);
}
RegionStart->eraseFromParent();
}
if (RegionEnd) {
while (!RegionEnd->use_empty()) {
CallInst *CI = cast<CallInst>(RegionEnd->use_back());
Value *Arg = CI->getOperand(1);
assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
CI->eraseFromParent();
if (Arg->use_empty())
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg))
DeadGlobals.push_back(GV);
}
RegionEnd->eraseFromParent();
}
if (Declare) {
while (!Declare->use_empty()) {
CallInst *CI = cast<CallInst>(Declare->use_back());
Value *Arg = CI->getOperand(2);
assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
CI->eraseFromParent();
if (Arg->use_empty())
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg))
DeadGlobals.push_back(GV);
}
Declare->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;
}