Internalize.cpp revision b576c94c15af9a440f69d9d03c2afead7971118c
1dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner//===-- Internalize.cpp - Mark functions internal -------------------------===// 2b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// 3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// The LLVM Compiler Infrastructure 4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// 5b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// This file was developed by the LLVM research group and is distributed under 6b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// the University of Illinois Open Source License. See LICENSE.TXT for details. 7b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// 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 16568ddabc8f9015baf2d42cc425618412972f1b92Chris Lattner#include "llvm/Transforms/IPO.h" 17dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner#include "llvm/Pass.h" 18dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner#include "llvm/Module.h" 19c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include "Support/CommandLine.h" 206806f5614d2ec260fda954c951d33f58e77ed610Chris Lattner#include "Support/Debug.h" 216806f5614d2ec260fda954c951d33f58e77ed610Chris Lattner#include "Support/Statistic.h" 22c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include <fstream> 23c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner#include <set> 243dec1f272219ee1f8e1499929cdf53f5bc3c2272Chris Lattner 25f629309f74cf1a64aa7fd1cd5784fd7db9a8f59eChris Lattnernamespace { 26a92f696b74a99325026ebbdbffd2a44317e0c10bChris Lattner Statistic<> NumFunctions("internalize", "Number of functions internalized"); 27a92f696b74a99325026ebbdbffd2a44317e0c10bChris Lattner Statistic<> NumGlobals ("internalize", "Number of global vars internalized"); 2855e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner 29c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner // APIFile - A file which contains a list of symbols that should not be marked 30c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner // external. 31c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner cl::opt<std::string> 32c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner APIFile("internalize-public-api-file", cl::value_desc("filename"), 332345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner cl::desc("A file containing list of symbol names to preserve")); 342345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner 352345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner // APIList - A list of symbols that should not be marked internal. 362345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner cl::list<std::string> 372345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner APIList("internalize-public-api-list", cl::value_desc("list"), 3888c7c3295d936c807bc03ff4fd9da4691084f5d8Chris Lattner cl::desc("A list of symbol names to preserve"), 3988c7c3295d936c807bc03ff4fd9da4691084f5d8Chris Lattner cl::CommaSeparated); 402345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner 4155e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner class InternalizePass : public Pass { 42c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner std::set<std::string> ExternalNames; 43c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner public: 44c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner InternalizePass() { 452345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner if (!APIFile.empty()) // If a filename is specified, use it 46c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner LoadFile(APIFile.c_str()); 472345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner else // Else, if a list is specified, use it. 482345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner ExternalNames.insert(APIList.begin(), APIList.end()); 49c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner } 5093fbd733e778c2623436ed5a0b9cf7f394407b1aChris Lattner 51c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner void LoadFile(const char *Filename) { 52c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner // Load the APIFile... 53c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner std::ifstream In(Filename); 54c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner if (!In.good()) { 55c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner std::cerr << "WARNING: Internalize couldn't load file '" << Filename 562345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner << "'!\n"; 57c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner return; // Do not internalize anything... 58c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner } 59c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner while (In) { 60c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner std::string Symbol; 61c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner In >> Symbol; 62c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner if (!Symbol.empty()) 63c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner ExternalNames.insert(Symbol); 64c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner } 65c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner } 66c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner 67c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner virtual bool run(Module &M) { 682345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner // If no list or file of symbols was specified, check to see if there is a 692345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner // "main" symbol defined in the module. If so, use it, otherwise do not 702345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner // internalize the module, it must be a library or something. 712345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner // 722345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner if (ExternalNames.empty()) { 732345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner Function *MainFunc = M.getMainFunction(); 742345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner if (MainFunc == 0 || MainFunc->isExternal()) 752345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner return false; // No main found, must be a library... 762345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner 772345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner // Preserve main, internalize all else. 782345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner ExternalNames.insert(MainFunc->getName()); 792345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner } 802345d71853e75fd56a8ca66d40bf36eba0a9edb6Chris Lattner 8155e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner bool Changed = false; 8255e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner 8355e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner // Found a main function, mark all functions not named main as internal. 8455e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) 85c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner if (!I->isExternal() && // Function must be defined here 86c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner !I->hasInternalLinkage() && // Can't already have internal linkage 87c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner !ExternalNames.count(I->getName())) {// Not marked to keep external? 884ad02e726d9b634372b037d4b352d8b63bb9e849Chris Lattner I->setLinkage(GlobalValue::InternalLinkage); 8955e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner Changed = true; 9055e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner ++NumFunctions; 9155e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner DEBUG(std::cerr << "Internalizing func " << I->getName() << "\n"); 9255e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner } 9355e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner 9455e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner // Mark all global variables with initializers as internal as well... 9555e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) 96c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner if (!I->isExternal() && !I->hasInternalLinkage() && 97c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner !ExternalNames.count(I->getName())) { 9881d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner // Special case handling of the global ctor and dtor list. When we 9981d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner // internalize it, we mark it constant, which allows elimination of 10081d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner // the list if it's empty. 10181d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner // 10281d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner if (I->hasAppendingLinkage() && (I->getName() == "llvm.global_ctors"|| 10381d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner I->getName() == "llvm.global_dtors")) 10481d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner I->setConstant(true); 10581d4e14449fce69ca3a315685a80bb3c20a3db23Chris Lattner 1064ad02e726d9b634372b037d4b352d8b63bb9e849Chris Lattner I->setLinkage(GlobalValue::InternalLinkage); 10755e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner Changed = true; 10855e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner ++NumGlobals; 10955e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner DEBUG(std::cerr << "Internalizing gvar " << I->getName() << "\n"); 11055e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner } 11155e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner 11255e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner return Changed; 11355e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner } 11455e41ba3d293699e47fdeb8996cc743b2018bde8Chris Lattner }; 115dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner 116c7a2c7f0c9900c6658bc567211d695f0593484c2Chris Lattner RegisterOpt<InternalizePass> X("internalize", "Internalize Global Symbols"); 117f629309f74cf1a64aa7fd1cd5784fd7db9a8f59eChris Lattner} // end anonymous namespace 118f629309f74cf1a64aa7fd1cd5784fd7db9a8f59eChris Lattner 119dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris LattnerPass *createInternalizePass() { 120dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner return new InternalizePass(); 121dbb1735673ed177a85f04698b9cd89f2dc1b4e91Chris Lattner} 122