1 //===-- Internalize.cpp - Mark functions internal -------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This pass loops over all of the functions and variables in the input module. 11 // If the function or variable is not in the list of external names given to 12 // the pass it is marked as internal. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #define DEBUG_TYPE "internalize" 17 #include "llvm/Transforms/IPO.h" 18 #include "llvm/ADT/SmallPtrSet.h" 19 #include "llvm/ADT/Statistic.h" 20 #include "llvm/Analysis/CallGraph.h" 21 #include "llvm/IR/Module.h" 22 #include "llvm/Pass.h" 23 #include "llvm/Support/CommandLine.h" 24 #include "llvm/Support/Debug.h" 25 #include "llvm/Support/raw_ostream.h" 26 #include "llvm/Transforms/Utils/ModuleUtils.h" 27 #include <fstream> 28 #include <set> 29 using namespace llvm; 30 31 STATISTIC(NumAliases , "Number of aliases internalized"); 32 STATISTIC(NumFunctions, "Number of functions internalized"); 33 STATISTIC(NumGlobals , "Number of global vars internalized"); 34 35 // APIFile - A file which contains a list of symbols that should not be marked 36 // external. 37 static cl::opt<std::string> 38 APIFile("internalize-public-api-file", cl::value_desc("filename"), 39 cl::desc("A file containing list of symbol names to preserve")); 40 41 // APIList - A list of symbols that should not be marked internal. 42 static cl::list<std::string> 43 APIList("internalize-public-api-list", cl::value_desc("list"), 44 cl::desc("A list of symbol names to preserve"), 45 cl::CommaSeparated); 46 47 static cl::list<std::string> 48 DSOList("internalize-dso-list", cl::value_desc("list"), 49 cl::desc("A list of symbol names need for a dso symbol table"), 50 cl::CommaSeparated); 51 52 namespace { 53 class InternalizePass : public ModulePass { 54 std::set<std::string> ExternalNames; 55 std::set<std::string> DSONames; 56 public: 57 static char ID; // Pass identification, replacement for typeid 58 explicit InternalizePass(); 59 explicit InternalizePass(ArrayRef<const char *> ExportList, 60 ArrayRef<const char *> DSOList); 61 void LoadFile(const char *Filename); 62 virtual bool runOnModule(Module &M); 63 64 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 65 AU.setPreservesCFG(); 66 AU.addPreserved<CallGraph>(); 67 } 68 }; 69 } // end anonymous namespace 70 71 char InternalizePass::ID = 0; 72 INITIALIZE_PASS(InternalizePass, "internalize", 73 "Internalize Global Symbols", false, false) 74 75 InternalizePass::InternalizePass() 76 : ModulePass(ID) { 77 initializeInternalizePassPass(*PassRegistry::getPassRegistry()); 78 if (!APIFile.empty()) // If a filename is specified, use it. 79 LoadFile(APIFile.c_str()); 80 ExternalNames.insert(APIList.begin(), APIList.end()); 81 DSONames.insert(DSOList.begin(), DSOList.end()); 82 } 83 84 InternalizePass::InternalizePass(ArrayRef<const char *> ExportList, 85 ArrayRef<const char *> DSOList) 86 : ModulePass(ID){ 87 initializeInternalizePassPass(*PassRegistry::getPassRegistry()); 88 for(ArrayRef<const char *>::const_iterator itr = ExportList.begin(); 89 itr != ExportList.end(); itr++) { 90 ExternalNames.insert(*itr); 91 } 92 for(ArrayRef<const char *>::const_iterator itr = DSOList.begin(); 93 itr != DSOList.end(); itr++) { 94 DSONames.insert(*itr); 95 } 96 } 97 98 void InternalizePass::LoadFile(const char *Filename) { 99 // Load the APIFile... 100 std::ifstream In(Filename); 101 if (!In.good()) { 102 errs() << "WARNING: Internalize couldn't load file '" << Filename 103 << "'! Continuing as if it's empty.\n"; 104 return; // Just continue as if the file were empty 105 } 106 while (In) { 107 std::string Symbol; 108 In >> Symbol; 109 if (!Symbol.empty()) 110 ExternalNames.insert(Symbol); 111 } 112 } 113 114 static bool shouldInternalize(const GlobalValue &GV, 115 const std::set<std::string> &ExternalNames, 116 const std::set<std::string> &DSONames) { 117 // Function must be defined here 118 if (GV.isDeclaration()) 119 return false; 120 121 // Available externally is really just a "declaration with a body". 122 if (GV.hasAvailableExternallyLinkage()) 123 return false; 124 125 // Already has internal linkage 126 if (GV.hasLocalLinkage()) 127 return false; 128 129 // Marked to keep external? 130 if (ExternalNames.count(GV.getName())) 131 return false; 132 133 // Not needed for the symbol table? 134 if (!DSONames.count(GV.getName())) 135 return true; 136 137 // Not a linkonce. Someone can depend on it being on the symbol table. 138 if (!GV.hasLinkOnceLinkage()) 139 return false; 140 141 // The address is not important, we can hide it. 142 if (GV.hasUnnamedAddr()) 143 return true; 144 145 // FIXME: Check if the address is used. 146 return false; 147 } 148 149 bool InternalizePass::runOnModule(Module &M) { 150 CallGraph *CG = getAnalysisIfAvailable<CallGraph>(); 151 CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0; 152 bool Changed = false; 153 154 SmallPtrSet<GlobalValue *, 8> Used; 155 collectUsedGlobalVariables(M, Used, false); 156 157 // We must assume that globals in llvm.used have a reference that not even 158 // the linker can see, so we don't internalize them. 159 // For llvm.compiler.used the situation is a bit fuzzy. The assembler and 160 // linker can drop those symbols. If this pass is running as part of LTO, 161 // one might think that it could just drop llvm.compiler.used. The problem 162 // is that even in LTO llvm doesn't see every reference. For example, 163 // we don't see references from function local inline assembly. To be 164 // conservative, we internalize symbols in llvm.compiler.used, but we 165 // keep llvm.compiler.used so that the symbol is not deleted by llvm. 166 for (SmallPtrSet<GlobalValue *, 8>::iterator I = Used.begin(), E = Used.end(); 167 I != E; ++I) { 168 GlobalValue *V = *I; 169 ExternalNames.insert(V->getName()); 170 } 171 172 // Mark all functions not in the api as internal. 173 // FIXME: maybe use private linkage? 174 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { 175 if (!shouldInternalize(*I, ExternalNames, DSONames)) 176 continue; 177 178 I->setLinkage(GlobalValue::InternalLinkage); 179 180 if (ExternalNode) 181 // Remove a callgraph edge from the external node to this function. 182 ExternalNode->removeOneAbstractEdgeTo((*CG)[I]); 183 184 Changed = true; 185 ++NumFunctions; 186 DEBUG(dbgs() << "Internalizing func " << I->getName() << "\n"); 187 } 188 189 // Never internalize the llvm.used symbol. It is used to implement 190 // attribute((used)). 191 // FIXME: Shouldn't this just filter on llvm.metadata section?? 192 ExternalNames.insert("llvm.used"); 193 ExternalNames.insert("llvm.compiler.used"); 194 195 // Never internalize anchors used by the machine module info, else the info 196 // won't find them. (see MachineModuleInfo.) 197 ExternalNames.insert("llvm.global_ctors"); 198 ExternalNames.insert("llvm.global_dtors"); 199 ExternalNames.insert("llvm.global.annotations"); 200 201 // Never internalize symbols code-gen inserts. 202 // FIXME: We should probably add this (and the __stack_chk_guard) via some 203 // type of call-back in CodeGen. 204 ExternalNames.insert("__stack_chk_fail"); 205 ExternalNames.insert("__stack_chk_guard"); 206 207 // Mark all global variables with initializers that are not in the api as 208 // internal as well. 209 // FIXME: maybe use private linkage? 210 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); 211 I != E; ++I) { 212 if (!shouldInternalize(*I, ExternalNames, DSONames)) 213 continue; 214 215 I->setLinkage(GlobalValue::InternalLinkage); 216 Changed = true; 217 ++NumGlobals; 218 DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n"); 219 } 220 221 // Mark all aliases that are not in the api as internal as well. 222 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); 223 I != E; ++I) { 224 if (!shouldInternalize(*I, ExternalNames, DSONames)) 225 continue; 226 227 I->setLinkage(GlobalValue::InternalLinkage); 228 Changed = true; 229 ++NumAliases; 230 DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n"); 231 } 232 233 return Changed; 234 } 235 236 ModulePass *llvm::createInternalizePass() { 237 return new InternalizePass(); 238 } 239 240 ModulePass *llvm::createInternalizePass(ArrayRef<const char *> ExportList, 241 ArrayRef<const char *> DSOList) { 242 return new InternalizePass(ExportList, DSOList); 243 } 244