Internalize.cpp revision b576c94c15af9a440f69d9d03c2afead7971118c
1dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner//===-- Internalize.cpp - Mark functions internal -------------------------===//
2b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//
3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//                     The LLVM Compiler Infrastructure
4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//
5b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// This file was developed by the LLVM research group and is distributed under
6b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// the University of Illinois Open Source License. See LICENSE.TXT for details.
7b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//
8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//===----------------------------------------------------------------------===//
9dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner//
10dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner// This pass loops over all of the functions in the input module, looking for a
1155e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner// main function.  If a main function is found, all other functions and all
1255e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner// global variables with initializers are marked as internal.
13dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner//
14dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner//===----------------------------------------------------------------------===//
15dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner
16568ddabc8f9015baf2d42cc425618412972f1b92Chris Lattner#include "llvm/Transforms/IPO.h"
17dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner#include "llvm/Pass.h"
18dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner#include "llvm/Module.h"
19c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include "Support/CommandLine.h"
206806f5614d2ec260fda954c951d33f58e77ed610Chris Lattner#include "Support/Debug.h"
216806f5614d2ec260fda954c951d33f58e77ed610Chris Lattner#include "Support/Statistic.h"
22c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include <fstream>
23c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include <set>
243dec1f272219ee1f8e1499929cdf53f5bc3c2272Chris Lattner
25f629309f74cf1a64aa7fd1cd5784fd7db9a8f59eChris Lattnernamespace {
26a92f696b74a99325026ebbdbffd2a44317e0c10bChris Lattner  Statistic<> NumFunctions("internalize", "Number of functions internalized");
27a92f696b74a99325026ebbdbffd2a44317e0c10bChris Lattner  Statistic<> NumGlobals  ("internalize", "Number of global vars internalized");
2855e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner
29c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner  // APIFile - A file which contains a list of symbols that should not be marked
30c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner  // external.
31c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner  cl::opt<std::string>
32c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner  APIFile("internalize-public-api-file", cl::value_desc("filename"),
332345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner          cl::desc("A file containing list of symbol names to preserve"));
342345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner
352345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner  // APIList - A list of symbols that should not be marked internal.
362345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner  cl::list<std::string>
372345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner  APIList("internalize-public-api-list", cl::value_desc("list"),
3888c7c3295d936c807bc03ff4fd9da4691084f5d8Chris Lattner          cl::desc("A list of symbol names to preserve"),
3988c7c3295d936c807bc03ff4fd9da4691084f5d8Chris Lattner          cl::CommaSeparated);
402345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner
4155e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner  class InternalizePass : public Pass {
42c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner    std::set<std::string> ExternalNames;
43c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner  public:
44c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner    InternalizePass() {
452345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner      if (!APIFile.empty())           // If a filename is specified, use it
46c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner        LoadFile(APIFile.c_str());
472345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner      else                            // Else, if a list is specified, use it.
482345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner        ExternalNames.insert(APIList.begin(), APIList.end());
49c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner    }
5093fbd733e778c2623436ed5a0b9cf7f394407b1aChris Lattner
51c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner    void LoadFile(const char *Filename) {
52c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner      // Load the APIFile...
53c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner      std::ifstream In(Filename);
54c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner      if (!In.good()) {
55c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner        std::cerr << "WARNING: Internalize couldn't load file '" << Filename
562345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner                  << "'!\n";
57c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner        return;   // Do not internalize anything...
58c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner      }
59c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner      while (In) {
60c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner        std::string Symbol;
61c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner        In >> Symbol;
62c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner        if (!Symbol.empty())
63c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner          ExternalNames.insert(Symbol);
64c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner      }
65c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner    }
66c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner
67c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner    virtual bool run(Module &M) {
682345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner      // If no list or file of symbols was specified, check to see if there is a
692345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner      // "main" symbol defined in the module.  If so, use it, otherwise do not
702345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner      // internalize the module, it must be a library or something.
712345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner      //
722345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner      if (ExternalNames.empty()) {
732345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner        Function *MainFunc = M.getMainFunction();
742345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner        if (MainFunc == 0 || MainFunc->isExternal())
752345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner          return false;  // No main found, must be a library...
762345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner
772345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner        // Preserve main, internalize all else.
782345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner        ExternalNames.insert(MainFunc->getName());
792345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner      }
802345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner
8155e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner      bool Changed = false;
8255e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner
8355e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner      // Found a main function, mark all functions not named main as internal.
8455e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner      for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
85c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner        if (!I->isExternal() &&         // Function must be defined here
86c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner            !I->hasInternalLinkage() &&  // Can't already have internal linkage
87c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner            !ExternalNames.count(I->getName())) {// Not marked to keep external?
884ad02e726d9b634372b037d4b352d8b63bb9e849Chris Lattner          I->setLinkage(GlobalValue::InternalLinkage);
8955e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner          Changed = true;
9055e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner          ++NumFunctions;
9155e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner          DEBUG(std::cerr << "Internalizing func " << I->getName() << "\n");
9255e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner        }
9355e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner
9455e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner      // Mark all global variables with initializers as internal as well...
9555e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner      for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
96c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner        if (!I->isExternal() && !I->hasInternalLinkage() &&
97c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner            !ExternalNames.count(I->getName())) {
9881d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner          // Special case handling of the global ctor and dtor list.  When we
9981d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner          // internalize it, we mark it constant, which allows elimination of
10081d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner          // the list if it's empty.
10181d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner          //
10281d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner          if (I->hasAppendingLinkage() && (I->getName() == "llvm.global_ctors"||
10381d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner                                           I->getName() == "llvm.global_dtors"))
10481d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner            I->setConstant(true);
10581d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner
1064ad02e726d9b634372b037d4b352d8b63bb9e849Chris Lattner          I->setLinkage(GlobalValue::InternalLinkage);
10755e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner          Changed = true;
10855e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner          ++NumGlobals;
10955e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner          DEBUG(std::cerr << "Internalizing gvar " << I->getName() << "\n");
11055e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner        }
11155e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner
11255e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner      return Changed;
11355e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner    }
11455e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner  };
115dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner
116c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner  RegisterOpt<InternalizePass> X("internalize", "Internalize Global Symbols");
117f629309f74cf1a64aa7fd1cd5784fd7db9a8f59eChris Lattner} // end anonymous namespace
118f629309f74cf1a64aa7fd1cd5784fd7db9a8f59eChris Lattner
119dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris LattnerPass *createInternalizePass() {
120dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner  return new InternalizePass();
121dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner}
122