llvm.org GIT mirror llvm / 67af045
LTO: add API to set strategy for -internalize Add API to LTOCodeGenerator to specify a strategy for the -internalize pass. This is a new attempt at Bill's change in r185882, which he reverted in r188029 due to problems with the gold linker. This puts the onus on the linker to decide whether (and what) to internalize. In particular, running internalize before outputting an object file may change a 'weak' symbol into an internal one, even though that symbol could be needed by an external object file --- e.g., with arclite. This patch enables three strategies: - LTO_INTERNALIZE_FULL: the default (and the old behaviour). - LTO_INTERNALIZE_NONE: skip -internalize. - LTO_INTERNALIZE_HIDDEN: only -internalize symbols with hidden visibility. LTO_INTERNALIZE_FULL should be used when linking an executable. Outputting an object file (e.g., via ld -r) is more complicated, and depends on whether hidden symbols should be internalized. E.g., for ld -r, LTO_INTERNALIZE_NONE can be used when -keep_private_externs, and LTO_INTERNALIZE_HIDDEN can be used otherwise. However, LTO_INTERNALIZE_FULL is inappropriate, since the output object file will eventually need to link with others. lto_codegen_set_internalize_strategy() sets the strategy for subsequent calls to lto_codegen_write_merged_modules() and lto_codegen_compile*(). <rdar://problem/14334895> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199191 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 6 years ago
6 changed file(s) with 77 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
6969 void setTargetOptions(llvm::TargetOptions options);
7070 void setDebugInfo(lto_debug_model);
7171 void setCodePICModel(lto_codegen_model);
72 void setInternalizeStrategy(lto_internalize_strategy);
7273
7374 void setCpu(const char *mCpu) { MCpu = mCpu; }
7475
113114 bool disableGVNLoadPRE,
114115 std::string &errMsg);
115116
117 bool shouldInternalize() const {
118 return InternalizeStrategy != LTO_INTERNALIZE_NONE;
119 }
120
121 bool shouldOnlyInternalizeHidden() const {
122 return InternalizeStrategy == LTO_INTERNALIZE_HIDDEN;
123 }
124
116125 private:
117126 void initializeLTOPasses();
118127
137146 bool EmitDwarfDebugInfo;
138147 bool ScopeRestrictionsDone;
139148 lto_codegen_model CodeModel;
149 lto_internalize_strategy InternalizeStrategy;
140150 StringSet MustPreserveSymbols;
141151 StringSet AsmUndefinedRefs;
142152 llvm::MemoryBuffer *NativeObjectFile;
107107 ////
108108 /// The symbols in \p ExportList are never internalized.
109109 ///
110 /// When OnlyHidden=true, only symbols with hidden visibility are internalized.
111 ///
110112 /// The symbol in DSOList are internalized if it is safe to drop them from
111113 /// the symbol table.
112114 ///
113115 /// Note that commandline options that are used with the above function are not
114116 /// used now!
115 ModulePass *createInternalizePass(ArrayRef ExportList);
117 ModulePass *createInternalizePass(ArrayRef ExportList,
118 bool OnlyHidden = false);
116119 /// createInternalizePass - Same as above, but with an empty exportList.
117 ModulePass *createInternalizePass();
120 ModulePass *createInternalizePass(bool OnlyHidden = false);
118121
119122 //===----------------------------------------------------------------------===//
120123 /// createDeadArgEliminationPass - This pass removes arguments from functions
3939 * @{
4040 */
4141
42 #define LTO_API_VERSION 5
42 #define LTO_API_VERSION 6
4343
4444 typedef enum {
4545 LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */
7272 LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC = 2
7373 } lto_codegen_model;
7474
75 typedef enum {
76 LTO_INTERNALIZE_FULL = 0,
77 LTO_INTERNALIZE_NONE = 1,
78 LTO_INTERNALIZE_HIDDEN = 2
79 } lto_internalize_strategy;
7580
7681 /** opaque reference to a loaded object module */
7782 typedef struct LTOModule* lto_module_t;
261266 extern void
262267 lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
263268 int nargs);
269
270 /**
271 * Sets the strategy to use during internalize. Default strategy is
272 * LTO_INTERNALIZE_FULL.
273 */
274 extern void
275 lto_codegen_set_internalize_strategy(lto_code_gen_t cg,
276 lto_internalize_strategy);
264277
265278 /**
266279 * Tells LTO optimization passes that this symbol must be preserved
6161 LTOCodeGenerator::LTOCodeGenerator()
6262 : Context(getGlobalContext()), Linker(new Module("ld-temp.o", Context)),
6363 TargetMach(NULL), EmitDwarfDebugInfo(false), ScopeRestrictionsDone(false),
64 CodeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), NativeObjectFile(NULL) {
64 CodeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
65 InternalizeStrategy(LTO_INTERNALIZE_FULL), NativeObjectFile(NULL) {
6566 initializeLTOPasses();
6667 }
6768
163164 llvm_unreachable("Unknown PIC model!");
164165 }
165166
167 void
168 LTOCodeGenerator::setInternalizeStrategy(lto_internalize_strategy Strategy) {
169 switch (Strategy) {
170 case LTO_INTERNALIZE_FULL:
171 case LTO_INTERNALIZE_NONE:
172 case LTO_INTERNALIZE_HIDDEN:
173 InternalizeStrategy = Strategy;
174 return;
175 }
176 llvm_unreachable("Unknown internalize strategy!");
177 }
178
166179 bool LTOCodeGenerator::writeMergedModules(const char *path,
167180 std::string &errMsg) {
168181 if (!determineTarget(errMsg))
376389 }
377390
378391 void LTOCodeGenerator::applyScopeRestrictions() {
379 if (ScopeRestrictionsDone)
392 if (ScopeRestrictionsDone || !shouldInternalize())
380393 return;
381394 Module *mergedModule = Linker.getModule();
382395
428441 LLVMCompilerUsed->setSection("llvm.metadata");
429442 }
430443
431 passes.add(createInternalizePass(MustPreserveList));
444 passes.add(
445 createInternalizePass(MustPreserveList, shouldOnlyInternalizeHidden()));
432446
433447 // apply scope restrictions
434448 passes.run(*mergedModule);
5353 namespace {
5454 class InternalizePass : public ModulePass {
5555 std::set ExternalNames;
56 bool OnlyHidden;
5657 public:
5758 static char ID; // Pass identification, replacement for typeid
58 explicit InternalizePass();
59 explicit InternalizePass(ArrayRef ExportList);
59 explicit InternalizePass(bool OnlyHidden = false);
60 explicit InternalizePass(ArrayRef ExportList, bool OnlyHidden);
6061 void LoadFile(const char *Filename);
6162 virtual bool runOnModule(Module &M);
6263
7172 INITIALIZE_PASS(InternalizePass, "internalize",
7273 "Internalize Global Symbols", false, false)
7374
74 InternalizePass::InternalizePass()
75 : ModulePass(ID) {
75 InternalizePass::InternalizePass(bool OnlyHidden)
76 : ModulePass(ID), OnlyHidden(OnlyHidden) {
7677 initializeInternalizePassPass(*PassRegistry::getPassRegistry());
7778 if (!APIFile.empty()) // If a filename is specified, use it.
7879 LoadFile(APIFile.c_str());
7980 ExternalNames.insert(APIList.begin(), APIList.end());
8081 }
8182
82 InternalizePass::InternalizePass(ArrayRef ExportList)
83 : ModulePass(ID){
83 InternalizePass::InternalizePass(ArrayRef ExportList,
84 bool OnlyHidden)
85 : ModulePass(ID), OnlyHidden(OnlyHidden) {
8486 initializeInternalizePassPass(*PassRegistry::getPassRegistry());
8587 for(ArrayRef::const_iterator itr = ExportList.begin();
8688 itr != ExportList.end(); itr++) {
105107 }
106108
107109 static bool shouldInternalize(const GlobalValue &GV,
108 const std::set &ExternalNames) {
110 const std::set &ExternalNames,
111 bool OnlyHidden) {
112 if (OnlyHidden && !GV.hasHiddenVisibility())
113 return false;
114
109115 // Function must be defined here
110116 if (GV.isDeclaration())
111117 return false;
154160 }
155161
156162 // Mark all functions not in the api as internal.
157 // FIXME: maybe use private linkage?
158163 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
159 if (!shouldInternalize(*I, ExternalNames))
164 if (!shouldInternalize(*I, ExternalNames, OnlyHidden))
160165 continue;
161166
162167 I->setLinkage(GlobalValue::InternalLinkage);
190195
191196 // Mark all global variables with initializers that are not in the api as
192197 // internal as well.
193 // FIXME: maybe use private linkage?
194198 for (Module::global_iterator I = M.global_begin(), E = M.global_end();
195199 I != E; ++I) {
196 if (!shouldInternalize(*I, ExternalNames))
200 if (!shouldInternalize(*I, ExternalNames, OnlyHidden))
197201 continue;
198202
199203 I->setLinkage(GlobalValue::InternalLinkage);
205209 // Mark all aliases that are not in the api as internal as well.
206210 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
207211 I != E; ++I) {
208 if (!shouldInternalize(*I, ExternalNames))
212 if (!shouldInternalize(*I, ExternalNames, OnlyHidden))
209213 continue;
210214
211215 I->setLinkage(GlobalValue::InternalLinkage);
217221 return Changed;
218222 }
219223
220 ModulePass *llvm::createInternalizePass() {
221 return new InternalizePass();
222 }
223
224 ModulePass *llvm::createInternalizePass(ArrayRef ExportList) {
225 return new InternalizePass(ExportList);
226 }
224 ModulePass *llvm::createInternalizePass(bool OnlyHidden) {
225 return new InternalizePass(OnlyHidden);
226 }
227
228 ModulePass *llvm::createInternalizePass(ArrayRef ExportList,
229 bool OnlyHidden) {
230 return new InternalizePass(ExportList, OnlyHidden);
231 }
251251 // In here only for backwards compatibility. We use MC now.
252252 }
253253
254 /// lto_codegen_set_internalize_strategy - Sets the strategy to use during
255 /// internalize.
256 void lto_codegen_set_internalize_strategy(lto_code_gen_t cg,
257 lto_internalize_strategy strategy) {
258 cg->setInternalizeStrategy(strategy);
259 }
260
254261 /// lto_codegen_add_must_preserve_symbol - Adds to a list of all global symbols
255262 /// that must exist in the final generated code. If a function is not listed
256263 /// there, it might be inlined into every usage and optimized away.