Internalize.cpp revision a2582da44dbe7204aac49cdaeccfd4e77ff7c408
1dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner//===-- Internalize.cpp - Mark functions internal -------------------------===//
2fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman//
3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//                     The LLVM Compiler Infrastructure
4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman//
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
1686453c52ba02e743d29c08456e51006500041456Chris Lattner#define DEBUG_TYPE "internalize"
17a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands#include "llvm/Analysis/CallGraph.h"
18568ddabc8f9015baf2d42cc425618412972f1b92Chris Lattner#include "llvm/Transforms/IPO.h"
19dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner#include "llvm/Pass.h"
20dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner#include "llvm/Module.h"
21551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/CommandLine.h"
229133fe28954d498fc4de13064c7d65bd811de02cReid Spencer#include "llvm/Support/Compiler.h"
23551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/Debug.h"
24551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/ADT/Statistic.h"
25c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include <fstream>
26c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include <set>
271e2385b941242f2f96398dc62767420622856149Chris Lattnerusing namespace llvm;
28d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
2986453c52ba02e743d29c08456e51006500041456Chris LattnerSTATISTIC(NumFunctions, "Number of functions internalized");
3086453c52ba02e743d29c08456e51006500041456Chris LattnerSTATISTIC(NumGlobals  , "Number of global vars internalized");
3186453c52ba02e743d29c08456e51006500041456Chris Lattner
32844731a7f1909f55935e3514c9e713a62d67662eDan Gohman// APIFile - A file which contains a list of symbols that should not be marked
33844731a7f1909f55935e3514c9e713a62d67662eDan Gohman// external.
34844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanstatic cl::opt<std::string>
35844731a7f1909f55935e3514c9e713a62d67662eDan GohmanAPIFile("internalize-public-api-file", cl::value_desc("filename"),
36844731a7f1909f55935e3514c9e713a62d67662eDan Gohman        cl::desc("A file containing list of symbol names to preserve"));
372345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner
38844731a7f1909f55935e3514c9e713a62d67662eDan Gohman// APIList - A list of symbols that should not be marked internal.
39844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanstatic cl::list<std::string>
40844731a7f1909f55935e3514c9e713a62d67662eDan GohmanAPIList("internalize-public-api-list", cl::value_desc("list"),
41844731a7f1909f55935e3514c9e713a62d67662eDan Gohman        cl::desc("A list of symbol names to preserve"),
42844731a7f1909f55935e3514c9e713a62d67662eDan Gohman        cl::CommaSeparated);
43fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman
44844731a7f1909f55935e3514c9e713a62d67662eDan Gohmannamespace {
459133fe28954d498fc4de13064c7d65bd811de02cReid Spencer  class VISIBILITY_HIDDEN InternalizePass : public ModulePass {
46c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner    std::set<std::string> ExternalNames;
47ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    /// If no api symbols were specified and a main function is defined,
48ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    /// assume the main function is the only API
49ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    bool AllButMain;
50c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner  public:
51ecd94c804a563f2a86572dcf1d2e81f397e19daaNick Lewycky    static char ID; // Pass identification, replacement for typeid
524e78908b9453edf7d0907d4811c469a630aff560Matthijs Kooijman    explicit InternalizePass(bool AllButMain = true);
53c2bbfc18e9adbbdcf5b3375d8d25e2452f7df7f1Dan Gohman    explicit InternalizePass(const std::vector <const char *>& exportList);
544eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    void LoadFile(const char *Filename);
554eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    virtual bool runOnModule(Module &M);
560483d018c4f15f206a83364e498957127e74f431Nuno Lopes
570483d018c4f15f206a83364e498957127e74f431Nuno Lopes    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
580483d018c4f15f206a83364e498957127e74f431Nuno Lopes      AU.setPreservesCFG();
59a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands      AU.addPreserved<CallGraph>();
600483d018c4f15f206a83364e498957127e74f431Nuno Lopes    }
614eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  };
624eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner} // end anonymous namespace
6393fbd733e778c2623436ed5a0b9cf7f394407b1aChris Lattner
64844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanchar InternalizePass::ID = 0;
65844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanstatic RegisterPass<InternalizePass>
66844731a7f1909f55935e3514c9e713a62d67662eDan GohmanX("internalize", "Internalize Global Symbols");
67844731a7f1909f55935e3514c9e713a62d67662eDan Gohman
68ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang PatelInternalizePass::InternalizePass(bool AllButMain)
69ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman  : ModulePass(&ID), AllButMain(AllButMain){
70ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  if (!APIFile.empty())           // If a filename is specified, use it.
714eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    LoadFile(APIFile.c_str());
72ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  if (!APIList.empty())           // If a list is specified, use it as well.
734eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    ExternalNames.insert(APIList.begin(), APIList.end());
744eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner}
75c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner
7656eac5f6f78b2aec32179d13115f57cd4bcc5675Devang PatelInternalizePass::InternalizePass(const std::vector<const char *>&exportList)
77ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman  : ModulePass(&ID), AllButMain(false){
78753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel  for(std::vector<const char *>::const_iterator itr = exportList.begin();
79bed2946a96ecb15b0b636fa74cb26ce61b1c648eAnton Korobeynikov        itr != exportList.end(); itr++) {
80753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel    ExternalNames.insert(*itr);
81753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel  }
82753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel}
83753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel
844eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnervoid InternalizePass::LoadFile(const char *Filename) {
854eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  // Load the APIFile...
864eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  std::ifstream In(Filename);
874eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  if (!In.good()) {
88ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    cerr << "WARNING: Internalize couldn't load file '" << Filename
89ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel         << "'! Continuing as if it's empty.\n";
90ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    return; // Just continue as if the file were empty
914eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  }
924eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  while (In) {
934eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    std::string Symbol;
944eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    In >> Symbol;
954eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    if (!Symbol.empty())
964eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      ExternalNames.insert(Symbol);
974eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  }
984eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner}
994eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
1004eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerbool InternalizePass::runOnModule(Module &M) {
101a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands  CallGraph *CG = getAnalysisToUpdate<CallGraph>();
102a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands  CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0;
103a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands
1044eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  if (ExternalNames.empty()) {
105ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    // Return if we're not in 'all but main' mode and have no external api
106ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    if (!AllButMain)
107ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel      return false;
108ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    // If no list or file of symbols was specified, check to see if there is a
109ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    // "main" symbol defined in the module.  If so, use it, otherwise do not
110ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    // internalize the module, it must be a library or something.
111ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    //
112688b0490e22eb67623f5aaa24406209be74efcb2Reid Spencer    Function *MainFunc = M.getFunction("main");
1135cbf985dcbc89fba3208e7baf8b6f488b06d3ec9Reid Spencer    if (MainFunc == 0 || MainFunc->isDeclaration())
1144eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      return false;  // No main found, must be a library...
1154eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
1164eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    // Preserve main, internalize all else.
1174eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    ExternalNames.insert(MainFunc->getName());
1184eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  }
1194eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
1204eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  bool Changed = false;
1214eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
122ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  // Mark all functions not in the api as internal.
1234eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
1245cbf985dcbc89fba3208e7baf8b6f488b06d3ec9Reid Spencer    if (!I->isDeclaration() &&         // Function must be defined here
1254eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner        !I->hasInternalLinkage() &&  // Can't already have internal linkage
1264eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner        !ExternalNames.count(I->getName())) {// Not marked to keep external?
1274eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      I->setLinkage(GlobalValue::InternalLinkage);
128a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands      // Remove a callgraph edge from the external node to this function.
129a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands      if (ExternalNode) ExternalNode->removeOneAbstractEdgeTo((*CG)[I]);
1304eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      Changed = true;
1314eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      ++NumFunctions;
1320a81aac4b46eed130d20714af5a1c01b05d0275eBill Wendling      DOUT << "Internalizing func " << I->getName() << "\n";
1334eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    }
1344eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
1354eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  // Never internalize the llvm.used symbol.  It is used to implement
1364eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  // attribute((used)).
1374eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  ExternalNames.insert("llvm.used");
138ee9e14cb8ab8e613bc6642396aaada20695b9458Chris Lattner
13944c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey  // Never internalize anchors used by the machine module info, else the info
14044c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey  // won't find them.  (see MachineModuleInfo.)
141e8c3e3b51c21dad94f0b427d7e0d6722e663fc64Jim Laskey  ExternalNames.insert("llvm.dbg.compile_units");
142e8c3e3b51c21dad94f0b427d7e0d6722e663fc64Jim Laskey  ExternalNames.insert("llvm.dbg.global_variables");
143e8c3e3b51c21dad94f0b427d7e0d6722e663fc64Jim Laskey  ExternalNames.insert("llvm.dbg.subprograms");
1444e2288b9de2fc30d4b88b437c86594cd8ec332faChris Lattner  ExternalNames.insert("llvm.global_ctors");
1454e2288b9de2fc30d4b88b437c86594cd8ec332faChris Lattner  ExternalNames.insert("llvm.global_dtors");
146bd14f58b765e994bf9a020575d517c5dc9bfbfe1Chris Lattner  ExternalNames.insert("llvm.noinline");
147088b5913ef6f91fccc3c931653e16bfeb330c90bTanya Lattner  ExternalNames.insert("llvm.global.annotations");
148a27ea769eb6f8be437ae1ff28ff49018a578f019Chris Lattner
149ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  // Mark all global variables with initializers that are not in the api as
150ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  // internal as well.
1514eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
1524eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner       I != E; ++I)
1535cbf985dcbc89fba3208e7baf8b6f488b06d3ec9Reid Spencer    if (!I->isDeclaration() && !I->hasInternalLinkage() &&
1544eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner        !ExternalNames.count(I->getName())) {
1554eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      I->setLinkage(GlobalValue::InternalLinkage);
1564eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      Changed = true;
1574eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      ++NumGlobals;
1580a81aac4b46eed130d20714af5a1c01b05d0275eBill Wendling      DOUT << "Internalized gvar " << I->getName() << "\n";
15955e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner    }
1604eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
1614eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  return Changed;
1624eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner}
163f629309f74cf1a64aa7fd1cd5784fd7db9a8f59eChris Lattner
1644e78908b9453edf7d0907d4811c469a630aff560Matthijs KooijmanModulePass *llvm::createInternalizePass(bool AllButMain) {
1654e78908b9453edf7d0907d4811c469a630aff560Matthijs Kooijman  return new InternalizePass(AllButMain);
166dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner}
167753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel
168d828a4b285339a2ae7d97428b64016628d9ef6dbDevang PatelModulePass *llvm::createInternalizePass(const std::vector <const char *> &el) {
169d828a4b285339a2ae7d97428b64016628d9ef6dbDevang Patel  return new InternalizePass(el);
170753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel}
171