xref: /aosp_15_r20/external/llvm/lib/Transforms/IPO/StripSymbols.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- StripSymbols.cpp - Strip symbols and debug info from a module ------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // The StripSymbols transformation implements code stripping. Specifically, it
11*9880d681SAndroid Build Coastguard Worker // can delete:
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //   * names for virtual registers
14*9880d681SAndroid Build Coastguard Worker //   * symbols for internal globals and functions
15*9880d681SAndroid Build Coastguard Worker //   * debug information
16*9880d681SAndroid Build Coastguard Worker //
17*9880d681SAndroid Build Coastguard Worker // Note that this transformation makes code much less readable, so it should
18*9880d681SAndroid Build Coastguard Worker // only be used in situations where the 'strip' utility would be used, such as
19*9880d681SAndroid Build Coastguard Worker // reducing code size or making it harder to reverse engineer code.
20*9880d681SAndroid Build Coastguard Worker //
21*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
22*9880d681SAndroid Build Coastguard Worker 
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/IPO.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallPtrSet.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DebugInfo.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/TypeFinder.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/ValueSymbolTable.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/Local.h"
34*9880d681SAndroid Build Coastguard Worker using namespace llvm;
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker namespace {
37*9880d681SAndroid Build Coastguard Worker   class StripSymbols : public ModulePass {
38*9880d681SAndroid Build Coastguard Worker     bool OnlyDebugInfo;
39*9880d681SAndroid Build Coastguard Worker   public:
40*9880d681SAndroid Build Coastguard Worker     static char ID; // Pass identification, replacement for typeid
StripSymbols(bool ODI=false)41*9880d681SAndroid Build Coastguard Worker     explicit StripSymbols(bool ODI = false)
42*9880d681SAndroid Build Coastguard Worker       : ModulePass(ID), OnlyDebugInfo(ODI) {
43*9880d681SAndroid Build Coastguard Worker         initializeStripSymbolsPass(*PassRegistry::getPassRegistry());
44*9880d681SAndroid Build Coastguard Worker       }
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker     bool runOnModule(Module &M) override;
47*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const48*9880d681SAndroid Build Coastguard Worker     void getAnalysisUsage(AnalysisUsage &AU) const override {
49*9880d681SAndroid Build Coastguard Worker       AU.setPreservesAll();
50*9880d681SAndroid Build Coastguard Worker     }
51*9880d681SAndroid Build Coastguard Worker   };
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker   class StripNonDebugSymbols : public ModulePass {
54*9880d681SAndroid Build Coastguard Worker   public:
55*9880d681SAndroid Build Coastguard Worker     static char ID; // Pass identification, replacement for typeid
StripNonDebugSymbols()56*9880d681SAndroid Build Coastguard Worker     explicit StripNonDebugSymbols()
57*9880d681SAndroid Build Coastguard Worker       : ModulePass(ID) {
58*9880d681SAndroid Build Coastguard Worker         initializeStripNonDebugSymbolsPass(*PassRegistry::getPassRegistry());
59*9880d681SAndroid Build Coastguard Worker       }
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker     bool runOnModule(Module &M) override;
62*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const63*9880d681SAndroid Build Coastguard Worker     void getAnalysisUsage(AnalysisUsage &AU) const override {
64*9880d681SAndroid Build Coastguard Worker       AU.setPreservesAll();
65*9880d681SAndroid Build Coastguard Worker     }
66*9880d681SAndroid Build Coastguard Worker   };
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker   class StripDebugDeclare : public ModulePass {
69*9880d681SAndroid Build Coastguard Worker   public:
70*9880d681SAndroid Build Coastguard Worker     static char ID; // Pass identification, replacement for typeid
StripDebugDeclare()71*9880d681SAndroid Build Coastguard Worker     explicit StripDebugDeclare()
72*9880d681SAndroid Build Coastguard Worker       : ModulePass(ID) {
73*9880d681SAndroid Build Coastguard Worker         initializeStripDebugDeclarePass(*PassRegistry::getPassRegistry());
74*9880d681SAndroid Build Coastguard Worker       }
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker     bool runOnModule(Module &M) override;
77*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const78*9880d681SAndroid Build Coastguard Worker     void getAnalysisUsage(AnalysisUsage &AU) const override {
79*9880d681SAndroid Build Coastguard Worker       AU.setPreservesAll();
80*9880d681SAndroid Build Coastguard Worker     }
81*9880d681SAndroid Build Coastguard Worker   };
82*9880d681SAndroid Build Coastguard Worker 
83*9880d681SAndroid Build Coastguard Worker   class StripDeadDebugInfo : public ModulePass {
84*9880d681SAndroid Build Coastguard Worker   public:
85*9880d681SAndroid Build Coastguard Worker     static char ID; // Pass identification, replacement for typeid
StripDeadDebugInfo()86*9880d681SAndroid Build Coastguard Worker     explicit StripDeadDebugInfo()
87*9880d681SAndroid Build Coastguard Worker       : ModulePass(ID) {
88*9880d681SAndroid Build Coastguard Worker         initializeStripDeadDebugInfoPass(*PassRegistry::getPassRegistry());
89*9880d681SAndroid Build Coastguard Worker       }
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker     bool runOnModule(Module &M) override;
92*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const93*9880d681SAndroid Build Coastguard Worker     void getAnalysisUsage(AnalysisUsage &AU) const override {
94*9880d681SAndroid Build Coastguard Worker       AU.setPreservesAll();
95*9880d681SAndroid Build Coastguard Worker     }
96*9880d681SAndroid Build Coastguard Worker   };
97*9880d681SAndroid Build Coastguard Worker }
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker char StripSymbols::ID = 0;
100*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(StripSymbols, "strip",
101*9880d681SAndroid Build Coastguard Worker                 "Strip all symbols from a module", false, false)
102*9880d681SAndroid Build Coastguard Worker 
createStripSymbolsPass(bool OnlyDebugInfo)103*9880d681SAndroid Build Coastguard Worker ModulePass *llvm::createStripSymbolsPass(bool OnlyDebugInfo) {
104*9880d681SAndroid Build Coastguard Worker   return new StripSymbols(OnlyDebugInfo);
105*9880d681SAndroid Build Coastguard Worker }
106*9880d681SAndroid Build Coastguard Worker 
107*9880d681SAndroid Build Coastguard Worker char StripNonDebugSymbols::ID = 0;
108*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(StripNonDebugSymbols, "strip-nondebug",
109*9880d681SAndroid Build Coastguard Worker                 "Strip all symbols, except dbg symbols, from a module",
110*9880d681SAndroid Build Coastguard Worker                 false, false)
111*9880d681SAndroid Build Coastguard Worker 
createStripNonDebugSymbolsPass()112*9880d681SAndroid Build Coastguard Worker ModulePass *llvm::createStripNonDebugSymbolsPass() {
113*9880d681SAndroid Build Coastguard Worker   return new StripNonDebugSymbols();
114*9880d681SAndroid Build Coastguard Worker }
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker char StripDebugDeclare::ID = 0;
117*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(StripDebugDeclare, "strip-debug-declare",
118*9880d681SAndroid Build Coastguard Worker                 "Strip all llvm.dbg.declare intrinsics", false, false)
119*9880d681SAndroid Build Coastguard Worker 
createStripDebugDeclarePass()120*9880d681SAndroid Build Coastguard Worker ModulePass *llvm::createStripDebugDeclarePass() {
121*9880d681SAndroid Build Coastguard Worker   return new StripDebugDeclare();
122*9880d681SAndroid Build Coastguard Worker }
123*9880d681SAndroid Build Coastguard Worker 
124*9880d681SAndroid Build Coastguard Worker char StripDeadDebugInfo::ID = 0;
125*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(StripDeadDebugInfo, "strip-dead-debug-info",
126*9880d681SAndroid Build Coastguard Worker                 "Strip debug info for unused symbols", false, false)
127*9880d681SAndroid Build Coastguard Worker 
createStripDeadDebugInfoPass()128*9880d681SAndroid Build Coastguard Worker ModulePass *llvm::createStripDeadDebugInfoPass() {
129*9880d681SAndroid Build Coastguard Worker   return new StripDeadDebugInfo();
130*9880d681SAndroid Build Coastguard Worker }
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker /// OnlyUsedBy - Return true if V is only used by Usr.
OnlyUsedBy(Value * V,Value * Usr)133*9880d681SAndroid Build Coastguard Worker static bool OnlyUsedBy(Value *V, Value *Usr) {
134*9880d681SAndroid Build Coastguard Worker   for (User *U : V->users())
135*9880d681SAndroid Build Coastguard Worker     if (U != Usr)
136*9880d681SAndroid Build Coastguard Worker       return false;
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker   return true;
139*9880d681SAndroid Build Coastguard Worker }
140*9880d681SAndroid Build Coastguard Worker 
RemoveDeadConstant(Constant * C)141*9880d681SAndroid Build Coastguard Worker static void RemoveDeadConstant(Constant *C) {
142*9880d681SAndroid Build Coastguard Worker   assert(C->use_empty() && "Constant is not dead!");
143*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<Constant*, 4> Operands;
144*9880d681SAndroid Build Coastguard Worker   for (Value *Op : C->operands())
145*9880d681SAndroid Build Coastguard Worker     if (OnlyUsedBy(Op, C))
146*9880d681SAndroid Build Coastguard Worker       Operands.insert(cast<Constant>(Op));
147*9880d681SAndroid Build Coastguard Worker   if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
148*9880d681SAndroid Build Coastguard Worker     if (!GV->hasLocalLinkage()) return;   // Don't delete non-static globals.
149*9880d681SAndroid Build Coastguard Worker     GV->eraseFromParent();
150*9880d681SAndroid Build Coastguard Worker   }
151*9880d681SAndroid Build Coastguard Worker   else if (!isa<Function>(C))
152*9880d681SAndroid Build Coastguard Worker     if (isa<CompositeType>(C->getType()))
153*9880d681SAndroid Build Coastguard Worker       C->destroyConstant();
154*9880d681SAndroid Build Coastguard Worker 
155*9880d681SAndroid Build Coastguard Worker   // If the constant referenced anything, see if we can delete it as well.
156*9880d681SAndroid Build Coastguard Worker   for (Constant *O : Operands)
157*9880d681SAndroid Build Coastguard Worker     RemoveDeadConstant(O);
158*9880d681SAndroid Build Coastguard Worker }
159*9880d681SAndroid Build Coastguard Worker 
160*9880d681SAndroid Build Coastguard Worker // Strip the symbol table of its names.
161*9880d681SAndroid Build Coastguard Worker //
StripSymtab(ValueSymbolTable & ST,bool PreserveDbgInfo)162*9880d681SAndroid Build Coastguard Worker static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
163*9880d681SAndroid Build Coastguard Worker   for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) {
164*9880d681SAndroid Build Coastguard Worker     Value *V = VI->getValue();
165*9880d681SAndroid Build Coastguard Worker     ++VI;
166*9880d681SAndroid Build Coastguard Worker     if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()) {
167*9880d681SAndroid Build Coastguard Worker       if (!PreserveDbgInfo || !V->getName().startswith("llvm.dbg"))
168*9880d681SAndroid Build Coastguard Worker         // Set name to "", removing from symbol table!
169*9880d681SAndroid Build Coastguard Worker         V->setName("");
170*9880d681SAndroid Build Coastguard Worker     }
171*9880d681SAndroid Build Coastguard Worker   }
172*9880d681SAndroid Build Coastguard Worker }
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker // Strip any named types of their names.
StripTypeNames(Module & M,bool PreserveDbgInfo)175*9880d681SAndroid Build Coastguard Worker static void StripTypeNames(Module &M, bool PreserveDbgInfo) {
176*9880d681SAndroid Build Coastguard Worker   TypeFinder StructTypes;
177*9880d681SAndroid Build Coastguard Worker   StructTypes.run(M, false);
178*9880d681SAndroid Build Coastguard Worker 
179*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) {
180*9880d681SAndroid Build Coastguard Worker     StructType *STy = StructTypes[i];
181*9880d681SAndroid Build Coastguard Worker     if (STy->isLiteral() || STy->getName().empty()) continue;
182*9880d681SAndroid Build Coastguard Worker 
183*9880d681SAndroid Build Coastguard Worker     if (PreserveDbgInfo && STy->getName().startswith("llvm.dbg"))
184*9880d681SAndroid Build Coastguard Worker       continue;
185*9880d681SAndroid Build Coastguard Worker 
186*9880d681SAndroid Build Coastguard Worker     STy->setName("");
187*9880d681SAndroid Build Coastguard Worker   }
188*9880d681SAndroid Build Coastguard Worker }
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker /// Find values that are marked as llvm.used.
findUsedValues(GlobalVariable * LLVMUsed,SmallPtrSetImpl<const GlobalValue * > & UsedValues)191*9880d681SAndroid Build Coastguard Worker static void findUsedValues(GlobalVariable *LLVMUsed,
192*9880d681SAndroid Build Coastguard Worker                            SmallPtrSetImpl<const GlobalValue*> &UsedValues) {
193*9880d681SAndroid Build Coastguard Worker   if (!LLVMUsed) return;
194*9880d681SAndroid Build Coastguard Worker   UsedValues.insert(LLVMUsed);
195*9880d681SAndroid Build Coastguard Worker 
196*9880d681SAndroid Build Coastguard Worker   ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
197*9880d681SAndroid Build Coastguard Worker 
198*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
199*9880d681SAndroid Build Coastguard Worker     if (GlobalValue *GV =
200*9880d681SAndroid Build Coastguard Worker           dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
201*9880d681SAndroid Build Coastguard Worker       UsedValues.insert(GV);
202*9880d681SAndroid Build Coastguard Worker }
203*9880d681SAndroid Build Coastguard Worker 
204*9880d681SAndroid Build Coastguard Worker /// StripSymbolNames - Strip symbol names.
StripSymbolNames(Module & M,bool PreserveDbgInfo)205*9880d681SAndroid Build Coastguard Worker static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
206*9880d681SAndroid Build Coastguard Worker 
207*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<const GlobalValue*, 8> llvmUsedValues;
208*9880d681SAndroid Build Coastguard Worker   findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
209*9880d681SAndroid Build Coastguard Worker   findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);
210*9880d681SAndroid Build Coastguard Worker 
211*9880d681SAndroid Build Coastguard Worker   for (Module::global_iterator I = M.global_begin(), E = M.global_end();
212*9880d681SAndroid Build Coastguard Worker        I != E; ++I) {
213*9880d681SAndroid Build Coastguard Worker     if (I->hasLocalLinkage() && llvmUsedValues.count(&*I) == 0)
214*9880d681SAndroid Build Coastguard Worker       if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg"))
215*9880d681SAndroid Build Coastguard Worker         I->setName("");     // Internal symbols can't participate in linkage
216*9880d681SAndroid Build Coastguard Worker   }
217*9880d681SAndroid Build Coastguard Worker 
218*9880d681SAndroid Build Coastguard Worker   for (Function &I : M) {
219*9880d681SAndroid Build Coastguard Worker     if (I.hasLocalLinkage() && llvmUsedValues.count(&I) == 0)
220*9880d681SAndroid Build Coastguard Worker       if (!PreserveDbgInfo || !I.getName().startswith("llvm.dbg"))
221*9880d681SAndroid Build Coastguard Worker         I.setName(""); // Internal symbols can't participate in linkage
222*9880d681SAndroid Build Coastguard Worker     StripSymtab(I.getValueSymbolTable(), PreserveDbgInfo);
223*9880d681SAndroid Build Coastguard Worker   }
224*9880d681SAndroid Build Coastguard Worker 
225*9880d681SAndroid Build Coastguard Worker   // Remove all names from types.
226*9880d681SAndroid Build Coastguard Worker   StripTypeNames(M, PreserveDbgInfo);
227*9880d681SAndroid Build Coastguard Worker 
228*9880d681SAndroid Build Coastguard Worker   return true;
229*9880d681SAndroid Build Coastguard Worker }
230*9880d681SAndroid Build Coastguard Worker 
runOnModule(Module & M)231*9880d681SAndroid Build Coastguard Worker bool StripSymbols::runOnModule(Module &M) {
232*9880d681SAndroid Build Coastguard Worker   if (skipModule(M))
233*9880d681SAndroid Build Coastguard Worker     return false;
234*9880d681SAndroid Build Coastguard Worker 
235*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
236*9880d681SAndroid Build Coastguard Worker   Changed |= StripDebugInfo(M);
237*9880d681SAndroid Build Coastguard Worker   if (!OnlyDebugInfo)
238*9880d681SAndroid Build Coastguard Worker     Changed |= StripSymbolNames(M, false);
239*9880d681SAndroid Build Coastguard Worker   return Changed;
240*9880d681SAndroid Build Coastguard Worker }
241*9880d681SAndroid Build Coastguard Worker 
runOnModule(Module & M)242*9880d681SAndroid Build Coastguard Worker bool StripNonDebugSymbols::runOnModule(Module &M) {
243*9880d681SAndroid Build Coastguard Worker   if (skipModule(M))
244*9880d681SAndroid Build Coastguard Worker     return false;
245*9880d681SAndroid Build Coastguard Worker 
246*9880d681SAndroid Build Coastguard Worker   return StripSymbolNames(M, true);
247*9880d681SAndroid Build Coastguard Worker }
248*9880d681SAndroid Build Coastguard Worker 
runOnModule(Module & M)249*9880d681SAndroid Build Coastguard Worker bool StripDebugDeclare::runOnModule(Module &M) {
250*9880d681SAndroid Build Coastguard Worker   if (skipModule(M))
251*9880d681SAndroid Build Coastguard Worker     return false;
252*9880d681SAndroid Build Coastguard Worker 
253*9880d681SAndroid Build Coastguard Worker   Function *Declare = M.getFunction("llvm.dbg.declare");
254*9880d681SAndroid Build Coastguard Worker   std::vector<Constant*> DeadConstants;
255*9880d681SAndroid Build Coastguard Worker 
256*9880d681SAndroid Build Coastguard Worker   if (Declare) {
257*9880d681SAndroid Build Coastguard Worker     while (!Declare->use_empty()) {
258*9880d681SAndroid Build Coastguard Worker       CallInst *CI = cast<CallInst>(Declare->user_back());
259*9880d681SAndroid Build Coastguard Worker       Value *Arg1 = CI->getArgOperand(0);
260*9880d681SAndroid Build Coastguard Worker       Value *Arg2 = CI->getArgOperand(1);
261*9880d681SAndroid Build Coastguard Worker       assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
262*9880d681SAndroid Build Coastguard Worker       CI->eraseFromParent();
263*9880d681SAndroid Build Coastguard Worker       if (Arg1->use_empty()) {
264*9880d681SAndroid Build Coastguard Worker         if (Constant *C = dyn_cast<Constant>(Arg1))
265*9880d681SAndroid Build Coastguard Worker           DeadConstants.push_back(C);
266*9880d681SAndroid Build Coastguard Worker         else
267*9880d681SAndroid Build Coastguard Worker           RecursivelyDeleteTriviallyDeadInstructions(Arg1);
268*9880d681SAndroid Build Coastguard Worker       }
269*9880d681SAndroid Build Coastguard Worker       if (Arg2->use_empty())
270*9880d681SAndroid Build Coastguard Worker         if (Constant *C = dyn_cast<Constant>(Arg2))
271*9880d681SAndroid Build Coastguard Worker           DeadConstants.push_back(C);
272*9880d681SAndroid Build Coastguard Worker     }
273*9880d681SAndroid Build Coastguard Worker     Declare->eraseFromParent();
274*9880d681SAndroid Build Coastguard Worker   }
275*9880d681SAndroid Build Coastguard Worker 
276*9880d681SAndroid Build Coastguard Worker   while (!DeadConstants.empty()) {
277*9880d681SAndroid Build Coastguard Worker     Constant *C = DeadConstants.back();
278*9880d681SAndroid Build Coastguard Worker     DeadConstants.pop_back();
279*9880d681SAndroid Build Coastguard Worker     if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
280*9880d681SAndroid Build Coastguard Worker       if (GV->hasLocalLinkage())
281*9880d681SAndroid Build Coastguard Worker         RemoveDeadConstant(GV);
282*9880d681SAndroid Build Coastguard Worker     } else
283*9880d681SAndroid Build Coastguard Worker       RemoveDeadConstant(C);
284*9880d681SAndroid Build Coastguard Worker   }
285*9880d681SAndroid Build Coastguard Worker 
286*9880d681SAndroid Build Coastguard Worker   return true;
287*9880d681SAndroid Build Coastguard Worker }
288*9880d681SAndroid Build Coastguard Worker 
289*9880d681SAndroid Build Coastguard Worker /// Remove any debug info for global variables/functions in the given module for
290*9880d681SAndroid Build Coastguard Worker /// which said global variable/function no longer exists (i.e. is null).
291*9880d681SAndroid Build Coastguard Worker ///
292*9880d681SAndroid Build Coastguard Worker /// Debugging information is encoded in llvm IR using metadata. This is designed
293*9880d681SAndroid Build Coastguard Worker /// such a way that debug info for symbols preserved even if symbols are
294*9880d681SAndroid Build Coastguard Worker /// optimized away by the optimizer. This special pass removes debug info for
295*9880d681SAndroid Build Coastguard Worker /// such symbols.
runOnModule(Module & M)296*9880d681SAndroid Build Coastguard Worker bool StripDeadDebugInfo::runOnModule(Module &M) {
297*9880d681SAndroid Build Coastguard Worker   if (skipModule(M))
298*9880d681SAndroid Build Coastguard Worker     return false;
299*9880d681SAndroid Build Coastguard Worker 
300*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker   LLVMContext &C = M.getContext();
303*9880d681SAndroid Build Coastguard Worker 
304*9880d681SAndroid Build Coastguard Worker   // Find all debug info in F. This is actually overkill in terms of what we
305*9880d681SAndroid Build Coastguard Worker   // want to do, but we want to try and be as resilient as possible in the face
306*9880d681SAndroid Build Coastguard Worker   // of potential debug info changes by using the formal interfaces given to us
307*9880d681SAndroid Build Coastguard Worker   // as much as possible.
308*9880d681SAndroid Build Coastguard Worker   DebugInfoFinder F;
309*9880d681SAndroid Build Coastguard Worker   F.processModule(M);
310*9880d681SAndroid Build Coastguard Worker 
311*9880d681SAndroid Build Coastguard Worker   // For each compile unit, find the live set of global variables/functions and
312*9880d681SAndroid Build Coastguard Worker   // replace the current list of potentially dead global variables/functions
313*9880d681SAndroid Build Coastguard Worker   // with the live list.
314*9880d681SAndroid Build Coastguard Worker   SmallVector<Metadata *, 64> LiveGlobalVariables;
315*9880d681SAndroid Build Coastguard Worker   SmallVector<Metadata *, 64> LiveSubprograms;
316*9880d681SAndroid Build Coastguard Worker   DenseSet<const MDNode *> VisitedSet;
317*9880d681SAndroid Build Coastguard Worker 
318*9880d681SAndroid Build Coastguard Worker   std::set<DISubprogram *> LiveSPs;
319*9880d681SAndroid Build Coastguard Worker   for (Function &F : M) {
320*9880d681SAndroid Build Coastguard Worker     if (DISubprogram *SP = F.getSubprogram())
321*9880d681SAndroid Build Coastguard Worker       LiveSPs.insert(SP);
322*9880d681SAndroid Build Coastguard Worker   }
323*9880d681SAndroid Build Coastguard Worker 
324*9880d681SAndroid Build Coastguard Worker   for (DICompileUnit *DIC : F.compile_units()) {
325*9880d681SAndroid Build Coastguard Worker     // Create our live global variable list.
326*9880d681SAndroid Build Coastguard Worker     bool GlobalVariableChange = false;
327*9880d681SAndroid Build Coastguard Worker     for (DIGlobalVariable *DIG : DIC->getGlobalVariables()) {
328*9880d681SAndroid Build Coastguard Worker       // Make sure we only visit each global variable only once.
329*9880d681SAndroid Build Coastguard Worker       if (!VisitedSet.insert(DIG).second)
330*9880d681SAndroid Build Coastguard Worker         continue;
331*9880d681SAndroid Build Coastguard Worker 
332*9880d681SAndroid Build Coastguard Worker       // If the global variable referenced by DIG is not null, the global
333*9880d681SAndroid Build Coastguard Worker       // variable is live.
334*9880d681SAndroid Build Coastguard Worker       if (DIG->getVariable())
335*9880d681SAndroid Build Coastguard Worker         LiveGlobalVariables.push_back(DIG);
336*9880d681SAndroid Build Coastguard Worker       else
337*9880d681SAndroid Build Coastguard Worker         GlobalVariableChange = true;
338*9880d681SAndroid Build Coastguard Worker     }
339*9880d681SAndroid Build Coastguard Worker 
340*9880d681SAndroid Build Coastguard Worker     // If we found dead global variables, replace the current global
341*9880d681SAndroid Build Coastguard Worker     // variable list with our new live global variable list.
342*9880d681SAndroid Build Coastguard Worker     if (GlobalVariableChange) {
343*9880d681SAndroid Build Coastguard Worker       DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables));
344*9880d681SAndroid Build Coastguard Worker       Changed = true;
345*9880d681SAndroid Build Coastguard Worker     }
346*9880d681SAndroid Build Coastguard Worker 
347*9880d681SAndroid Build Coastguard Worker     // Reset lists for the next iteration.
348*9880d681SAndroid Build Coastguard Worker     LiveSubprograms.clear();
349*9880d681SAndroid Build Coastguard Worker     LiveGlobalVariables.clear();
350*9880d681SAndroid Build Coastguard Worker   }
351*9880d681SAndroid Build Coastguard Worker 
352*9880d681SAndroid Build Coastguard Worker   return Changed;
353*9880d681SAndroid Build Coastguard Worker }
354