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