Internalize.cpp revision 88c7c3295d936c807bc03ff4fd9da4691084f5d8
1//===-- Internalize.cpp - Mark functions internal -------------------------===//
2//
3// This pass loops over all of the functions in the input module, looking for a
4// main function.  If a main function is found, all other functions and all
5// global variables with initializers are marked as internal.
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/Transforms/IPO.h"
10#include "llvm/Pass.h"
11#include "llvm/Module.h"
12#include "Support/Statistic.h"
13#include "Support/CommandLine.h"
14#include <fstream>
15#include <set>
16
17namespace {
18  Statistic<> NumFunctions("internalize", "Number of functions internalized");
19  Statistic<> NumGlobals  ("internalize", "Number of global vars internalized");
20
21  // APIFile - A file which contains a list of symbols that should not be marked
22  // external.
23  cl::opt<std::string>
24  APIFile("internalize-public-api-file", cl::value_desc("filename"),
25          cl::desc("A file containing list of symbol names to preserve"));
26
27  // APIList - A list of symbols that should not be marked internal.
28  cl::list<std::string>
29  APIList("internalize-public-api-list", cl::value_desc("list"),
30          cl::desc("A list of symbol names to preserve"),
31          cl::CommaSeparated);
32
33  class InternalizePass : public Pass {
34    std::set<std::string> ExternalNames;
35  public:
36    InternalizePass() {
37      if (!APIFile.empty())           // If a filename is specified, use it
38        LoadFile(APIFile.c_str());
39      else                            // Else, if a list is specified, use it.
40        ExternalNames.insert(APIList.begin(), APIList.end());
41    }
42
43    void LoadFile(const char *Filename) {
44      // Load the APIFile...
45      std::ifstream In(Filename);
46      if (!In.good()) {
47        std::cerr << "WARNING: Internalize couldn't load file '" << Filename
48                  << "'!\n";
49        return;   // Do not internalize anything...
50      }
51      while (In) {
52        std::string Symbol;
53        In >> Symbol;
54        if (!Symbol.empty())
55          ExternalNames.insert(Symbol);
56      }
57    }
58
59    virtual bool run(Module &M) {
60      // If no list or file of symbols was specified, check to see if there is a
61      // "main" symbol defined in the module.  If so, use it, otherwise do not
62      // internalize the module, it must be a library or something.
63      //
64      if (ExternalNames.empty()) {
65        Function *MainFunc = M.getMainFunction();
66        if (MainFunc == 0 || MainFunc->isExternal())
67          return false;  // No main found, must be a library...
68
69        // Preserve main, internalize all else.
70        ExternalNames.insert(MainFunc->getName());
71      }
72
73      bool Changed = false;
74
75      // Found a main function, mark all functions not named main as internal.
76      for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
77        if (!I->isExternal() &&         // Function must be defined here
78            !I->hasInternalLinkage() &&  // Can't already have internal linkage
79            !ExternalNames.count(I->getName())) {// Not marked to keep external?
80          I->setLinkage(GlobalValue::InternalLinkage);
81          Changed = true;
82          ++NumFunctions;
83          DEBUG(std::cerr << "Internalizing func " << I->getName() << "\n");
84        }
85
86      // Mark all global variables with initializers as internal as well...
87      for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
88        if (!I->isExternal() && !I->hasInternalLinkage() &&
89            !ExternalNames.count(I->getName())) {
90          I->setLinkage(GlobalValue::InternalLinkage);
91          Changed = true;
92          ++NumGlobals;
93          DEBUG(std::cerr << "Internalizing gvar " << I->getName() << "\n");
94        }
95
96      return Changed;
97    }
98  };
99
100  RegisterOpt<InternalizePass> X("internalize", "Internalize Global Symbols");
101} // end anonymous namespace
102
103Pass *createInternalizePass() {
104  return new InternalizePass();
105}
106