1 //===-lto.cpp - LLVM Link Time Optimizer ----------------------------------===// 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 file implements the Link Time Optimization library. This library is 11 // intended to be used by linker to optimize code at link time. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm-c/lto.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/Bitcode/BitcodeReader.h" 18 #include "llvm/CodeGen/CommandFlags.inc" 19 #include "llvm/IR/DiagnosticInfo.h" 20 #include "llvm/IR/DiagnosticPrinter.h" 21 #include "llvm/IR/LLVMContext.h" 22 #include "llvm/LTO/legacy/LTOCodeGenerator.h" 23 #include "llvm/LTO/legacy/LTOModule.h" 24 #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h" 25 #include "llvm/Support/MemoryBuffer.h" 26 #include "llvm/Support/Signals.h" 27 #include "llvm/Support/TargetSelect.h" 28 #include "llvm/Support/raw_ostream.h" 29 30 // extra command-line flags needed for LTOCodeGenerator 31 static cl::opt<char> 32 OptLevel("O", 33 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " 34 "(default = '-O2')"), 35 cl::Prefix, 36 cl::ZeroOrMore, 37 cl::init('2')); 38 39 static cl::opt<bool> 40 DisableInline("disable-inlining", cl::init(false), 41 cl::desc("Do not run the inliner pass")); 42 43 static cl::opt<bool> 44 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), 45 cl::desc("Do not run the GVN load PRE pass")); 46 47 static cl::opt<bool> DisableLTOVectorization( 48 "disable-lto-vectorization", cl::init(false), 49 cl::desc("Do not run loop or slp vectorization during LTO")); 50 51 static cl::opt<bool> EnableFreestanding( 52 "lto-freestanding", cl::init(false), 53 cl::desc("Enable Freestanding (disable builtins / TLI) during LTO")); 54 55 #ifdef NDEBUG 56 static bool VerifyByDefault = false; 57 #else 58 static bool VerifyByDefault = true; 59 #endif 60 61 static cl::opt<bool> DisableVerify( 62 "disable-llvm-verifier", cl::init(!VerifyByDefault), 63 cl::desc("Don't run the LLVM verifier during the optimization pipeline")); 64 65 // Holds most recent error string. 66 // *** Not thread safe *** 67 static std::string sLastErrorString; 68 69 // Holds the initialization state of the LTO module. 70 // *** Not thread safe *** 71 static bool initialized = false; 72 73 // Holds the command-line option parsing state of the LTO module. 74 static bool parsedOptions = false; 75 76 static LLVMContext *LTOContext = nullptr; 77 78 struct LTOToolDiagnosticHandler : public DiagnosticHandler { 79 bool handleDiagnostics(const DiagnosticInfo &DI) override { 80 if (DI.getSeverity() != DS_Error) { 81 DiagnosticPrinterRawOStream DP(errs()); 82 DI.print(DP); 83 errs() << '\n'; 84 return true; 85 } 86 sLastErrorString = ""; 87 { 88 raw_string_ostream Stream(sLastErrorString); 89 DiagnosticPrinterRawOStream DP(Stream); 90 DI.print(DP); 91 } 92 return true; 93 } 94 }; 95 96 // Initialize the configured targets if they have not been initialized. 97 static void lto_initialize() { 98 if (!initialized) { 99 #ifdef _WIN32 100 // Dialog box on crash disabling doesn't work across DLL boundaries, so do 101 // it here. 102 llvm::sys::DisableSystemDialogsOnCrash(); 103 #endif 104 105 InitializeAllTargetInfos(); 106 InitializeAllTargets(); 107 InitializeAllTargetMCs(); 108 InitializeAllAsmParsers(); 109 InitializeAllAsmPrinters(); 110 InitializeAllDisassemblers(); 111 112 static LLVMContext Context; 113 LTOContext = &Context; 114 LTOContext->setDiagnosticHandler( 115 llvm::make_unique<LTOToolDiagnosticHandler>(), true); 116 initialized = true; 117 } 118 } 119 120 namespace { 121 122 static void handleLibLTODiagnostic(lto_codegen_diagnostic_severity_t Severity, 123 const char *Msg, void *) { 124 sLastErrorString = Msg; 125 } 126 127 // This derived class owns the native object file. This helps implement the 128 // libLTO API semantics, which require that the code generator owns the object 129 // file. 130 struct LibLTOCodeGenerator : LTOCodeGenerator { 131 LibLTOCodeGenerator() : LTOCodeGenerator(*LTOContext) { init(); } 132 LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context) 133 : LTOCodeGenerator(*Context), OwnedContext(std::move(Context)) { 134 init(); 135 } 136 137 // Reset the module first in case MergedModule is created in OwnedContext. 138 // Module must be destructed before its context gets destructed. 139 ~LibLTOCodeGenerator() { resetMergedModule(); } 140 141 void init() { setDiagnosticHandler(handleLibLTODiagnostic, nullptr); } 142 143 std::unique_ptr<MemoryBuffer> NativeObjectFile; 144 std::unique_ptr<LLVMContext> OwnedContext; 145 }; 146 147 } 148 149 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t) 150 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThinLTOCodeGenerator, thinlto_code_gen_t) 151 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t) 152 153 // Convert the subtarget features into a string to pass to LTOCodeGenerator. 154 static void lto_add_attrs(lto_code_gen_t cg) { 155 LTOCodeGenerator *CG = unwrap(cg); 156 if (MAttrs.size()) { 157 std::string attrs; 158 for (unsigned i = 0; i < MAttrs.size(); ++i) { 159 if (i > 0) 160 attrs.append(","); 161 attrs.append(MAttrs[i]); 162 } 163 164 CG->setAttr(attrs); 165 } 166 167 if (OptLevel < '0' || OptLevel > '3') 168 report_fatal_error("Optimization level must be between 0 and 3"); 169 CG->setOptLevel(OptLevel - '0'); 170 CG->setFreestanding(EnableFreestanding); 171 } 172 173 extern const char* lto_get_version() { 174 return LTOCodeGenerator::getVersionString(); 175 } 176 177 const char* lto_get_error_message() { 178 return sLastErrorString.c_str(); 179 } 180 181 bool lto_module_is_object_file(const char* path) { 182 return LTOModule::isBitcodeFile(StringRef(path)); 183 } 184 185 bool lto_module_is_object_file_for_target(const char* path, 186 const char* target_triplet_prefix) { 187 ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(path); 188 if (!Buffer) 189 return false; 190 return LTOModule::isBitcodeForTarget(Buffer->get(), 191 StringRef(target_triplet_prefix)); 192 } 193 194 bool lto_module_has_objc_category(const void *mem, size_t length) { 195 std::unique_ptr<MemoryBuffer> Buffer(LTOModule::makeBuffer(mem, length)); 196 if (!Buffer) 197 return false; 198 LLVMContext Ctx; 199 ErrorOr<bool> Result = expectedToErrorOrAndEmitErrors( 200 Ctx, llvm::isBitcodeContainingObjCCategory(*Buffer)); 201 return Result && *Result; 202 } 203 204 bool lto_module_is_object_file_in_memory(const void* mem, size_t length) { 205 return LTOModule::isBitcodeFile(mem, length); 206 } 207 208 bool 209 lto_module_is_object_file_in_memory_for_target(const void* mem, 210 size_t length, 211 const char* target_triplet_prefix) { 212 std::unique_ptr<MemoryBuffer> buffer(LTOModule::makeBuffer(mem, length)); 213 if (!buffer) 214 return false; 215 return LTOModule::isBitcodeForTarget(buffer.get(), 216 StringRef(target_triplet_prefix)); 217 } 218 219 lto_module_t lto_module_create(const char* path) { 220 lto_initialize(); 221 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 222 ErrorOr<std::unique_ptr<LTOModule>> M = 223 LTOModule::createFromFile(*LTOContext, StringRef(path), Options); 224 if (!M) 225 return nullptr; 226 return wrap(M->release()); 227 } 228 229 lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) { 230 lto_initialize(); 231 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 232 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFile( 233 *LTOContext, fd, StringRef(path), size, Options); 234 if (!M) 235 return nullptr; 236 return wrap(M->release()); 237 } 238 239 lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path, 240 size_t file_size, 241 size_t map_size, 242 off_t offset) { 243 lto_initialize(); 244 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 245 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFileSlice( 246 *LTOContext, fd, StringRef(path), map_size, offset, Options); 247 if (!M) 248 return nullptr; 249 return wrap(M->release()); 250 } 251 252 lto_module_t lto_module_create_from_memory(const void* mem, size_t length) { 253 lto_initialize(); 254 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 255 ErrorOr<std::unique_ptr<LTOModule>> M = 256 LTOModule::createFromBuffer(*LTOContext, mem, length, Options); 257 if (!M) 258 return nullptr; 259 return wrap(M->release()); 260 } 261 262 lto_module_t lto_module_create_from_memory_with_path(const void* mem, 263 size_t length, 264 const char *path) { 265 lto_initialize(); 266 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 267 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer( 268 *LTOContext, mem, length, Options, StringRef(path)); 269 if (!M) 270 return nullptr; 271 return wrap(M->release()); 272 } 273 274 lto_module_t lto_module_create_in_local_context(const void *mem, size_t length, 275 const char *path) { 276 lto_initialize(); 277 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 278 279 // Create a local context. Ownership will be transferred to LTOModule. 280 std::unique_ptr<LLVMContext> Context = llvm::make_unique<LLVMContext>(); 281 Context->setDiagnosticHandler(llvm::make_unique<LTOToolDiagnosticHandler>(), 282 true); 283 284 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createInLocalContext( 285 std::move(Context), mem, length, Options, StringRef(path)); 286 if (!M) 287 return nullptr; 288 return wrap(M->release()); 289 } 290 291 lto_module_t lto_module_create_in_codegen_context(const void *mem, 292 size_t length, 293 const char *path, 294 lto_code_gen_t cg) { 295 lto_initialize(); 296 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 297 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer( 298 unwrap(cg)->getContext(), mem, length, Options, StringRef(path)); 299 return wrap(M->release()); 300 } 301 302 void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); } 303 304 const char* lto_module_get_target_triple(lto_module_t mod) { 305 return unwrap(mod)->getTargetTriple().c_str(); 306 } 307 308 void lto_module_set_target_triple(lto_module_t mod, const char *triple) { 309 return unwrap(mod)->setTargetTriple(StringRef(triple)); 310 } 311 312 unsigned int lto_module_get_num_symbols(lto_module_t mod) { 313 return unwrap(mod)->getSymbolCount(); 314 } 315 316 const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) { 317 return unwrap(mod)->getSymbolName(index).data(); 318 } 319 320 lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod, 321 unsigned int index) { 322 return unwrap(mod)->getSymbolAttributes(index); 323 } 324 325 const char* lto_module_get_linkeropts(lto_module_t mod) { 326 return unwrap(mod)->getLinkerOpts().data(); 327 } 328 329 void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg, 330 lto_diagnostic_handler_t diag_handler, 331 void *ctxt) { 332 unwrap(cg)->setDiagnosticHandler(diag_handler, ctxt); 333 } 334 335 static lto_code_gen_t createCodeGen(bool InLocalContext) { 336 lto_initialize(); 337 338 TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 339 340 LibLTOCodeGenerator *CodeGen = 341 InLocalContext ? new LibLTOCodeGenerator(make_unique<LLVMContext>()) 342 : new LibLTOCodeGenerator(); 343 CodeGen->setTargetOptions(Options); 344 return wrap(CodeGen); 345 } 346 347 lto_code_gen_t lto_codegen_create(void) { 348 return createCodeGen(/* InLocalContext */ false); 349 } 350 351 lto_code_gen_t lto_codegen_create_in_local_context(void) { 352 return createCodeGen(/* InLocalContext */ true); 353 } 354 355 void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); } 356 357 bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) { 358 return !unwrap(cg)->addModule(unwrap(mod)); 359 } 360 361 void lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod) { 362 unwrap(cg)->setModule(std::unique_ptr<LTOModule>(unwrap(mod))); 363 } 364 365 bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) { 366 unwrap(cg)->setDebugInfo(debug); 367 return false; 368 } 369 370 bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) { 371 switch (model) { 372 case LTO_CODEGEN_PIC_MODEL_STATIC: 373 unwrap(cg)->setCodePICModel(Reloc::Static); 374 return false; 375 case LTO_CODEGEN_PIC_MODEL_DYNAMIC: 376 unwrap(cg)->setCodePICModel(Reloc::PIC_); 377 return false; 378 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: 379 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC); 380 return false; 381 case LTO_CODEGEN_PIC_MODEL_DEFAULT: 382 unwrap(cg)->setCodePICModel(None); 383 return false; 384 } 385 sLastErrorString = "Unknown PIC model"; 386 return true; 387 } 388 389 void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) { 390 return unwrap(cg)->setCpu(cpu); 391 } 392 393 void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) { 394 // In here only for backwards compatibility. We use MC now. 395 } 396 397 void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, 398 int nargs) { 399 // In here only for backwards compatibility. We use MC now. 400 } 401 402 void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, 403 const char *symbol) { 404 unwrap(cg)->addMustPreserveSymbol(symbol); 405 } 406 407 static void maybeParseOptions(lto_code_gen_t cg) { 408 if (!parsedOptions) { 409 unwrap(cg)->parseCodeGenDebugOptions(); 410 lto_add_attrs(cg); 411 parsedOptions = true; 412 } 413 } 414 415 bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) { 416 maybeParseOptions(cg); 417 return !unwrap(cg)->writeMergedModules(path); 418 } 419 420 const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) { 421 maybeParseOptions(cg); 422 LibLTOCodeGenerator *CG = unwrap(cg); 423 CG->NativeObjectFile = 424 CG->compile(DisableVerify, DisableInline, DisableGVNLoadPRE, 425 DisableLTOVectorization); 426 if (!CG->NativeObjectFile) 427 return nullptr; 428 *length = CG->NativeObjectFile->getBufferSize(); 429 return CG->NativeObjectFile->getBufferStart(); 430 } 431 432 bool lto_codegen_optimize(lto_code_gen_t cg) { 433 maybeParseOptions(cg); 434 return !unwrap(cg)->optimize(DisableVerify, DisableInline, DisableGVNLoadPRE, 435 DisableLTOVectorization); 436 } 437 438 const void *lto_codegen_compile_optimized(lto_code_gen_t cg, size_t *length) { 439 maybeParseOptions(cg); 440 LibLTOCodeGenerator *CG = unwrap(cg); 441 CG->NativeObjectFile = CG->compileOptimized(); 442 if (!CG->NativeObjectFile) 443 return nullptr; 444 *length = CG->NativeObjectFile->getBufferSize(); 445 return CG->NativeObjectFile->getBufferStart(); 446 } 447 448 bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) { 449 maybeParseOptions(cg); 450 return !unwrap(cg)->compile_to_file( 451 name, DisableVerify, DisableInline, DisableGVNLoadPRE, 452 DisableLTOVectorization); 453 } 454 455 void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) { 456 unwrap(cg)->setCodeGenDebugOptions(opt); 457 } 458 459 unsigned int lto_api_version() { return LTO_API_VERSION; } 460 461 void lto_codegen_set_should_internalize(lto_code_gen_t cg, 462 bool ShouldInternalize) { 463 unwrap(cg)->setShouldInternalize(ShouldInternalize); 464 } 465 466 void lto_codegen_set_should_embed_uselists(lto_code_gen_t cg, 467 lto_bool_t ShouldEmbedUselists) { 468 unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists); 469 } 470 471 // ThinLTO API below 472 473 thinlto_code_gen_t thinlto_create_codegen(void) { 474 lto_initialize(); 475 ThinLTOCodeGenerator *CodeGen = new ThinLTOCodeGenerator(); 476 CodeGen->setTargetOptions(InitTargetOptionsFromCodeGenFlags()); 477 CodeGen->setFreestanding(EnableFreestanding); 478 479 if (OptLevel.getNumOccurrences()) { 480 if (OptLevel < '0' || OptLevel > '3') 481 report_fatal_error("Optimization level must be between 0 and 3"); 482 CodeGen->setOptLevel(OptLevel - '0'); 483 switch (OptLevel) { 484 case '0': 485 CodeGen->setCodeGenOptLevel(CodeGenOpt::None); 486 break; 487 case '1': 488 CodeGen->setCodeGenOptLevel(CodeGenOpt::Less); 489 break; 490 case '2': 491 CodeGen->setCodeGenOptLevel(CodeGenOpt::Default); 492 break; 493 case '3': 494 CodeGen->setCodeGenOptLevel(CodeGenOpt::Aggressive); 495 break; 496 } 497 } 498 return wrap(CodeGen); 499 } 500 501 void thinlto_codegen_dispose(thinlto_code_gen_t cg) { delete unwrap(cg); } 502 503 void thinlto_codegen_add_module(thinlto_code_gen_t cg, const char *Identifier, 504 const char *Data, int Length) { 505 unwrap(cg)->addModule(Identifier, StringRef(Data, Length)); 506 } 507 508 void thinlto_codegen_process(thinlto_code_gen_t cg) { unwrap(cg)->run(); } 509 510 unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg) { 511 return unwrap(cg)->getProducedBinaries().size(); 512 } 513 LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg, 514 unsigned int index) { 515 assert(index < unwrap(cg)->getProducedBinaries().size() && "Index overflow"); 516 auto &MemBuffer = unwrap(cg)->getProducedBinaries()[index]; 517 return LTOObjectBuffer{MemBuffer->getBufferStart(), 518 MemBuffer->getBufferSize()}; 519 } 520 521 unsigned int thinlto_module_get_num_object_files(thinlto_code_gen_t cg) { 522 return unwrap(cg)->getProducedBinaryFiles().size(); 523 } 524 const char *thinlto_module_get_object_file(thinlto_code_gen_t cg, 525 unsigned int index) { 526 assert(index < unwrap(cg)->getProducedBinaryFiles().size() && 527 "Index overflow"); 528 return unwrap(cg)->getProducedBinaryFiles()[index].c_str(); 529 } 530 531 void thinlto_codegen_disable_codegen(thinlto_code_gen_t cg, 532 lto_bool_t disable) { 533 unwrap(cg)->disableCodeGen(disable); 534 } 535 536 void thinlto_codegen_set_codegen_only(thinlto_code_gen_t cg, 537 lto_bool_t CodeGenOnly) { 538 unwrap(cg)->setCodeGenOnly(CodeGenOnly); 539 } 540 541 void thinlto_debug_options(const char *const *options, int number) { 542 // if options were requested, set them 543 if (number && options) { 544 std::vector<const char *> CodegenArgv(1, "libLTO"); 545 for (auto Arg : ArrayRef<const char *>(options, number)) 546 CodegenArgv.push_back(Arg); 547 cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data()); 548 } 549 } 550 551 lto_bool_t lto_module_is_thinlto(lto_module_t mod) { 552 return unwrap(mod)->isThinLTO(); 553 } 554 555 void thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg, 556 const char *Name, int Length) { 557 unwrap(cg)->preserveSymbol(StringRef(Name, Length)); 558 } 559 560 void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg, 561 const char *Name, int Length) { 562 unwrap(cg)->crossReferenceSymbol(StringRef(Name, Length)); 563 } 564 565 void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu) { 566 return unwrap(cg)->setCpu(cpu); 567 } 568 569 void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg, 570 const char *cache_dir) { 571 return unwrap(cg)->setCacheDir(cache_dir); 572 } 573 574 void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg, 575 int interval) { 576 return unwrap(cg)->setCachePruningInterval(interval); 577 } 578 579 void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg, 580 unsigned expiration) { 581 return unwrap(cg)->setCacheEntryExpiration(expiration); 582 } 583 584 void thinlto_codegen_set_final_cache_size_relative_to_available_space( 585 thinlto_code_gen_t cg, unsigned Percentage) { 586 return unwrap(cg)->setMaxCacheSizeRelativeToAvailableSpace(Percentage); 587 } 588 589 void thinlto_codegen_set_cache_size_bytes( 590 thinlto_code_gen_t cg, unsigned MaxSizeBytes) { 591 return unwrap(cg)->setCacheMaxSizeBytes(MaxSizeBytes); 592 } 593 594 void thinlto_codegen_set_cache_size_files( 595 thinlto_code_gen_t cg, unsigned MaxSizeFiles) { 596 return unwrap(cg)->setCacheMaxSizeFiles(MaxSizeFiles); 597 } 598 599 void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg, 600 const char *save_temps_dir) { 601 return unwrap(cg)->setSaveTempsDir(save_temps_dir); 602 } 603 604 void thinlto_set_generated_objects_dir(thinlto_code_gen_t cg, 605 const char *save_temps_dir) { 606 unwrap(cg)->setGeneratedObjectsDirectory(save_temps_dir); 607 } 608 609 lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg, 610 lto_codegen_model model) { 611 switch (model) { 612 case LTO_CODEGEN_PIC_MODEL_STATIC: 613 unwrap(cg)->setCodePICModel(Reloc::Static); 614 return false; 615 case LTO_CODEGEN_PIC_MODEL_DYNAMIC: 616 unwrap(cg)->setCodePICModel(Reloc::PIC_); 617 return false; 618 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: 619 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC); 620 return false; 621 case LTO_CODEGEN_PIC_MODEL_DEFAULT: 622 unwrap(cg)->setCodePICModel(None); 623 return false; 624 } 625 sLastErrorString = "Unknown PIC model"; 626 return true; 627 } 628