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