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