LLVM API Documentation

Internalize.cpp
Go to the documentation of this file.
00001 //===-- Internalize.cpp - Mark functions internal -------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This pass loops over all of the functions and variables in the input module.
00011 // If the function or variable is not in the list of external names given to
00012 // the pass it is marked as internal.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #define DEBUG_TYPE "internalize"
00017 #include "llvm/Transforms/IPO.h"
00018 #include "llvm/ADT/Statistic.h"
00019 #include "llvm/Analysis/CallGraph.h"
00020 #include "llvm/IR/Module.h"
00021 #include "llvm/Pass.h"
00022 #include "llvm/Support/CommandLine.h"
00023 #include "llvm/Support/Debug.h"
00024 #include "llvm/Support/raw_ostream.h"
00025 #include <fstream>
00026 #include <set>
00027 using namespace llvm;
00028 
00029 STATISTIC(NumAliases  , "Number of aliases internalized");
00030 STATISTIC(NumFunctions, "Number of functions internalized");
00031 STATISTIC(NumGlobals  , "Number of global vars internalized");
00032 
00033 // APIFile - A file which contains a list of symbols that should not be marked
00034 // external.
00035 static cl::opt<std::string>
00036 APIFile("internalize-public-api-file", cl::value_desc("filename"),
00037         cl::desc("A file containing list of symbol names to preserve"));
00038 
00039 // APIList - A list of symbols that should not be marked internal.
00040 static cl::list<std::string>
00041 APIList("internalize-public-api-list", cl::value_desc("list"),
00042         cl::desc("A list of symbol names to preserve"),
00043         cl::CommaSeparated);
00044 
00045 namespace {
00046   class InternalizePass : public ModulePass {
00047     std::set<std::string> ExternalNames;
00048   public:
00049     static char ID; // Pass identification, replacement for typeid
00050     explicit InternalizePass();
00051     explicit InternalizePass(ArrayRef<const char *> exportList);
00052     void LoadFile(const char *Filename);
00053     void ClearExportList();
00054     void AddToExportList(const std::string &val);
00055     virtual bool runOnModule(Module &M);
00056 
00057     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
00058       AU.setPreservesCFG();
00059       AU.addPreserved<CallGraph>();
00060     }
00061   };
00062 } // end anonymous namespace
00063 
00064 char InternalizePass::ID = 0;
00065 INITIALIZE_PASS(InternalizePass, "internalize",
00066                 "Internalize Global Symbols", false, false)
00067 
00068 InternalizePass::InternalizePass()
00069   : ModulePass(ID) {
00070   initializeInternalizePassPass(*PassRegistry::getPassRegistry());
00071   if (!APIFile.empty())           // If a filename is specified, use it.
00072     LoadFile(APIFile.c_str());
00073   if (!APIList.empty())           // If a list is specified, use it as well.
00074     ExternalNames.insert(APIList.begin(), APIList.end());
00075 }
00076 
00077 InternalizePass::InternalizePass(ArrayRef<const char *> exportList)
00078   : ModulePass(ID){
00079   initializeInternalizePassPass(*PassRegistry::getPassRegistry());
00080   for(ArrayRef<const char *>::const_iterator itr = exportList.begin();
00081         itr != exportList.end(); itr++) {
00082     ExternalNames.insert(*itr);
00083   }
00084 }
00085 
00086 void InternalizePass::LoadFile(const char *Filename) {
00087   // Load the APIFile...
00088   std::ifstream In(Filename);
00089   if (!In.good()) {
00090     errs() << "WARNING: Internalize couldn't load file '" << Filename
00091          << "'! Continuing as if it's empty.\n";
00092     return; // Just continue as if the file were empty
00093   }
00094   while (In) {
00095     std::string Symbol;
00096     In >> Symbol;
00097     if (!Symbol.empty())
00098       ExternalNames.insert(Symbol);
00099   }
00100 }
00101 
00102 void InternalizePass::ClearExportList() {
00103   ExternalNames.clear();
00104 }
00105 
00106 void InternalizePass::AddToExportList(const std::string &val) {
00107   ExternalNames.insert(val);
00108 }
00109 
00110 bool InternalizePass::runOnModule(Module &M) {
00111   CallGraph *CG = getAnalysisIfAvailable<CallGraph>();
00112   CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0;
00113   bool Changed = false;
00114 
00115   // Never internalize functions which code-gen might insert.
00116   // FIXME: We should probably add this (and the __stack_chk_guard) via some
00117   // type of call-back in CodeGen.
00118   ExternalNames.insert("__stack_chk_fail");
00119 
00120   // Mark all functions not in the api as internal.
00121   // FIXME: maybe use private linkage?
00122   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
00123     if (!I->isDeclaration() &&         // Function must be defined here
00124         // Available externally is really just a "declaration with a body".
00125         !I->hasAvailableExternallyLinkage() &&
00126         !I->hasLocalLinkage() &&  // Can't already have internal linkage
00127         !ExternalNames.count(I->getName())) {// Not marked to keep external?
00128       I->setLinkage(GlobalValue::InternalLinkage);
00129       // Remove a callgraph edge from the external node to this function.
00130       if (ExternalNode) ExternalNode->removeOneAbstractEdgeTo((*CG)[I]);
00131       Changed = true;
00132       ++NumFunctions;
00133       DEBUG(dbgs() << "Internalizing func " << I->getName() << "\n");
00134     }
00135 
00136   // Never internalize the llvm.used symbol.  It is used to implement
00137   // attribute((used)).
00138   // FIXME: Shouldn't this just filter on llvm.metadata section??
00139   ExternalNames.insert("llvm.used");
00140   ExternalNames.insert("llvm.compiler.used");
00141 
00142   // Never internalize anchors used by the machine module info, else the info
00143   // won't find them.  (see MachineModuleInfo.)
00144   ExternalNames.insert("llvm.global_ctors");
00145   ExternalNames.insert("llvm.global_dtors");
00146   ExternalNames.insert("llvm.global.annotations");
00147 
00148   // Never internalize symbols code-gen inserts.
00149   ExternalNames.insert("__stack_chk_guard");
00150 
00151   // Mark all global variables with initializers that are not in the api as
00152   // internal as well.
00153   // FIXME: maybe use private linkage?
00154   for (Module::global_iterator I = M.global_begin(), E = M.global_end();
00155        I != E; ++I)
00156     if (!I->isDeclaration() && !I->hasLocalLinkage() &&
00157         // Available externally is really just a "declaration with a body".
00158         !I->hasAvailableExternallyLinkage() &&
00159         !ExternalNames.count(I->getName())) {
00160       I->setLinkage(GlobalValue::InternalLinkage);
00161       Changed = true;
00162       ++NumGlobals;
00163       DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n");
00164     }
00165 
00166   // Mark all aliases that are not in the api as internal as well.
00167   for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
00168        I != E; ++I)
00169     if (!I->isDeclaration() && !I->hasInternalLinkage() &&
00170         // Available externally is really just a "declaration with a body".
00171         !I->hasAvailableExternallyLinkage() &&
00172         !ExternalNames.count(I->getName())) {
00173       I->setLinkage(GlobalValue::InternalLinkage);
00174       Changed = true;
00175       ++NumAliases;
00176       DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n");
00177     }
00178 
00179   return Changed;
00180 }
00181 
00182 ModulePass *llvm::createInternalizePass() {
00183   return new InternalizePass();
00184 }
00185 
00186 ModulePass *llvm::createInternalizePass(ArrayRef<const char *> el) {
00187   return new InternalizePass(el);
00188 }