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//
10e5551ed9cec1ae777c4e4b8852a1d7842c2e1c3dRafael Espindola// This pass loops over all of the functions and variables in the input module.
11e5551ed9cec1ae777c4e4b8852a1d7842c2e1c3dRafael Espindola// If the function or variable is not in the list of external names given to
12e5551ed9cec1ae777c4e4b8852a1d7842c2e1c3dRafael Espindola// the pass it is marked as internal.
13dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner//
147e667c56cf7e27ff521ceb86518beab32bfb630dRafael Espindola// This transformation would not be legal in a regular compilation, but it gets
157e667c56cf7e27ff521ceb86518beab32bfb630dRafael Espindola// extra information from the linker about what is safe.
16713cab059ebb67c2f51d8da9d8e57be2b1dcd9c2Rafael Espindola//
177e667c56cf7e27ff521ceb86518beab32bfb630dRafael Espindola// For example: Internalizing a function with external linkage. Only if we are
187e667c56cf7e27ff521ceb86518beab32bfb630dRafael Espindola// told it is only used from within this module, it is safe to do it.
19713cab059ebb67c2f51d8da9d8e57be2b1dcd9c2Rafael Espindola//
20dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner//===----------------------------------------------------------------------===//
21dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner
22568ddabc8f9015baf2d42cc425618412972f1b92Chris Lattner#include "llvm/Transforms/IPO.h"
234ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola#include "llvm/ADT/SmallPtrSet.h"
24d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/Statistic.h"
25d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Analysis/CallGraph.h"
260b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h"
27d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Pass.h"
28551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/CommandLine.h"
29551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/Debug.h"
30ce63ffb52f249b62cdf2d250c128007b13f27e71Daniel Dunbar#include "llvm/Support/raw_ostream.h"
31713cab059ebb67c2f51d8da9d8e57be2b1dcd9c2Rafael Espindola#include "llvm/Transforms/Utils/GlobalStatus.h"
324ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola#include "llvm/Transforms/Utils/ModuleUtils.h"
33c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include <fstream>
34c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include <set>
351e2385b941242f2f96398dc62767420622856149Chris Lattnerusing namespace llvm;
36d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
37dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "internalize"
38dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
3927a53009efcf1b0334dc17c3d54382798686ff59Duncan SandsSTATISTIC(NumAliases  , "Number of aliases internalized");
4086453c52ba02e743d29c08456e51006500041456Chris LattnerSTATISTIC(NumFunctions, "Number of functions internalized");
4186453c52ba02e743d29c08456e51006500041456Chris LattnerSTATISTIC(NumGlobals  , "Number of global vars internalized");
4286453c52ba02e743d29c08456e51006500041456Chris Lattner
43844731a7f1909f55935e3514c9e713a62d67662eDan Gohman// APIFile - A file which contains a list of symbols that should not be marked
44844731a7f1909f55935e3514c9e713a62d67662eDan Gohman// external.
45844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanstatic cl::opt<std::string>
46844731a7f1909f55935e3514c9e713a62d67662eDan GohmanAPIFile("internalize-public-api-file", cl::value_desc("filename"),
47844731a7f1909f55935e3514c9e713a62d67662eDan Gohman        cl::desc("A file containing list of symbol names to preserve"));
482345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner
49844731a7f1909f55935e3514c9e713a62d67662eDan Gohman// APIList - A list of symbols that should not be marked internal.
50844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanstatic cl::list<std::string>
51844731a7f1909f55935e3514c9e713a62d67662eDan GohmanAPIList("internalize-public-api-list", cl::value_desc("list"),
52844731a7f1909f55935e3514c9e713a62d67662eDan Gohman        cl::desc("A list of symbol names to preserve"),
53844731a7f1909f55935e3514c9e713a62d67662eDan Gohman        cl::CommaSeparated);
54fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman
55844731a7f1909f55935e3514c9e713a62d67662eDan Gohmannamespace {
566726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky  class InternalizePass : public ModulePass {
57c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner    std::set<std::string> ExternalNames;
58c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner  public:
59ecd94c804a563f2a86572dcf1d2e81f397e19daaNick Lewycky    static char ID; // Pass identification, replacement for typeid
60e5551ed9cec1ae777c4e4b8852a1d7842c2e1c3dRafael Espindola    explicit InternalizePass();
617e667c56cf7e27ff521ceb86518beab32bfb630dRafael Espindola    explicit InternalizePass(ArrayRef<const char *> ExportList);
624eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    void LoadFile(const char *Filename);
63cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    bool maybeInternalize(GlobalValue &GV,
64cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                          const std::set<const Comdat *> &ExternalComdats);
65cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void checkComdatVisibility(GlobalValue &GV,
66cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                               std::set<const Comdat *> &ExternalComdats);
6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool runOnModule(Module &M) override;
680483d018c4f15f206a83364e498957127e74f431Nuno Lopes
6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void getAnalysisUsage(AnalysisUsage &AU) const override {
700483d018c4f15f206a83364e498957127e74f431Nuno Lopes      AU.setPreservesCFG();
7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      AU.addPreserved<CallGraphWrapperPass>();
720483d018c4f15f206a83364e498957127e74f431Nuno Lopes    }
734eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  };
744eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner} // end anonymous namespace
7593fbd733e778c2623436ed5a0b9cf7f394407b1aChris Lattner
76844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanchar InternalizePass::ID = 0;
77d13db2c59cc94162d6cf0a04187d408bfef6d4a7Owen AndersonINITIALIZE_PASS(InternalizePass, "internalize",
78ce665bd2e2b581ab0858d1afe359192bac96b868Owen Anderson                "Internalize Global Symbols", false, false)
79844731a7f1909f55935e3514c9e713a62d67662eDan Gohman
8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesInternalizePass::InternalizePass() : ModulePass(ID) {
81081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson  initializeInternalizePassPass(*PassRegistry::getPassRegistry());
82ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  if (!APIFile.empty())           // If a filename is specified, use it.
834eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    LoadFile(APIFile.c_str());
841d7df349ab7fa051ffe88589b06a1aa514f84a00Rafael Espindola  ExternalNames.insert(APIList.begin(), APIList.end());
854eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner}
86c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner
877e667c56cf7e27ff521ceb86518beab32bfb630dRafael EspindolaInternalizePass::InternalizePass(ArrayRef<const char *> ExportList)
8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    : ModulePass(ID) {
89081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson  initializeInternalizePassPass(*PassRegistry::getPassRegistry());
90775079c227083be3fe22f6ae071d5b74a7ade745Rafael Espindola  for(ArrayRef<const char *>::const_iterator itr = ExportList.begin();
91775079c227083be3fe22f6ae071d5b74a7ade745Rafael Espindola        itr != ExportList.end(); itr++) {
92753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel    ExternalNames.insert(*itr);
93753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel  }
94753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel}
95753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel
964eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnervoid InternalizePass::LoadFile(const char *Filename) {
974eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  // Load the APIFile...
984eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  std::ifstream In(Filename);
994eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  if (!In.good()) {
1004437ae213d5435390f0750213b53ec807c047f22Chris Lattner    errs() << "WARNING: Internalize couldn't load file '" << Filename
101ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel         << "'! Continuing as if it's empty.\n";
102ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel    return; // Just continue as if the file were empty
1034eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  }
1044eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  while (In) {
1054eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    std::string Symbol;
1064eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    In >> Symbol;
1074eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner    if (!Symbol.empty())
1084eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner      ExternalNames.insert(Symbol);
1094eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  }
1104eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner}
1114eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner
112cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarstatic bool isExternallyVisible(const GlobalValue &GV,
113cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                const std::set<std::string> &ExternalNames) {
1140fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola  // Function must be defined here
1150fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola  if (GV.isDeclaration())
116cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    return true;
1170fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola
1180fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola  // Available externally is really just a "declaration with a body".
1190fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola  if (GV.hasAvailableExternallyLinkage())
120cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    return true;
1210fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola
12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Assume that dllexported symbols are referenced elsewhere
12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (GV.hasDLLExportStorageClass())
124cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    return true;
1250fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola
1260fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola  // Marked to keep external?
127cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (!GV.hasLocalLinkage() && ExternalNames.count(GV.getName()))
128cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    return true;
129cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
130cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return false;
131cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
1320fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola
133cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// Internalize GV if it is possible to do so, i.e. it is not externally visible
134cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// and is not a member of an externally visible comdat.
135cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarbool InternalizePass::maybeInternalize(
136cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    GlobalValue &GV, const std::set<const Comdat *> &ExternalComdats) {
137cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (Comdat *C = GV.getComdat()) {
138cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (ExternalComdats.count(C))
139cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      return false;
140cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
141cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // If a comdat is not externally visible we can drop it.
142cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (auto GO = dyn_cast<GlobalObject>(&GV))
143cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      GO->setComdat(nullptr);
144cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
145cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (GV.hasLocalLinkage())
146cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      return false;
147cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  } else {
148cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (GV.hasLocalLinkage())
149cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      return false;
150cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
151cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (isExternallyVisible(GV, ExternalNames))
152cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      return false;
153cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
154cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
155cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  GV.setVisibility(GlobalValue::DefaultVisibility);
156cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  GV.setLinkage(GlobalValue::InternalLinkage);
1577e667c56cf7e27ff521ceb86518beab32bfb630dRafael Espindola  return true;
1580fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola}
1590fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola
160cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// If GV is part of a comdat and is externally visible, keep track of its
161cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// comdat so that we don't internalize any of its members.
162cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarvoid InternalizePass::checkComdatVisibility(
163cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    GlobalValue &GV, std::set<const Comdat *> &ExternalComdats) {
164cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  Comdat *C = GV.getComdat();
165cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (!C)
166cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    return;
167cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
168cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (isExternallyVisible(GV, ExternalNames))
169cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    ExternalComdats.insert(C);
170cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
171cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
1724eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattnerbool InternalizePass::runOnModule(Module &M) {
17336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  CallGraphWrapperPass *CGPass = getAnalysisIfAvailable<CallGraphWrapperPass>();
174dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  CallGraph *CG = CGPass ? &CGPass->getCallGraph() : nullptr;
175dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : nullptr;
1762631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
1774ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  SmallPtrSet<GlobalValue *, 8> Used;
1784ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  collectUsedGlobalVariables(M, Used, false);
1794ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola
180cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // Collect comdat visiblity information for the module.
181cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  std::set<const Comdat *> ExternalComdats;
182cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (!M.getComdatSymbolTable().empty()) {
183cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    for (Function &F : M)
184cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      checkComdatVisibility(F, ExternalComdats);
185cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    for (GlobalVariable &GV : M.globals())
186cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      checkComdatVisibility(GV, ExternalComdats);
187cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    for (GlobalAlias &GA : M.aliases())
188cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      checkComdatVisibility(GA, ExternalComdats);
189cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
190cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
1914ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  // We must assume that globals in llvm.used have a reference that not even
1924ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  // the linker can see, so we don't internalize them.
1934ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  // For llvm.compiler.used the situation is a bit fuzzy. The assembler and
1944ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  // linker can drop those symbols. If this pass is running as part of LTO,
1954ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  // one might think that it could just drop llvm.compiler.used. The problem
1964ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  // is that even in LTO llvm doesn't see every reference. For example,
1974ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  // we don't see references from function local inline assembly. To be
1984ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  // conservative, we internalize symbols in llvm.compiler.used, but we
1994ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  // keep llvm.compiler.used so that the symbol is not deleted by llvm.
20037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  for (GlobalValue *V : Used) {
2014ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola    ExternalNames.insert(V->getName());
2024ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  }
2034ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola
204ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  // Mark all functions not in the api as internal.
205cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  for (Function &I : M) {
206cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (!maybeInternalize(I, ExternalComdats))
2070fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola      continue;
2080fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola
2090fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola    if (ExternalNode)
2100fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola      // Remove a callgraph edge from the external node to this function.
211cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      ExternalNode->removeOneAbstractEdgeTo((*CG)[&I]);
2120fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola
2130fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola    ++NumFunctions;
214cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    DEBUG(dbgs() << "Internalizing func " << I.getName() << "\n");
2150fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola  }
2162631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
2174eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  // Never internalize the llvm.used symbol.  It is used to implement
2184eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  // attribute((used)).
219401e10c4fbfcdcfade5065093e2ca97f69a1d144Chris Lattner  // FIXME: Shouldn't this just filter on llvm.metadata section??
2204eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  ExternalNames.insert("llvm.used");
221401e10c4fbfcdcfade5065093e2ca97f69a1d144Chris Lattner  ExternalNames.insert("llvm.compiler.used");
2222631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
22344c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey  // Never internalize anchors used by the machine module info, else the info
22444c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey  // won't find them.  (see MachineModuleInfo.)
2254e2288b9de2fc30d4b88b437c86594cd8ec332faChris Lattner  ExternalNames.insert("llvm.global_ctors");
2264e2288b9de2fc30d4b88b437c86594cd8ec332faChris Lattner  ExternalNames.insert("llvm.global_dtors");
227088b5913ef6f91fccc3c931653e16bfeb330c90bTanya Lattner  ExternalNames.insert("llvm.global.annotations");
2282631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
229aab3c0cb077f741af3447cc030c28bedd23b491cBill Wendling  // Never internalize symbols code-gen inserts.
230d275ff5d4c4f4f8bf9a77acd70605caa98c14246Bill Wendling  // FIXME: We should probably add this (and the __stack_chk_guard) via some
231d275ff5d4c4f4f8bf9a77acd70605caa98c14246Bill Wendling  // type of call-back in CodeGen.
232d275ff5d4c4f4f8bf9a77acd70605caa98c14246Bill Wendling  ExternalNames.insert("__stack_chk_fail");
233aab3c0cb077f741af3447cc030c28bedd23b491cBill Wendling  ExternalNames.insert("__stack_chk_guard");
234aab3c0cb077f741af3447cc030c28bedd23b491cBill Wendling
235ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  // Mark all global variables with initializers that are not in the api as
236ef3682a4fbfc3ff1a593adf95740ad8ab0d1d487Devang Patel  // internal as well.
2374eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
2380fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola       I != E; ++I) {
239cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (!maybeInternalize(*I, ExternalComdats))
2400fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola      continue;
2410fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola
2420fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola    ++NumGlobals;
2430fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola    DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n");
2440fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola  }
2452631ac3b5b4c2d7eaf8d1db178dc98071a708ad2Duncan Sands
24627a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands  // Mark all aliases that are not in the api as internal as well.
24727a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands  for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
2480fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola       I != E; ++I) {
249cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (!maybeInternalize(*I, ExternalComdats))
2500fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola      continue;
2510fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola
2520fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola    ++NumAliases;
2530fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola    DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n");
2540fb771667eb2f8a5cd623ce0ee3775b4d1416576Rafael Espindola  }
25527a53009efcf1b0334dc17c3d54382798686ff59Duncan Sands
256cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // We do not keep track of whether this pass changed the module because
257cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // it adds unnecessary complexity:
258cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // 1) This pass will generally be near the start of the pass pipeline, so
259cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  //    there will be no analyses to invalidate.
260cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // 2) This pass will most likely end up changing the module and it isn't worth
261cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  //    worrying about optimizing the case where the module is unchanged.
262cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return true;
2634eb40df1a839c08bca6dcab90ba1a4831e5ef52dChris Lattner}
264f629309f74cf1a64aa7fd1cd5784fd7db9a8f59eChris Lattner
26536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesModulePass *llvm::createInternalizePass() { return new InternalizePass(); }
266753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel
2677e667c56cf7e27ff521ceb86518beab32bfb630dRafael EspindolaModulePass *llvm::createInternalizePass(ArrayRef<const char *> ExportList) {
2687e667c56cf7e27ff521ceb86518beab32bfb630dRafael Espindola  return new InternalizePass(ExportList);
269753d94a1c8fe02f64eb4f482d396712c68db1d84Devang Patel}
270