blob: 92d389a33d0d8ff60d671bdfbdef084aabc92c1b [file] [log] [blame]
Chris Lattner1b94c002002-04-28 05:43:27 +00001//===-- Internalize.cpp - Mark functions internal -------------------------===//
John Criswell482202a2003-10-20 19:43:21 +00002//
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//===----------------------------------------------------------------------===//
Chris Lattner1b94c002002-04-28 05:43:27 +00009//
10// This pass loops over all of the functions in the input module, looking for a
Chris Lattner47cc3662002-07-30 19:48:44 +000011// main function. If a main function is found, all other functions and all
12// global variables with initializers are marked as internal.
Chris Lattner1b94c002002-04-28 05:43:27 +000013//
14//===----------------------------------------------------------------------===//
15
Chris Lattner99a53f62002-07-24 17:12:05 +000016#include "llvm/Transforms/IPO.h"
Chris Lattner1b94c002002-04-28 05:43:27 +000017#include "llvm/Pass.h"
18#include "llvm/Module.h"
Chris Lattner44457bb2003-05-22 19:34:49 +000019#include "Support/CommandLine.h"
Chris Lattner8abcd562003-08-01 22:15:03 +000020#include "Support/Debug.h"
21#include "Support/Statistic.h"
Chris Lattner44457bb2003-05-22 19:34:49 +000022#include <fstream>
23#include <set>
Chris Lattner0b18c1d2002-05-10 15:38:35 +000024
Chris Lattnerb28b6802002-07-23 18:06:35 +000025namespace {
Chris Lattnerbf3a0992002-10-01 22:38:41 +000026 Statistic<> NumFunctions("internalize", "Number of functions internalized");
27 Statistic<> NumGlobals ("internalize", "Number of global vars internalized");
Chris Lattner1b94c002002-04-28 05:43:27 +000028
Chris Lattner44457bb2003-05-22 19:34:49 +000029 // APIFile - A file which contains a list of symbols that should not be marked
30 // external.
31 cl::opt<std::string>
32 APIFile("internalize-public-api-file", cl::value_desc("filename"),
Chris Lattnerad44cd82003-05-22 19:48:00 +000033 cl::desc("A file containing list of symbol names to preserve"));
34
35 // APIList - A list of symbols that should not be marked internal.
36 cl::list<std::string>
37 APIList("internalize-public-api-list", cl::value_desc("list"),
Chris Lattner224ae022003-05-22 20:27:13 +000038 cl::desc("A list of symbol names to preserve"),
39 cl::CommaSeparated);
Chris Lattnerad44cd82003-05-22 19:48:00 +000040
Chris Lattner47cc3662002-07-30 19:48:44 +000041 class InternalizePass : public Pass {
Chris Lattner44457bb2003-05-22 19:34:49 +000042 std::set<std::string> ExternalNames;
43 public:
44 InternalizePass() {
Chris Lattnerad44cd82003-05-22 19:48:00 +000045 if (!APIFile.empty()) // If a filename is specified, use it
Chris Lattner44457bb2003-05-22 19:34:49 +000046 LoadFile(APIFile.c_str());
Chris Lattnerad44cd82003-05-22 19:48:00 +000047 else // Else, if a list is specified, use it.
48 ExternalNames.insert(APIList.begin(), APIList.end());
Chris Lattner44457bb2003-05-22 19:34:49 +000049 }
Chris Lattner17069b32002-11-08 20:34:21 +000050
Chris Lattner44457bb2003-05-22 19:34:49 +000051 void LoadFile(const char *Filename) {
52 // Load the APIFile...
53 std::ifstream In(Filename);
54 if (!In.good()) {
55 std::cerr << "WARNING: Internalize couldn't load file '" << Filename
Chris Lattnerad44cd82003-05-22 19:48:00 +000056 << "'!\n";
Chris Lattner44457bb2003-05-22 19:34:49 +000057 return; // Do not internalize anything...
58 }
59 while (In) {
60 std::string Symbol;
61 In >> Symbol;
62 if (!Symbol.empty())
63 ExternalNames.insert(Symbol);
64 }
65 }
66
67 virtual bool run(Module &M) {
Chris Lattnerad44cd82003-05-22 19:48:00 +000068 // If no list or file of symbols was specified, check to see if there is a
69 // "main" symbol defined in the module. If so, use it, otherwise do not
70 // internalize the module, it must be a library or something.
71 //
72 if (ExternalNames.empty()) {
73 Function *MainFunc = M.getMainFunction();
74 if (MainFunc == 0 || MainFunc->isExternal())
75 return false; // No main found, must be a library...
76
77 // Preserve main, internalize all else.
78 ExternalNames.insert(MainFunc->getName());
79 }
80
Chris Lattner47cc3662002-07-30 19:48:44 +000081 bool Changed = false;
82
83 // Found a main function, mark all functions not named main as internal.
84 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
Chris Lattner44457bb2003-05-22 19:34:49 +000085 if (!I->isExternal() && // Function must be defined here
86 !I->hasInternalLinkage() && // Can't already have internal linkage
87 !ExternalNames.count(I->getName())) {// Not marked to keep external?
Chris Lattner379a8d22003-04-16 20:28:45 +000088 I->setLinkage(GlobalValue::InternalLinkage);
Chris Lattner47cc3662002-07-30 19:48:44 +000089 Changed = true;
90 ++NumFunctions;
91 DEBUG(std::cerr << "Internalizing func " << I->getName() << "\n");
92 }
Chris Lattner1b94c002002-04-28 05:43:27 +000093
Chris Lattner47cc3662002-07-30 19:48:44 +000094 // Mark all global variables with initializers as internal as well...
95 for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
Chris Lattner44457bb2003-05-22 19:34:49 +000096 if (!I->isExternal() && !I->hasInternalLinkage() &&
97 !ExternalNames.count(I->getName())) {
Chris Lattnerfd5d3232003-06-26 05:30:40 +000098 // Special case handling of the global ctor and dtor list. When we
99 // internalize it, we mark it constant, which allows elimination of
100 // the list if it's empty.
101 //
102 if (I->hasAppendingLinkage() && (I->getName() == "llvm.global_ctors"||
103 I->getName() == "llvm.global_dtors"))
104 I->setConstant(true);
105
Chris Lattner379a8d22003-04-16 20:28:45 +0000106 I->setLinkage(GlobalValue::InternalLinkage);
Chris Lattner47cc3662002-07-30 19:48:44 +0000107 Changed = true;
108 ++NumGlobals;
109 DEBUG(std::cerr << "Internalizing gvar " << I->getName() << "\n");
110 }
111
112 return Changed;
113 }
114 };
Chris Lattner1b94c002002-04-28 05:43:27 +0000115
Chris Lattner44457bb2003-05-22 19:34:49 +0000116 RegisterOpt<InternalizePass> X("internalize", "Internalize Global Symbols");
Chris Lattnerb28b6802002-07-23 18:06:35 +0000117} // end anonymous namespace
118
Chris Lattner1b94c002002-04-28 05:43:27 +0000119Pass *createInternalizePass() {
120 return new InternalizePass();
121}