comparison tools/lto/lto.cpp @ 120:1172e4bd9c6f

update 4.0.0
author mir3636
date Fri, 25 Nov 2016 19:14:25 +0900
parents 7d135dc70f03
children 803732b1fca8
comparison
equal deleted inserted replaced
101:34baf5011add 120:1172e4bd9c6f
12 // 12 //
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #include "llvm-c/lto.h" 15 #include "llvm-c/lto.h"
16 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/Bitcode/BitcodeReader.h"
17 #include "llvm/CodeGen/CommandFlags.h" 18 #include "llvm/CodeGen/CommandFlags.h"
18 #include "llvm/IR/DiagnosticInfo.h" 19 #include "llvm/IR/DiagnosticInfo.h"
19 #include "llvm/IR/DiagnosticPrinter.h" 20 #include "llvm/IR/DiagnosticPrinter.h"
20 #include "llvm/IR/LLVMContext.h" 21 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/LTO/LTOCodeGenerator.h" 22 #include "llvm/LTO/legacy/LTOCodeGenerator.h"
22 #include "llvm/LTO/LTOModule.h" 23 #include "llvm/LTO/legacy/LTOModule.h"
24 #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
23 #include "llvm/Support/MemoryBuffer.h" 25 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/Signals.h" 26 #include "llvm/Support/Signals.h"
25 #include "llvm/Support/TargetSelect.h" 27 #include "llvm/Support/TargetSelect.h"
28 #include "llvm/Support/raw_ostream.h"
26 29
27 // extra command-line flags needed for LTOCodeGenerator 30 // extra command-line flags needed for LTOCodeGenerator
28 static cl::opt<char> 31 static cl::opt<char>
29 OptLevel("O", 32 OptLevel("O",
30 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " 33 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
97 InitializeAllTargetMCs(); 100 InitializeAllTargetMCs();
98 InitializeAllAsmParsers(); 101 InitializeAllAsmParsers();
99 InitializeAllAsmPrinters(); 102 InitializeAllAsmPrinters();
100 InitializeAllDisassemblers(); 103 InitializeAllDisassemblers();
101 104
102 LTOContext = &getGlobalContext(); 105 static LLVMContext Context;
106 LTOContext = &Context;
103 LTOContext->setDiagnosticHandler(diagnosticHandler, nullptr, true); 107 LTOContext->setDiagnosticHandler(diagnosticHandler, nullptr, true);
104 initialized = true; 108 initialized = true;
105 } 109 }
106 } 110 }
107 111
114 118
115 // This derived class owns the native object file. This helps implement the 119 // This derived class owns the native object file. This helps implement the
116 // libLTO API semantics, which require that the code generator owns the object 120 // libLTO API semantics, which require that the code generator owns the object
117 // file. 121 // file.
118 struct LibLTOCodeGenerator : LTOCodeGenerator { 122 struct LibLTOCodeGenerator : LTOCodeGenerator {
119 LibLTOCodeGenerator() : LTOCodeGenerator(*LTOContext) { 123 LibLTOCodeGenerator() : LTOCodeGenerator(*LTOContext) { init(); }
120 setDiagnosticHandler(handleLibLTODiagnostic, nullptr); }
121 LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context) 124 LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context)
122 : LTOCodeGenerator(*Context), OwnedContext(std::move(Context)) { 125 : LTOCodeGenerator(*Context), OwnedContext(std::move(Context)) {
123 setDiagnosticHandler(handleLibLTODiagnostic, nullptr); } 126 init();
127 }
124 128
125 // Reset the module first in case MergedModule is created in OwnedContext. 129 // Reset the module first in case MergedModule is created in OwnedContext.
126 // Module must be destructed before its context gets destructed. 130 // Module must be destructed before its context gets destructed.
127 ~LibLTOCodeGenerator() { resetMergedModule(); } 131 ~LibLTOCodeGenerator() { resetMergedModule(); }
128 132
133 void init() { setDiagnosticHandler(handleLibLTODiagnostic, nullptr); }
134
129 std::unique_ptr<MemoryBuffer> NativeObjectFile; 135 std::unique_ptr<MemoryBuffer> NativeObjectFile;
130 std::unique_ptr<LLVMContext> OwnedContext; 136 std::unique_ptr<LLVMContext> OwnedContext;
131 }; 137 };
132 138
133 } 139 }
134 140
135 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t) 141 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t)
142 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThinLTOCodeGenerator, thinlto_code_gen_t)
136 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t) 143 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t)
137 144
138 // Convert the subtarget features into a string to pass to LTOCodeGenerator. 145 // Convert the subtarget features into a string to pass to LTOCodeGenerator.
139 static void lto_add_attrs(lto_code_gen_t cg) { 146 static void lto_add_attrs(lto_code_gen_t cg) {
140 LTOCodeGenerator *CG = unwrap(cg); 147 LTOCodeGenerator *CG = unwrap(cg);
144 if (i > 0) 151 if (i > 0)
145 attrs.append(","); 152 attrs.append(",");
146 attrs.append(MAttrs[i]); 153 attrs.append(MAttrs[i]);
147 } 154 }
148 155
149 CG->setAttr(attrs.c_str()); 156 CG->setAttr(attrs);
150 } 157 }
151 158
152 if (OptLevel < '0' || OptLevel > '3') 159 if (OptLevel < '0' || OptLevel > '3')
153 report_fatal_error("Optimization level must be between 0 and 3"); 160 report_fatal_error("Optimization level must be between 0 and 3");
154 CG->setOptLevel(OptLevel - '0'); 161 CG->setOptLevel(OptLevel - '0');
161 const char* lto_get_error_message() { 168 const char* lto_get_error_message() {
162 return sLastErrorString.c_str(); 169 return sLastErrorString.c_str();
163 } 170 }
164 171
165 bool lto_module_is_object_file(const char* path) { 172 bool lto_module_is_object_file(const char* path) {
166 return LTOModule::isBitcodeFile(path); 173 return LTOModule::isBitcodeFile(StringRef(path));
167 } 174 }
168 175
169 bool lto_module_is_object_file_for_target(const char* path, 176 bool lto_module_is_object_file_for_target(const char* path,
170 const char* target_triplet_prefix) { 177 const char* target_triplet_prefix) {
171 ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(path); 178 ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(path);
172 if (!Buffer) 179 if (!Buffer)
173 return false; 180 return false;
174 return LTOModule::isBitcodeForTarget(Buffer->get(), target_triplet_prefix); 181 return LTOModule::isBitcodeForTarget(Buffer->get(),
182 StringRef(target_triplet_prefix));
183 }
184
185 bool lto_module_has_objc_category(const void *mem, size_t length) {
186 std::unique_ptr<MemoryBuffer> Buffer(LTOModule::makeBuffer(mem, length));
187 if (!Buffer)
188 return false;
189 LLVMContext Ctx;
190 ErrorOr<bool> Result = expectedToErrorOrAndEmitErrors(
191 Ctx, llvm::isBitcodeContainingObjCCategory(*Buffer));
192 return Result && *Result;
175 } 193 }
176 194
177 bool lto_module_is_object_file_in_memory(const void* mem, size_t length) { 195 bool lto_module_is_object_file_in_memory(const void* mem, size_t length) {
178 return LTOModule::isBitcodeFile(mem, length); 196 return LTOModule::isBitcodeFile(mem, length);
179 } 197 }
183 size_t length, 201 size_t length,
184 const char* target_triplet_prefix) { 202 const char* target_triplet_prefix) {
185 std::unique_ptr<MemoryBuffer> buffer(LTOModule::makeBuffer(mem, length)); 203 std::unique_ptr<MemoryBuffer> buffer(LTOModule::makeBuffer(mem, length));
186 if (!buffer) 204 if (!buffer)
187 return false; 205 return false;
188 return LTOModule::isBitcodeForTarget(buffer.get(), target_triplet_prefix); 206 return LTOModule::isBitcodeForTarget(buffer.get(),
207 StringRef(target_triplet_prefix));
189 } 208 }
190 209
191 lto_module_t lto_module_create(const char* path) { 210 lto_module_t lto_module_create(const char* path) {
192 lto_initialize(); 211 lto_initialize();
193 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 212 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
194 ErrorOr<std::unique_ptr<LTOModule>> M = 213 ErrorOr<std::unique_ptr<LTOModule>> M =
195 LTOModule::createFromFile(*LTOContext, path, Options); 214 LTOModule::createFromFile(*LTOContext, StringRef(path), Options);
196 if (!M) 215 if (!M)
197 return nullptr; 216 return nullptr;
198 return wrap(M->release()); 217 return wrap(M->release());
199 } 218 }
200 219
201 lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) { 220 lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {
202 lto_initialize(); 221 lto_initialize();
203 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 222 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
204 ErrorOr<std::unique_ptr<LTOModule>> M = 223 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFile(
205 LTOModule::createFromOpenFile(*LTOContext, fd, path, size, Options); 224 *LTOContext, fd, StringRef(path), size, Options);
206 if (!M) 225 if (!M)
207 return nullptr; 226 return nullptr;
208 return wrap(M->release()); 227 return wrap(M->release());
209 } 228 }
210 229
213 size_t map_size, 232 size_t map_size,
214 off_t offset) { 233 off_t offset) {
215 lto_initialize(); 234 lto_initialize();
216 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 235 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
217 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFileSlice( 236 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFileSlice(
218 *LTOContext, fd, path, map_size, offset, Options); 237 *LTOContext, fd, StringRef(path), map_size, offset, Options);
219 if (!M) 238 if (!M)
220 return nullptr; 239 return nullptr;
221 return wrap(M->release()); 240 return wrap(M->release());
222 } 241 }
223 242
234 lto_module_t lto_module_create_from_memory_with_path(const void* mem, 253 lto_module_t lto_module_create_from_memory_with_path(const void* mem,
235 size_t length, 254 size_t length,
236 const char *path) { 255 const char *path) {
237 lto_initialize(); 256 lto_initialize();
238 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 257 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
239 ErrorOr<std::unique_ptr<LTOModule>> M = 258 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer(
240 LTOModule::createFromBuffer(*LTOContext, mem, length, Options, path); 259 *LTOContext, mem, length, Options, StringRef(path));
241 if (!M) 260 if (!M)
242 return nullptr; 261 return nullptr;
243 return wrap(M->release()); 262 return wrap(M->release());
244 } 263 }
245 264
246 lto_module_t lto_module_create_in_local_context(const void *mem, size_t length, 265 lto_module_t lto_module_create_in_local_context(const void *mem, size_t length,
247 const char *path) { 266 const char *path) {
248 lto_initialize(); 267 lto_initialize();
249 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 268 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
250 ErrorOr<std::unique_ptr<LTOModule>> M = 269
251 LTOModule::createInLocalContext(mem, length, Options, path); 270 // Create a local context. Ownership will be transfered to LTOModule.
271 std::unique_ptr<LLVMContext> Context = llvm::make_unique<LLVMContext>();
272 Context->setDiagnosticHandler(diagnosticHandler, nullptr, true);
273
274 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createInLocalContext(
275 std::move(Context), mem, length, Options, StringRef(path));
252 if (!M) 276 if (!M)
253 return nullptr; 277 return nullptr;
254 return wrap(M->release()); 278 return wrap(M->release());
255 } 279 }
256 280
258 size_t length, 282 size_t length,
259 const char *path, 283 const char *path,
260 lto_code_gen_t cg) { 284 lto_code_gen_t cg) {
261 lto_initialize(); 285 lto_initialize();
262 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 286 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
263 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createInContext( 287 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer(
264 mem, length, Options, path, &unwrap(cg)->getContext()); 288 unwrap(cg)->getContext(), mem, length, Options, StringRef(path));
265 return wrap(M->release()); 289 return wrap(M->release());
266 } 290 }
267 291
268 void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); } 292 void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); }
269 293
270 const char* lto_module_get_target_triple(lto_module_t mod) { 294 const char* lto_module_get_target_triple(lto_module_t mod) {
271 return unwrap(mod)->getTargetTriple().c_str(); 295 return unwrap(mod)->getTargetTriple().c_str();
272 } 296 }
273 297
274 void lto_module_set_target_triple(lto_module_t mod, const char *triple) { 298 void lto_module_set_target_triple(lto_module_t mod, const char *triple) {
275 return unwrap(mod)->setTargetTriple(triple); 299 return unwrap(mod)->setTargetTriple(StringRef(triple));
276 } 300 }
277 301
278 unsigned int lto_module_get_num_symbols(lto_module_t mod) { 302 unsigned int lto_module_get_num_symbols(lto_module_t mod) {
279 return unwrap(mod)->getSymbolCount(); 303 return unwrap(mod)->getSymbolCount();
280 } 304 }
281 305
282 const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) { 306 const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) {
283 return unwrap(mod)->getSymbolName(index); 307 return unwrap(mod)->getSymbolName(index).data();
284 } 308 }
285 309
286 lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod, 310 lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,
287 unsigned int index) { 311 unsigned int index) {
288 return unwrap(mod)->getSymbolAttributes(index); 312 return unwrap(mod)->getSymbolAttributes(index);
289 } 313 }
290 314
291 const char* lto_module_get_linkeropts(lto_module_t mod) { 315 const char* lto_module_get_linkeropts(lto_module_t mod) {
292 return unwrap(mod)->getLinkerOpts(); 316 return unwrap(mod)->getLinkerOpts().data();
293 } 317 }
294 318
295 void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg, 319 void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
296 lto_diagnostic_handler_t diag_handler, 320 lto_diagnostic_handler_t diag_handler,
297 void *ctxt) { 321 void *ctxt) {
343 return false; 367 return false;
344 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: 368 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
345 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC); 369 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
346 return false; 370 return false;
347 case LTO_CODEGEN_PIC_MODEL_DEFAULT: 371 case LTO_CODEGEN_PIC_MODEL_DEFAULT:
348 unwrap(cg)->setCodePICModel(Reloc::Default); 372 unwrap(cg)->setCodePICModel(None);
349 return false; 373 return false;
350 } 374 }
351 sLastErrorString = "Unknown PIC model"; 375 sLastErrorString = "Unknown PIC model";
352 return true; 376 return true;
353 } 377 }
431 455
432 void lto_codegen_set_should_embed_uselists(lto_code_gen_t cg, 456 void lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
433 lto_bool_t ShouldEmbedUselists) { 457 lto_bool_t ShouldEmbedUselists) {
434 unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists); 458 unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists);
435 } 459 }
460
461 // ThinLTO API below
462
463 thinlto_code_gen_t thinlto_create_codegen(void) {
464 lto_initialize();
465 ThinLTOCodeGenerator *CodeGen = new ThinLTOCodeGenerator();
466 CodeGen->setTargetOptions(InitTargetOptionsFromCodeGenFlags());
467
468 return wrap(CodeGen);
469 }
470
471 void thinlto_codegen_dispose(thinlto_code_gen_t cg) { delete unwrap(cg); }
472
473 void thinlto_codegen_add_module(thinlto_code_gen_t cg, const char *Identifier,
474 const char *Data, int Length) {
475 unwrap(cg)->addModule(Identifier, StringRef(Data, Length));
476 }
477
478 void thinlto_codegen_process(thinlto_code_gen_t cg) { unwrap(cg)->run(); }
479
480 unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg) {
481 return unwrap(cg)->getProducedBinaries().size();
482 }
483 LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg,
484 unsigned int index) {
485 assert(index < unwrap(cg)->getProducedBinaries().size() && "Index overflow");
486 auto &MemBuffer = unwrap(cg)->getProducedBinaries()[index];
487 return LTOObjectBuffer{MemBuffer->getBufferStart(),
488 MemBuffer->getBufferSize()};
489 }
490
491 void thinlto_codegen_disable_codegen(thinlto_code_gen_t cg,
492 lto_bool_t disable) {
493 unwrap(cg)->disableCodeGen(disable);
494 }
495
496 void thinlto_codegen_set_codegen_only(thinlto_code_gen_t cg,
497 lto_bool_t CodeGenOnly) {
498 unwrap(cg)->setCodeGenOnly(CodeGenOnly);
499 }
500
501 void thinlto_debug_options(const char *const *options, int number) {
502 // if options were requested, set them
503 if (number && options) {
504 std::vector<const char *> CodegenArgv(1, "libLTO");
505 for (auto Arg : ArrayRef<const char *>(options, number))
506 CodegenArgv.push_back(Arg);
507 cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data());
508 }
509 }
510
511 lto_bool_t lto_module_is_thinlto(lto_module_t mod) {
512 return unwrap(mod)->isThinLTO();
513 }
514
515 void thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg,
516 const char *Name, int Length) {
517 unwrap(cg)->preserveSymbol(StringRef(Name, Length));
518 }
519
520 void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,
521 const char *Name, int Length) {
522 unwrap(cg)->crossReferenceSymbol(StringRef(Name, Length));
523 }
524
525 void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu) {
526 return unwrap(cg)->setCpu(cpu);
527 }
528
529 void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
530 const char *cache_dir) {
531 return unwrap(cg)->setCacheDir(cache_dir);
532 }
533
534 void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
535 int interval) {
536 return unwrap(cg)->setCachePruningInterval(interval);
537 }
538
539 void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
540 unsigned expiration) {
541 return unwrap(cg)->setCacheEntryExpiration(expiration);
542 }
543
544 void thinlto_codegen_set_final_cache_size_relative_to_available_space(
545 thinlto_code_gen_t cg, unsigned Percentage) {
546 return unwrap(cg)->setMaxCacheSizeRelativeToAvailableSpace(Percentage);
547 }
548
549 void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,
550 const char *save_temps_dir) {
551 return unwrap(cg)->setSaveTempsDir(save_temps_dir);
552 }
553
554 lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,
555 lto_codegen_model model) {
556 switch (model) {
557 case LTO_CODEGEN_PIC_MODEL_STATIC:
558 unwrap(cg)->setCodePICModel(Reloc::Static);
559 return false;
560 case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
561 unwrap(cg)->setCodePICModel(Reloc::PIC_);
562 return false;
563 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
564 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
565 return false;
566 case LTO_CODEGEN_PIC_MODEL_DEFAULT:
567 unwrap(cg)->setCodePICModel(None);
568 return false;
569 }
570 sLastErrorString = "Unknown PIC model";
571 return true;
572 }