bool StripExternals::runOnModule(Module &M) { bool Changed = false; for (Module::iterator I = M.begin(); I != M.end(); ) { if (I->hasAvailableExternallyLinkage()) { assert(!I->isDeclaration()&&"Declarations can't be available_externally"); Changed = true; ++NumFunctions; if (I->use_empty()) { DEBUG(errs() << "Deleting function: " << *I); Module::iterator todelete = I; ++I; todelete->eraseFromParent(); continue; } else { I->deleteBody(); DEBUG(errs() << "Deleted function body: " << *I); } } ++I; } for (Module::global_iterator I = M.global_begin(); I != M.global_end(); ) { if (I->hasAvailableExternallyLinkage()) { assert(!I->isDeclaration()&&"Declarations can't be available_externally"); Changed = true; ++NumVariables; if (I->use_empty()) { DEBUG(errs() << "Deleting global: " << *I); Module::global_iterator todelete = I; ++I; todelete->eraseFromParent(); continue; } else { I->setInitializer(0); I->setLinkage(GlobalValue::ExternalLinkage); DEBUG(errs() << "Deleted initializer: " << *I); } } ++I; } return Changed; }
bool GlobalDCE::runOnModule(Module &M) { bool Changed = false; // Loop over the module, adding globals which are obviously necessary. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Functions with external linkage are needed if they have a body if (!I->isDiscardableIfUnused() && !I->isDeclaration() && !I->hasAvailableExternallyLinkage()) GlobalIsNeeded(I); } for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Externally visible & appending globals are needed, if they have an // initializer. if (!I->isDiscardableIfUnused() && !I->isDeclaration() && !I->hasAvailableExternallyLinkage()) GlobalIsNeeded(I); } for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Externally visible aliases are needed. if (!I->isDiscardableIfUnused()) GlobalIsNeeded(I); } // Now that all globals which are needed are in the AliveGlobals set, we loop // through the program, deleting those which are not alive. // // The first pass is to drop initializers of global variables which are dead. std::vector<GlobalVariable*> DeadGlobalVars; // Keep track of dead globals for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadGlobalVars.push_back(I); // Keep track of dead globals I->setInitializer(0); } // The second pass drops the bodies of functions which are dead... std::vector<Function*> DeadFunctions; for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadFunctions.push_back(I); // Keep track of dead globals if (!I->isDeclaration()) I->deleteBody(); } // The third pass drops targets of aliases which are dead... std::vector<GlobalAlias*> DeadAliases; for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadAliases.push_back(I); I->setAliasee(0); } if (!DeadFunctions.empty()) { // Now that all interferences have been dropped, delete the actual objects // themselves. for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadFunctions[i]); M.getFunctionList().erase(DeadFunctions[i]); } NumFunctions += DeadFunctions.size(); Changed = true; } if (!DeadGlobalVars.empty()) { for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadGlobalVars[i]); M.getGlobalList().erase(DeadGlobalVars[i]); } NumVariables += DeadGlobalVars.size(); Changed = true; } // Now delete any dead aliases. if (!DeadAliases.empty()) { for (unsigned i = 0, e = DeadAliases.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadAliases[i]); M.getAliasList().erase(DeadAliases[i]); } NumAliases += DeadAliases.size(); Changed = true; } // Make sure that all memory is released AliveGlobals.clear(); return Changed; }
bool DelinkPass::runOnModule(Module& M) { if(DelinkExcept.size()) { std::ifstream RFI(DelinkExcept.c_str()); DenseSet<GlobalValue*> Keep; while(!RFI.eof()) { std::string line; std::getline(RFI, line); trim(line); if(line.empty()) continue; GlobalValue* GV = M.getNamedValue(line); if(!GV) { errs() << "Warning: Skipped " << line << "\n"; continue; } Keep.insert(GV); } for(Module::iterator it = M.begin(), itend = M.end(); it != itend; ++it) { if(!Keep.count(it)) it->deleteBody(); } } else { std::ifstream RFI(DelinkSymbols.c_str()); while(!RFI.eof()) { std::string line; std::getline(RFI, line); trim(line); if(line.empty()) continue; if(line == "__uClibc_main" || line == "__uClibc_main_spec") continue; GlobalValue* GV = M.getNamedValue(line); if(!GV) { errs() << "Warning: Skipped " << line << "\n"; continue; } if(Function* F = dyn_cast<Function>(GV)) F->deleteBody(); } } return true; }