Internalize.cpp revision 2345d71853e75fd56a8ca66d40bf36eba0a9edb6
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
32  class InternalizePass : public Pass {
33    std::set<std::string> ExternalNames;
34  public:
35    InternalizePass() {
36      if (!APIFile.empty())           // If a filename is specified, use it
37        LoadFile(APIFile.c_str());
38      else                            // Else, if a list is specified, use it.
39        ExternalNames.insert(APIList.begin(), APIList.end());
40    }
41
42    void LoadFile(const char *Filename) {
43      // Load the APIFile...
44      std::ifstream In(Filename);
45      if (!In.good()) {
46        std::cerr << "WARNING: Internalize couldn't load file '" << Filename
47                  << "'!\n";
48        return;   // Do not internalize anything...
49      }
50      while (In) {
51        std::string Symbol;
52        In >> Symbol;
53        if (!Symbol.empty())
54          ExternalNames.insert(Symbol);
55      }
56    }
57
58    virtual bool run(Module &M) {
59      // If no list or file of symbols was specified, check to see if there is a
60      // "main" symbol defined in the module.  If so, use it, otherwise do not
61      // internalize the module, it must be a library or something.
62      //
63      if (ExternalNames.empty()) {
64        Function *MainFunc = M.getMainFunction();
65        if (MainFunc == 0 || MainFunc->isExternal())
66          return false;  // No main found, must be a library...
67
68        // Preserve main, internalize all else.
69        ExternalNames.insert(MainFunc->getName());
70      }
71
72      bool Changed = false;
73
74      // Found a main function, mark all functions not named main as internal.
75      for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
76        if (!I->isExternal() &&         // Function must be defined here
77            !I->hasInternalLinkage() &&  // Can't already have internal linkage
78            !ExternalNames.count(I->getName())) {// Not marked to keep external?
79          I->setLinkage(GlobalValue::InternalLinkage);
80          Changed = true;
81          ++NumFunctions;
82          DEBUG(std::cerr << "Internalizing func " << I->getName() << "\n");
83        }
84
85      // Mark all global variables with initializers as internal as well...
86      for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
87        if (!I->isExternal() && !I->hasInternalLinkage() &&
88            !ExternalNames.count(I->getName())) {
89          I->setLinkage(GlobalValue::InternalLinkage);
90          Changed = true;
91          ++NumGlobals;
92          DEBUG(std::cerr << "Internalizing gvar " << I->getName() << "\n");
93        }
94
95      return Changed;
96    }
97  };
98
99  RegisterOpt<InternalizePass> X("internalize", "Internalize Global Symbols");
100} // end anonymous namespace
101
102Pass *createInternalizePass() {
103  return new InternalizePass();
104}
105