Internalize.cpp revision 551ccae044b0ff658fe629dd67edd5ffe75d10e8
1//===-- Internalize.cpp - Mark functions internal -------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the LLVM research group and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This pass loops over all of the functions in the input module, looking for a 11// main function. If a main function is found, all other functions and all 12// global variables with initializers are marked as internal. 13// 14//===----------------------------------------------------------------------===// 15 16#include "llvm/Transforms/IPO.h" 17#include "llvm/Pass.h" 18#include "llvm/Module.h" 19#include "llvm/Support/CommandLine.h" 20#include "llvm/Support/Debug.h" 21#include "llvm/ADT/Statistic.h" 22#include <fstream> 23#include <set> 24using namespace llvm; 25 26namespace { 27 Statistic<> NumFunctions("internalize", "Number of functions internalized"); 28 Statistic<> NumGlobals ("internalize", "Number of global vars internalized"); 29 30 // APIFile - A file which contains a list of symbols that should not be marked 31 // external. 32 cl::opt<std::string> 33 APIFile("internalize-public-api-file", cl::value_desc("filename"), 34 cl::desc("A file containing list of symbol names to preserve")); 35 36 // APIList - A list of symbols that should not be marked internal. 37 cl::list<std::string> 38 APIList("internalize-public-api-list", cl::value_desc("list"), 39 cl::desc("A list of symbol names to preserve"), 40 cl::CommaSeparated); 41 42 class InternalizePass : public Pass { 43 std::set<std::string> ExternalNames; 44 public: 45 InternalizePass() { 46 if (!APIFile.empty()) // If a filename is specified, use it 47 LoadFile(APIFile.c_str()); 48 else // Else, if a list is specified, use it. 49 ExternalNames.insert(APIList.begin(), APIList.end()); 50 } 51 52 void LoadFile(const char *Filename) { 53 // Load the APIFile... 54 std::ifstream In(Filename); 55 if (!In.good()) { 56 std::cerr << "WARNING: Internalize couldn't load file '" << Filename 57 << "'!\n"; 58 return; // Do not internalize anything... 59 } 60 while (In) { 61 std::string Symbol; 62 In >> Symbol; 63 if (!Symbol.empty()) 64 ExternalNames.insert(Symbol); 65 } 66 } 67 68 virtual bool run(Module &M) { 69 // If no list or file of symbols was specified, check to see if there is a 70 // "main" symbol defined in the module. If so, use it, otherwise do not 71 // internalize the module, it must be a library or something. 72 // 73 if (ExternalNames.empty()) { 74 Function *MainFunc = M.getMainFunction(); 75 if (MainFunc == 0 || MainFunc->isExternal()) 76 return false; // No main found, must be a library... 77 78 // Preserve main, internalize all else. 79 ExternalNames.insert(MainFunc->getName()); 80 } 81 82 bool Changed = false; 83 84 // Found a main function, mark all functions not named main as internal. 85 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) 86 if (!I->isExternal() && // Function must be defined here 87 !I->hasInternalLinkage() && // Can't already have internal linkage 88 !ExternalNames.count(I->getName())) {// Not marked to keep external? 89 I->setLinkage(GlobalValue::InternalLinkage); 90 Changed = true; 91 ++NumFunctions; 92 DEBUG(std::cerr << "Internalizing func " << I->getName() << "\n"); 93 } 94 95 // Mark all global variables with initializers as internal as well... 96 for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) 97 if (!I->isExternal() && !I->hasInternalLinkage() && 98 !ExternalNames.count(I->getName())) { 99 // Special case handling of the global ctor and dtor list. When we 100 // internalize it, we mark it constant, which allows elimination of 101 // the list if it's empty. 102 // 103 if (I->hasAppendingLinkage() && (I->getName() == "llvm.global_ctors"|| 104 I->getName() == "llvm.global_dtors")) 105 I->setConstant(true); 106 107 I->setLinkage(GlobalValue::InternalLinkage); 108 Changed = true; 109 ++NumGlobals; 110 DEBUG(std::cerr << "Internalizing gvar " << I->getName() << "\n"); 111 } 112 113 return Changed; 114 } 115 }; 116 117 RegisterOpt<InternalizePass> X("internalize", "Internalize Global Symbols"); 118} // end anonymous namespace 119 120Pass *llvm::createInternalizePass() { 121 return new InternalizePass(); 122} 123