Home | History | Annotate | Download | only in IPO
      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 in the input module, looking for a
     11 // main function.  If a main function is found, all other functions and all
     12 // global variables with initializers are marked as internal.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #define DEBUG_TYPE "internalize"
     17 #include "llvm/Analysis/CallGraph.h"
     18 #include "llvm/Transforms/IPO.h"
     19 #include "llvm/Pass.h"
     20 #include "llvm/Module.h"
     21 #include "llvm/Support/CommandLine.h"
     22 #include "llvm/Support/Debug.h"
     23 #include "llvm/Support/raw_ostream.h"
     24 #include "llvm/ADT/Statistic.h"
     25 #include <fstream>
     26 #include <set>
     27 using namespace llvm;
     28 
     29 STATISTIC(NumAliases  , "Number of aliases internalized");
     30 STATISTIC(NumFunctions, "Number of functions internalized");
     31 STATISTIC(NumGlobals  , "Number of global vars internalized");
     32 
     33 // APIFile - A file which contains a list of symbols that should not be marked
     34 // external.
     35 static cl::opt<std::string>
     36 APIFile("internalize-public-api-file", cl::value_desc("filename"),
     37         cl::desc("A file containing list of symbol names to preserve"));
     38 
     39 // APIList - A list of symbols that should not be marked internal.
     40 static cl::list<std::string>
     41 APIList("internalize-public-api-list", cl::value_desc("list"),
     42         cl::desc("A list of symbol names to preserve"),
     43         cl::CommaSeparated);
     44 
     45 namespace {
     46   class InternalizePass : public ModulePass {
     47     std::set<std::string> ExternalNames;
     48     /// If no api symbols were specified and a main function is defined,
     49     /// assume the main function is the only API
     50     bool AllButMain;
     51   public:
     52     static char ID; // Pass identification, replacement for typeid
     53     explicit InternalizePass(bool AllButMain = true);
     54     explicit InternalizePass(const std::vector <const char *>& exportList);
     55     void LoadFile(const char *Filename);
     56     virtual bool runOnModule(Module &M);
     57 
     58     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
     59       AU.setPreservesCFG();
     60       AU.addPreserved<CallGraph>();
     61     }
     62   };
     63 } // end anonymous namespace
     64 
     65 char InternalizePass::ID = 0;
     66 INITIALIZE_PASS(InternalizePass, "internalize",
     67                 "Internalize Global Symbols", false, false)
     68 
     69 InternalizePass::InternalizePass(bool AllButMain)
     70   : ModulePass(ID), AllButMain(AllButMain){
     71   initializeInternalizePassPass(*PassRegistry::getPassRegistry());
     72   if (!APIFile.empty())           // If a filename is specified, use it.
     73     LoadFile(APIFile.c_str());
     74   if (!APIList.empty())           // If a list is specified, use it as well.
     75     ExternalNames.insert(APIList.begin(), APIList.end());
     76 }
     77 
     78 InternalizePass::InternalizePass(const std::vector<const char *>&exportList)
     79   : ModulePass(ID), AllButMain(false){
     80   initializeInternalizePassPass(*PassRegistry::getPassRegistry());
     81   for(std::vector<const char *>::const_iterator itr = exportList.begin();
     82         itr != exportList.end(); itr++) {
     83     ExternalNames.insert(*itr);
     84   }
     85 }
     86 
     87 void InternalizePass::LoadFile(const char *Filename) {
     88   // Load the APIFile...
     89   std::ifstream In(Filename);
     90   if (!In.good()) {
     91     errs() << "WARNING: Internalize couldn't load file '" << Filename
     92          << "'! Continuing as if it's empty.\n";
     93     return; // Just continue as if the file were empty
     94   }
     95   while (In) {
     96     std::string Symbol;
     97     In >> Symbol;
     98     if (!Symbol.empty())
     99       ExternalNames.insert(Symbol);
    100   }
    101 }
    102 
    103 bool InternalizePass::runOnModule(Module &M) {
    104   CallGraph *CG = getAnalysisIfAvailable<CallGraph>();
    105   CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0;
    106 
    107   if (ExternalNames.empty()) {
    108     // Return if we're not in 'all but main' mode and have no external api
    109     if (!AllButMain)
    110       return false;
    111     // If no list or file of symbols was specified, check to see if there is a
    112     // "main" symbol defined in the module.  If so, use it, otherwise do not
    113     // internalize the module, it must be a library or something.
    114     //
    115     Function *MainFunc = M.getFunction("main");
    116     if (MainFunc == 0 || MainFunc->isDeclaration())
    117       return false;  // No main found, must be a library...
    118 
    119     // Preserve main, internalize all else.
    120     ExternalNames.insert(MainFunc->getName());
    121   }
    122 
    123   bool Changed = false;
    124 
    125   // Never internalize functions which code-gen might insert.
    126   // FIXME: We should probably add this (and the __stack_chk_guard) via some
    127   // type of call-back in CodeGen.
    128   ExternalNames.insert("__stack_chk_fail");
    129 
    130   // Mark all functions not in the api as internal.
    131   // FIXME: maybe use private linkage?
    132   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    133     if (!I->isDeclaration() &&         // Function must be defined here
    134         // Available externally is really just a "declaration with a body".
    135         !I->hasAvailableExternallyLinkage() &&
    136         !I->hasLocalLinkage() &&  // Can't already have internal linkage
    137         !ExternalNames.count(I->getName())) {// Not marked to keep external?
    138       I->setLinkage(GlobalValue::InternalLinkage);
    139       // Remove a callgraph edge from the external node to this function.
    140       if (ExternalNode) ExternalNode->removeOneAbstractEdgeTo((*CG)[I]);
    141       Changed = true;
    142       ++NumFunctions;
    143       DEBUG(dbgs() << "Internalizing func " << I->getName() << "\n");
    144     }
    145 
    146   // Never internalize the llvm.used symbol.  It is used to implement
    147   // attribute((used)).
    148   // FIXME: Shouldn't this just filter on llvm.metadata section??
    149   ExternalNames.insert("llvm.used");
    150   ExternalNames.insert("llvm.compiler.used");
    151 
    152   // Never internalize anchors used by the machine module info, else the info
    153   // won't find them.  (see MachineModuleInfo.)
    154   ExternalNames.insert("llvm.global_ctors");
    155   ExternalNames.insert("llvm.global_dtors");
    156   ExternalNames.insert("llvm.global.annotations");
    157 
    158   // Never internalize symbols code-gen inserts.
    159   ExternalNames.insert("__stack_chk_guard");
    160 
    161   // Mark all global variables with initializers that are not in the api as
    162   // internal as well.
    163   // FIXME: maybe use private linkage?
    164   for (Module::global_iterator I = M.global_begin(), E = M.global_end();
    165        I != E; ++I)
    166     if (!I->isDeclaration() && !I->hasLocalLinkage() &&
    167         // Available externally is really just a "declaration with a body".
    168         !I->hasAvailableExternallyLinkage() &&
    169         !ExternalNames.count(I->getName())) {
    170       I->setLinkage(GlobalValue::InternalLinkage);
    171       Changed = true;
    172       ++NumGlobals;
    173       DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n");
    174     }
    175 
    176   // Mark all aliases that are not in the api as internal as well.
    177   for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
    178        I != E; ++I)
    179     if (!I->isDeclaration() && !I->hasInternalLinkage() &&
    180         // Available externally is really just a "declaration with a body".
    181         !I->hasAvailableExternallyLinkage() &&
    182         !ExternalNames.count(I->getName())) {
    183       I->setLinkage(GlobalValue::InternalLinkage);
    184       Changed = true;
    185       ++NumAliases;
    186       DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n");
    187     }
    188 
    189   return Changed;
    190 }
    191 
    192 ModulePass *llvm::createInternalizePass(bool AllButMain) {
    193   return new InternalizePass(AllButMain);
    194 }
    195 
    196 ModulePass *llvm::createInternalizePass(const std::vector <const char *> &el) {
    197   return new InternalizePass(el);
    198 }
    199