#include "llvm/Pass.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/TypeSymbolTable.h"
+#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;
explicit StripSymbols(bool ODI = false)
: ModulePass(&ID), OnlyDebugInfo(ODI) {}
- /// StripSymbolNames - Strip symbol names.
- bool StripSymbolNames(Module &M);
+ virtual bool runOnModule(Module &M);
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ }
+ };
+
+ class VISIBILITY_HIDDEN StripNonDebugSymbols : public ModulePass {
+ public:
+ static char ID; // Pass identification, replacement for typeid
+ explicit StripNonDebugSymbols()
+ : ModulePass(&ID) {}
+
+ virtual bool runOnModule(Module &M);
- // StripDebugInfo - 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.
- bool StripDebugInfo(Module &M);
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ }
+ };
+
+ class VISIBILITY_HIDDEN StripDebugDeclare : public ModulePass {
+ public:
+ static char ID; // Pass identification, replacement for typeid
+ explicit StripDebugDeclare()
+ : ModulePass(&ID) {}
virtual bool runOnModule(Module &M);
return new StripSymbols(OnlyDebugInfo);
}
+char StripNonDebugSymbols::ID = 0;
+static RegisterPass<StripNonDebugSymbols>
+Y("strip-nondebug", "Strip all symbols, except dbg symbols, from a module");
+
+ModulePass *llvm::createStripNonDebugSymbolsPass() {
+ return new StripNonDebugSymbols();
+}
+
+char StripDebugDeclare::ID = 0;
+static RegisterPass<StripDebugDeclare>
+Z("strip-debug-declare", "Strip all llvm.dbg.declare intrinsics");
+
+ModulePass *llvm::createStripDebugDeclarePass() {
+ return new StripDebugDeclare();
+}
+
/// OnlyUsedBy - Return true if V is only used by Usr.
static bool OnlyUsedBy(Value *V, Value *Usr) {
for(Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) {
OnlyUsedBy(C->getOperand(i), C))
Operands.insert(C->getOperand(i));
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
- if (!GV->hasInternalLinkage()) return; // Don't delete non static globals.
+ if (!GV->hasLocalLinkage()) return; // Don't delete non static globals.
GV->eraseFromParent();
}
else if (!isa<Function>(C))
- C->destroyConstant();
+ if (isa<CompositeType>(C->getType()))
+ C->destroyConstant();
// If the constant referenced anything, see if we can delete it as well.
for (SmallPtrSet<Constant *, 4>::iterator OI = Operands.begin(),
// Strip the symbol table of its names.
//
-static void StripSymtab(ValueSymbolTable &ST) {
+static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) {
Value *V = VI->getValue();
++VI;
- if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasInternalLinkage()) {
- // Set name to "", removing from symbol table!
- V->setName("");
+ if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()) {
+ if (!PreserveDbgInfo || strncmp(V->getNameStart(), "llvm.dbg", 8))
+ // Set name to "", removing from symbol table!
+ V->setName("");
}
}
}
-bool StripSymbols::runOnModule(Module &M) {
- bool Changed = false;
- Changed |= StripDebugInfo(M);
- Changed |= StripSymbolNames(M);
- return Changed;
-}
-
// Strip the symbol table of its names.
-static void StripTypeSymtab(TypeSymbolTable &ST) {
- for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; )
- ST.remove(TI++);
+static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) {
+ for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; ) {
+ if (PreserveDbgInfo && strncmp(TI->first.c_str(), "llvm.dbg", 8) == 0)
+ ++TI;
+ else
+ ST.remove(TI++);
+ }
}
/// Find values that are marked as llvm.used.
}
/// StripSymbolNames - Strip symbol names.
-bool StripSymbols::StripSymbolNames(Module &M) {
-
- if (OnlyDebugInfo)
- return false;
+bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
SmallPtrSet<const GlobalValue*, 8> llvmUsedValues;
findUsedValues(M, llvmUsedValues);
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
- if (I->hasInternalLinkage() && llvmUsedValues.count(I) == 0)
- I->setName(""); // Internal symbols can't participate in linkage
+ if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0)
+ if (!PreserveDbgInfo || strncmp(I->getNameStart(), "llvm.dbg", 8))
+ I->setName(""); // Internal symbols can't participate in linkage
}
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
- if (I->hasInternalLinkage() && llvmUsedValues.count(I) == 0)
- I->setName(""); // Internal symbols can't participate in linkage
- StripSymtab(I->getValueSymbolTable());
+ if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0)
+ if (!PreserveDbgInfo || strncmp(I->getNameStart(), "llvm.dbg", 8))
+ I->setName(""); // Internal symbols can't participate in linkage
+ StripSymtab(I->getValueSymbolTable(), PreserveDbgInfo);
}
// Remove all names from types.
- StripTypeSymtab(M.getTypeSymbolTable());
+ StripTypeSymtab(M.getTypeSymbolTable(), PreserveDbgInfo);
return true;
}
// StripDebugInfo - 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.
-bool StripSymbols::StripDebugInfo(Module &M) {
+bool StripDebugInfo(Module &M) {
+
+ SmallPtrSet<const GlobalValue*, 8> llvmUsedValues;
+ findUsedValues(M, llvmUsedValues);
+
+ // Delete all dbg variables.
+ for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+ I != E; ++I) {
+ GlobalVariable *GV = dyn_cast<GlobalVariable>(I);
+ if (!GV) continue;
+ if (!GV->use_empty() && llvmUsedValues.count(I) == 0) {
+ if (strncmp(GV->getNameStart(), "llvm.dbg", 8) == 0) {
+ GV->replaceAllUsesWith(UndefValue::get(GV->getType()));
+ }
+ }
+ }
Function *FuncStart = M.getFunction("llvm.dbg.func.start");
Function *StopPoint = M.getFunction("llvm.dbg.stoppoint");
if (Declare) {
while (!Declare->use_empty()) {
CallInst *CI = cast<CallInst>(Declare->use_back());
- Value *Arg = CI->getOperand(2);
+ Value *Arg1 = CI->getOperand(1);
+ Value *Arg2 = CI->getOperand(2);
assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
CI->eraseFromParent();
- if (Arg->use_empty())
- if (Constant *C = dyn_cast<GlobalVariable>(Arg))
+ if (Arg1->use_empty()) {
+ if (Constant *C = dyn_cast<Constant>(Arg1))
+ DeadConstants.push_back(C);
+ else
+ RecursivelyDeleteTriviallyDeadInstructions(Arg1, NULL);
+ }
+ if (Arg2->use_empty())
+ if (Constant *C = dyn_cast<Constant>(Arg2))
DeadConstants.push_back(C);
}
Declare->eraseFromParent();
}
- SmallPtrSet<const GlobalValue*, 8> llvmUsedValues;
- findUsedValues(M, llvmUsedValues);
-
// llvm.dbg.compile_units and llvm.dbg.subprograms are marked as linkonce
// but since we are removing all debug information, make them internal now.
+ // FIXME: Use private linkage maybe?
if (Constant *C = M.getNamedGlobal("llvm.dbg.compile_units"))
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
GV->setLinkage(GlobalValue::InternalLinkage);
GV->setLinkage(GlobalValue::InternalLinkage);
// Delete all dbg variables.
- const Type *DbgVTy = M.getTypeByName("llvm.dbg.variable.type");
- const Type *DbgGVTy = M.getTypeByName("llvm.dbg.global_variable.type");
- if (DbgVTy || DbgGVTy)
- for (Module::global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I) {
- GlobalVariable *GV = dyn_cast<GlobalVariable>(I);
- if (!GV) continue;
- if (GV->use_empty() && llvmUsedValues.count(I) == 0
- && (!GV->hasSection()
- || strcmp(GV->getSection().c_str(), "llvm.metadata") == 0))
- DeadConstants.push_back(GV);
- }
+ for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+ I != E; ++I) {
+ GlobalVariable *GV = dyn_cast<GlobalVariable>(I);
+ if (!GV) continue;
+ if (GV->use_empty() && llvmUsedValues.count(I) == 0
+ && (!GV->hasSection()
+ || strcmp(GV->getSection().c_str(), "llvm.metadata") == 0))
+ DeadConstants.push_back(GV);
+ }
if (DeadConstants.empty())
return false;
Constant *C = DeadConstants.back();
DeadConstants.pop_back();
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
- if (GV->hasInternalLinkage())
+ if (GV->hasLocalLinkage())
RemoveDeadConstant(GV);
}
else
return true;
}
+
+bool StripSymbols::runOnModule(Module &M) {
+ bool Changed = false;
+ Changed |= StripDebugInfo(M);
+ if (!OnlyDebugInfo)
+ Changed |= StripSymbolNames(M, false);
+ return Changed;
+}
+
+bool StripNonDebugSymbols::runOnModule(Module &M) {
+ return StripSymbolNames(M, true);
+}
+
+bool StripDebugDeclare::runOnModule(Module &M) {
+
+ Function *Declare = M.getFunction("llvm.dbg.declare");
+
+ if (!Declare)
+ return false;
+
+ std::vector<Constant*> DeadConstants;
+
+ while (!Declare->use_empty()) {
+ CallInst *CI = cast<CallInst>(Declare->use_back());
+ Value *Arg1 = CI->getOperand(1);
+ Value *Arg2 = CI->getOperand(2);
+ assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
+ CI->eraseFromParent();
+ if (Arg1->use_empty()) {
+ if (Constant *C = dyn_cast<Constant>(Arg1))
+ DeadConstants.push_back(C);
+ else
+ RecursivelyDeleteTriviallyDeadInstructions(Arg1, NULL);
+ }
+ if (Arg2->use_empty())
+ if (Constant *C = dyn_cast<Constant>(Arg2))
+ DeadConstants.push_back(C);
+ }
+ Declare->eraseFromParent();
+
+ while (!DeadConstants.empty()) {
+ Constant *C = DeadConstants.back();
+ DeadConstants.pop_back();
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
+ if (GV->hasLocalLinkage())
+ RemoveDeadConstant(GV);
+ }
+ else
+ RemoveDeadConstant(C);
+ }
+
+ return true;
+}