Mercurial > hg > CbC > CbC_llvm
comparison lib/Transforms/IPO/Internalize.cpp @ 0:95c75e76d11b LLVM3.4
LLVM 3.4
author | Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 12 Dec 2013 13:56:28 +0900 |
parents | |
children | e4204d083e25 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:95c75e76d11b |
---|---|
1 //===-- Internalize.cpp - Mark functions internal -------------------------===// | |
2 // | |
3 // The LLVM Compiler Infrastructure | |
4 // | |
5 // This file is distributed under the University of Illinois Open Source | |
6 // License. See LICENSE.TXT for details. | |
7 // | |
8 //===----------------------------------------------------------------------===// | |
9 // | |
10 // This pass loops over all of the functions and variables in the input module. | |
11 // If the function or variable is not in the list of external names given to | |
12 // the pass it is marked as internal. | |
13 // | |
14 // This transformation would not be legal in a regular compilation, but it gets | |
15 // extra information from the linker about what is safe. | |
16 // | |
17 // For example: Internalizing a function with external linkage. Only if we are | |
18 // told it is only used from within this module, it is safe to do it. | |
19 // | |
20 //===----------------------------------------------------------------------===// | |
21 | |
22 #define DEBUG_TYPE "internalize" | |
23 #include "llvm/Transforms/IPO.h" | |
24 #include "llvm/ADT/SmallPtrSet.h" | |
25 #include "llvm/ADT/Statistic.h" | |
26 #include "llvm/Analysis/CallGraph.h" | |
27 #include "llvm/IR/Module.h" | |
28 #include "llvm/Pass.h" | |
29 #include "llvm/Support/CommandLine.h" | |
30 #include "llvm/Support/Debug.h" | |
31 #include "llvm/Support/raw_ostream.h" | |
32 #include "llvm/Transforms/Utils/GlobalStatus.h" | |
33 #include "llvm/Transforms/Utils/ModuleUtils.h" | |
34 #include <fstream> | |
35 #include <set> | |
36 using namespace llvm; | |
37 | |
38 STATISTIC(NumAliases , "Number of aliases internalized"); | |
39 STATISTIC(NumFunctions, "Number of functions internalized"); | |
40 STATISTIC(NumGlobals , "Number of global vars internalized"); | |
41 | |
42 // APIFile - A file which contains a list of symbols that should not be marked | |
43 // external. | |
44 static cl::opt<std::string> | |
45 APIFile("internalize-public-api-file", cl::value_desc("filename"), | |
46 cl::desc("A file containing list of symbol names to preserve")); | |
47 | |
48 // APIList - A list of symbols that should not be marked internal. | |
49 static cl::list<std::string> | |
50 APIList("internalize-public-api-list", cl::value_desc("list"), | |
51 cl::desc("A list of symbol names to preserve"), | |
52 cl::CommaSeparated); | |
53 | |
54 namespace { | |
55 class InternalizePass : public ModulePass { | |
56 std::set<std::string> ExternalNames; | |
57 public: | |
58 static char ID; // Pass identification, replacement for typeid | |
59 explicit InternalizePass(); | |
60 explicit InternalizePass(ArrayRef<const char *> ExportList); | |
61 void LoadFile(const char *Filename); | |
62 virtual bool runOnModule(Module &M); | |
63 | |
64 virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
65 AU.setPreservesCFG(); | |
66 AU.addPreserved<CallGraph>(); | |
67 } | |
68 }; | |
69 } // end anonymous namespace | |
70 | |
71 char InternalizePass::ID = 0; | |
72 INITIALIZE_PASS(InternalizePass, "internalize", | |
73 "Internalize Global Symbols", false, false) | |
74 | |
75 InternalizePass::InternalizePass() | |
76 : ModulePass(ID) { | |
77 initializeInternalizePassPass(*PassRegistry::getPassRegistry()); | |
78 if (!APIFile.empty()) // If a filename is specified, use it. | |
79 LoadFile(APIFile.c_str()); | |
80 ExternalNames.insert(APIList.begin(), APIList.end()); | |
81 } | |
82 | |
83 InternalizePass::InternalizePass(ArrayRef<const char *> ExportList) | |
84 : ModulePass(ID){ | |
85 initializeInternalizePassPass(*PassRegistry::getPassRegistry()); | |
86 for(ArrayRef<const char *>::const_iterator itr = ExportList.begin(); | |
87 itr != ExportList.end(); itr++) { | |
88 ExternalNames.insert(*itr); | |
89 } | |
90 } | |
91 | |
92 void InternalizePass::LoadFile(const char *Filename) { | |
93 // Load the APIFile... | |
94 std::ifstream In(Filename); | |
95 if (!In.good()) { | |
96 errs() << "WARNING: Internalize couldn't load file '" << Filename | |
97 << "'! Continuing as if it's empty.\n"; | |
98 return; // Just continue as if the file were empty | |
99 } | |
100 while (In) { | |
101 std::string Symbol; | |
102 In >> Symbol; | |
103 if (!Symbol.empty()) | |
104 ExternalNames.insert(Symbol); | |
105 } | |
106 } | |
107 | |
108 static bool shouldInternalize(const GlobalValue &GV, | |
109 const std::set<std::string> &ExternalNames) { | |
110 // Function must be defined here | |
111 if (GV.isDeclaration()) | |
112 return false; | |
113 | |
114 // Available externally is really just a "declaration with a body". | |
115 if (GV.hasAvailableExternallyLinkage()) | |
116 return false; | |
117 | |
118 // Already has internal linkage | |
119 if (GV.hasLocalLinkage()) | |
120 return false; | |
121 | |
122 // Marked to keep external? | |
123 if (ExternalNames.count(GV.getName())) | |
124 return false; | |
125 | |
126 return true; | |
127 } | |
128 | |
129 bool InternalizePass::runOnModule(Module &M) { | |
130 CallGraph *CG = getAnalysisIfAvailable<CallGraph>(); | |
131 CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0; | |
132 bool Changed = false; | |
133 | |
134 SmallPtrSet<GlobalValue *, 8> Used; | |
135 collectUsedGlobalVariables(M, Used, false); | |
136 | |
137 // We must assume that globals in llvm.used have a reference that not even | |
138 // the linker can see, so we don't internalize them. | |
139 // For llvm.compiler.used the situation is a bit fuzzy. The assembler and | |
140 // linker can drop those symbols. If this pass is running as part of LTO, | |
141 // one might think that it could just drop llvm.compiler.used. The problem | |
142 // is that even in LTO llvm doesn't see every reference. For example, | |
143 // we don't see references from function local inline assembly. To be | |
144 // conservative, we internalize symbols in llvm.compiler.used, but we | |
145 // keep llvm.compiler.used so that the symbol is not deleted by llvm. | |
146 for (SmallPtrSet<GlobalValue *, 8>::iterator I = Used.begin(), E = Used.end(); | |
147 I != E; ++I) { | |
148 GlobalValue *V = *I; | |
149 ExternalNames.insert(V->getName()); | |
150 } | |
151 | |
152 // Mark all functions not in the api as internal. | |
153 // FIXME: maybe use private linkage? | |
154 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { | |
155 if (!shouldInternalize(*I, ExternalNames)) | |
156 continue; | |
157 | |
158 I->setLinkage(GlobalValue::InternalLinkage); | |
159 | |
160 if (ExternalNode) | |
161 // Remove a callgraph edge from the external node to this function. | |
162 ExternalNode->removeOneAbstractEdgeTo((*CG)[I]); | |
163 | |
164 Changed = true; | |
165 ++NumFunctions; | |
166 DEBUG(dbgs() << "Internalizing func " << I->getName() << "\n"); | |
167 } | |
168 | |
169 // Never internalize the llvm.used symbol. It is used to implement | |
170 // attribute((used)). | |
171 // FIXME: Shouldn't this just filter on llvm.metadata section?? | |
172 ExternalNames.insert("llvm.used"); | |
173 ExternalNames.insert("llvm.compiler.used"); | |
174 | |
175 // Never internalize anchors used by the machine module info, else the info | |
176 // won't find them. (see MachineModuleInfo.) | |
177 ExternalNames.insert("llvm.global_ctors"); | |
178 ExternalNames.insert("llvm.global_dtors"); | |
179 ExternalNames.insert("llvm.global.annotations"); | |
180 | |
181 // Never internalize symbols code-gen inserts. | |
182 // FIXME: We should probably add this (and the __stack_chk_guard) via some | |
183 // type of call-back in CodeGen. | |
184 ExternalNames.insert("__stack_chk_fail"); | |
185 ExternalNames.insert("__stack_chk_guard"); | |
186 | |
187 // Mark all global variables with initializers that are not in the api as | |
188 // internal as well. | |
189 // FIXME: maybe use private linkage? | |
190 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); | |
191 I != E; ++I) { | |
192 if (!shouldInternalize(*I, ExternalNames)) | |
193 continue; | |
194 | |
195 I->setLinkage(GlobalValue::InternalLinkage); | |
196 Changed = true; | |
197 ++NumGlobals; | |
198 DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n"); | |
199 } | |
200 | |
201 // Mark all aliases that are not in the api as internal as well. | |
202 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); | |
203 I != E; ++I) { | |
204 if (!shouldInternalize(*I, ExternalNames)) | |
205 continue; | |
206 | |
207 I->setLinkage(GlobalValue::InternalLinkage); | |
208 Changed = true; | |
209 ++NumAliases; | |
210 DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n"); | |
211 } | |
212 | |
213 return Changed; | |
214 } | |
215 | |
216 ModulePass *llvm::createInternalizePass() { | |
217 return new InternalizePass(); | |
218 } | |
219 | |
220 ModulePass *llvm::createInternalizePass(ArrayRef<const char *> ExportList) { | |
221 return new InternalizePass(ExportList); | |
222 } |