Internalize.cpp revision d13db2c59cc94162d6cf0a04187d408bfef6d4a7
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"
22551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/Debug.h"
23ce63ffb52f249b62cdf2d250c128007b13f27e71Daniel Dunbar#include "llvm/Support/raw_ostream.h"
24551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/ADT/Statistic.h"
25c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include <fstream>
26c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include <set>
271e2385b941242f2f96398dc62767420622856149Chris Lattnerusing namespace llvm;
28d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
2927a53009efcf1b0334dc17c3d54382798686ff59Duncan SandsSTATISTIC(NumAliases  , "Number of aliases internalized");
3086453c52ba02e743d29c08456e51006500041456Chris LattnerSTATISTIC(NumFunctions, "Number of functions internalized");
3186453c52ba02e743d29c08456e51006500041456Chris LattnerSTATISTIC(NumGlobals  , "Number of global vars internalized");
3286453c52ba02e743d29c08456e51006500041456Chris Lattner
33844731a7f1909f55935e3514c9e713a62d67662eDan Gohman// APIFile - A file which contains a list of symbols that should not be marked
34844731a7f1909f55935e3514c9e713a62d67662eDan Gohman// external.
35844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanstatic cl::opt<std::string>
36844731a7f1909f55935e3514c9e713a62d67662eDan GohmanAPIFile("internalize-public-api-file", cl::value_desc("filename"),
37844731a7f1909f55935e3514c9e713a62d67662eDan Gohman        cl::desc("A file containing list of symbol names to preserve"));
382345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner
39844731a7f1909f55935e3514c9e713a62d67662eDan Gohman// APIList - A list of symbols that should not be marked internal.
40844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanstatic cl::list<std::string>
41844731a7f1909f55935e3514c9e713a62d67662eDan GohmanAPIList("internalize-public-api-list", cl::value_desc("list"),
42844731a7f1909f55935e3514c9e713a62d67662eDan Gohman        cl::desc("A list of symbol names to preserve"),
43844731a7f1909f55935e3514c9e713a62d67662eDan Gohman        cl::CommaSeparated);
44fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman
45844731a7f1909f55935e3514c9e713a62d67662eDan Gohmannamespace {
466726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky  class InternalizePass : public ModulePass {
47c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner    std::set<std::string> ExternalNames;
48ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    /// If no api symbols were specified and a main function is defined,
49ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    /// assume the main function is the only API
50ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    bool AllButMain;
51c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner  public:
52ecd94c804a563f2a86572dcf1d2e81f397e19daaNick Lewycky    static char ID; // Pass identification, replacement for typeid
534e78908b9453edf7d0907d4811c469a630aff560Matthijs Kooijman    explicit InternalizePass(bool AllButMain = true);
54c2bbfc18e9adbbdcf5b3375d8d25e2452f7df7f1Dan Gohman    explicit InternalizePass(const std::vector <const char *>& exportList);
554eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    void LoadFile(const char *Filename);
564eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    virtual bool runOnModule(Module &M);
570483d018c4f15f206a83364e498957127e74f431Nuno Lopes
580483d018c4f15f206a83364e498957127e74f431Nuno Lopes    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
590483d018c4f15f206a83364e498957127e74f431Nuno Lopes      AU.setPreservesCFG();
60a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands      AU.addPreserved<CallGraph>();
610483d018c4f15f206a83364e498957127e74f431Nuno Lopes    }
624eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  };
634eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner} // end anonymous namespace
6493fbd733e778c2623436ed5a0b9cf7f394407b1aChris Lattner
65844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanchar InternalizePass::ID = 0;
66d13db2c59cc94162d6cf0a04187d408bfef6d4a7Owen AndersonINITIALIZE_PASS(InternalizePass, "internalize",
67d13db2c59cc94162d6cf0a04187d408bfef6d4a7Owen Anderson                "Internalize Global Symbols", false, false);
68844731a7f1909f55935e3514c9e713a62d67662eDan Gohman
69ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang PatelInternalizePass::InternalizePass(bool AllButMain)
70ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman  : ModulePass(&ID), AllButMain(AllButMain){
71ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  if (!APIFile.empty())           // If a filename is specified, use it.
724eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    LoadFile(APIFile.c_str());
73ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  if (!APIList.empty())           // If a list is specified, use it as well.
744eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    ExternalNames.insert(APIList.begin(), APIList.end());
754eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner}
76c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner
772631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan SandsInternalizePass::InternalizePass(const std::vector<const char *>&exportList)
78ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman  : ModulePass(&ID), AllButMain(false){
79753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel  for(std::vector<const char *>::const_iterator itr = exportList.begin();
80bed2946a96ecb15b0b636fa74cb26ce61b1c648eAnton Korobeynikov        itr != exportList.end(); itr++) {
81753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel    ExternalNames.insert(*itr);
82753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel  }
83753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel}
84753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel
854eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnervoid InternalizePass::LoadFile(const char *Filename) {
864eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  // Load the APIFile...
874eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  std::ifstream In(Filename);
884eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  if (!In.good()) {
894437ae213d5435390f0750213b53ec807c047f22Chris Lattner    errs() << "WARNING: Internalize couldn't load file '" << Filename
90ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel         << "'! Continuing as if it's empty.\n";
91ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    return; // Just continue as if the file were empty
924eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  }
934eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  while (In) {
944eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    std::string Symbol;
954eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    In >> Symbol;
964eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    if (!Symbol.empty())
974eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      ExternalNames.insert(Symbol);
984eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  }
994eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner}
1004eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
1014eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerbool InternalizePass::runOnModule(Module &M) {
1021465d61bdd36cfd6021036a527895f0dd358e97dDuncan Sands  CallGraph *CG = getAnalysisIfAvailable<CallGraph>();
103a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands  CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0;
104001dbfebcbbded8c8e74b19e838b50da2b6c6fb5Owen Anderson
1054eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  if (ExternalNames.empty()) {
106ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    // Return if we're not in 'all but main' mode and have no external api
107ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    if (!AllButMain)
1082631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands      return false;
109ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    // If no list or file of symbols was specified, check to see if there is a
110ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    // "main" symbol defined in the module.  If so, use it, otherwise do not
111ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    // internalize the module, it must be a library or something.
112ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    //
113688b0490e22eb67623f5aaa24406209be74efcb2Reid Spencer    Function *MainFunc = M.getFunction("main");
1145cbf985dcbc89fba3208e7baf8b6f488b06d3ec9Reid Spencer    if (MainFunc == 0 || MainFunc->isDeclaration())
1154eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      return false;  // No main found, must be a library...
1162631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
1174eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    // Preserve main, internalize all else.
1184eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    ExternalNames.insert(MainFunc->getName());
1194eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  }
1202631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
1214eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  bool Changed = false;
1222631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
123ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  // Mark all functions not in the api as internal.
124bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindola  // FIXME: maybe use private linkage?
1254eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
1265cbf985dcbc89fba3208e7baf8b6f488b06d3ec9Reid Spencer    if (!I->isDeclaration() &&         // Function must be defined here
127bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindola        !I->hasLocalLinkage() &&  // Can't already have internal linkage
1284eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner        !ExternalNames.count(I->getName())) {// Not marked to keep external?
1294eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      I->setLinkage(GlobalValue::InternalLinkage);
130a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands      // Remove a callgraph edge from the external node to this function.
131a2582da44dbe7204aac49cdaeccfd4e77ff7c408Duncan Sands      if (ExternalNode) ExternalNode->removeOneAbstractEdgeTo((*CG)[I]);
1324eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      Changed = true;
1334eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      ++NumFunctions;
134fd2ab9ff4466cb2e07be536fc838d3520a0f8aa5David Greene      DEBUG(dbgs() << "Internalizing func " << I->getName() << "\n");
1354eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    }
1362631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
1374eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  // Never internalize the llvm.used symbol.  It is used to implement
1384eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  // attribute((used)).
139401e10c4fbfcdcfade5065093e2ca97f69a1d144Chris Lattner  // FIXME: Shouldn't this just filter on llvm.metadata section??
1404eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  ExternalNames.insert("llvm.used");
141401e10c4fbfcdcfade5065093e2ca97f69a1d144Chris Lattner  ExternalNames.insert("llvm.compiler.used");
1422631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
14344c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey  // Never internalize anchors used by the machine module info, else the info
14444c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey  // won't find them.  (see MachineModuleInfo.)
145e8c3e3b51c21dad94f0b427d7e0d6722e663fc64Jim Laskey  ExternalNames.insert("llvm.dbg.compile_units");
146e8c3e3b51c21dad94f0b427d7e0d6722e663fc64Jim Laskey  ExternalNames.insert("llvm.dbg.global_variables");
147e8c3e3b51c21dad94f0b427d7e0d6722e663fc64Jim Laskey  ExternalNames.insert("llvm.dbg.subprograms");
1484e2288b9de2fc30d4b88b437c86594cd8ec332faChris Lattner  ExternalNames.insert("llvm.global_ctors");
1494e2288b9de2fc30d4b88b437c86594cd8ec332faChris Lattner  ExternalNames.insert("llvm.global_dtors");
150bd14f58b765e994bf9a020575d517c5dc9bfbfe1Chris Lattner  ExternalNames.insert("llvm.noinline");
151088b5913ef6f91fccc3c931653e16bfeb330c90bTanya Lattner  ExternalNames.insert("llvm.global.annotations");
1522631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
153ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  // Mark all global variables with initializers that are not in the api as
154ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  // internal as well.
155bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindola  // FIXME: maybe use private linkage?
1564eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
1574eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner       I != E; ++I)
158bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindola    if (!I->isDeclaration() && !I->hasLocalLinkage() &&
1598e9c48a606acd5894407f73453448bb0911648c7Chris Lattner        // Available externally is really just a "declaration with a body".
1608e9c48a606acd5894407f73453448bb0911648c7Chris Lattner        !I->hasAvailableExternallyLinkage() &&
1614eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner        !ExternalNames.count(I->getName())) {
1624eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      I->setLinkage(GlobalValue::InternalLinkage);
1634eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      Changed = true;
1644eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      ++NumGlobals;
165fd2ab9ff4466cb2e07be536fc838d3520a0f8aa5David Greene      DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n");
16655e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner    }
1672631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
16827a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands  // Mark all aliases that are not in the api as internal as well.
16927a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands  for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
17027a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands       I != E; ++I)
17127a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands    if (!I->isDeclaration() && !I->hasInternalLinkage() &&
1728e9c48a606acd5894407f73453448bb0911648c7Chris Lattner        // Available externally is really just a "declaration with a body".
1738e9c48a606acd5894407f73453448bb0911648c7Chris Lattner        !I->hasAvailableExternallyLinkage() &&
17427a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands        !ExternalNames.count(I->getName())) {
17527a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands      I->setLinkage(GlobalValue::InternalLinkage);
17627a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands      Changed = true;
17727a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands      ++NumAliases;
178fd2ab9ff4466cb2e07be536fc838d3520a0f8aa5David Greene      DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n");
17927a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands    }
18027a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands
1814eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  return Changed;
1824eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner}
183f629309f74cf1a64aa7fd1cd5784fd7db9a8f59eChris Lattner
1844e78908b9453edf7d0907d4811c469a630aff560Matthijs KooijmanModulePass *llvm::createInternalizePass(bool AllButMain) {
1854e78908b9453edf7d0907d4811c469a630aff560Matthijs Kooijman  return new InternalizePass(AllButMain);
186dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner}
187753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel
188d828a4b285339a2ae7d97428b64016628d9ef6dbDevang PatelModulePass *llvm::createInternalizePass(const std::vector <const char *> &el) {
189d828a4b285339a2ae7d97428b64016628d9ef6dbDevang Patel  return new InternalizePass(el);
190753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel}
191