750 lines · cpp
1//===-lto.cpp - LLVM Link Time Optimizer ----------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the Link Time Optimization library. This library is10// intended to be used by linker to optimize code at link time.11//12//===----------------------------------------------------------------------===//13 14#include "llvm-c/lto.h"15#include "llvm/ADT/STLExtras.h"16#include "llvm/ADT/SmallVector.h"17#include "llvm/ADT/StringExtras.h"18#include "llvm/Bitcode/BitcodeReader.h"19#include "llvm/CodeGen/CommandFlags.h"20#include "llvm/IR/DiagnosticInfo.h"21#include "llvm/IR/DiagnosticPrinter.h"22#include "llvm/IR/LLVMContext.h"23#include "llvm/LTO/LTO.h"24#include "llvm/LTO/legacy/LTOCodeGenerator.h"25#include "llvm/LTO/legacy/LTOModule.h"26#include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"27#include "llvm/Support/FileSystem.h"28#include "llvm/Support/MemoryBuffer.h"29#include "llvm/Support/Signals.h"30#include "llvm/Support/TargetSelect.h"31#include "llvm/Support/raw_ostream.h"32 33using namespace llvm;34 35static codegen::RegisterCodeGenFlags CGF;36 37// extra command-line flags needed for LTOCodeGenerator38static cl::opt<char>39 OptLevel("O",40 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "41 "(default = '-O2')"),42 cl::Prefix, cl::init('2'));43 44static cl::opt<bool> EnableFreestanding(45 "lto-freestanding", cl::init(false),46 cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));47 48static cl::opt<std::string> ThinLTOCacheDir(49 "legacy-thinlto-cache-dir",50 cl::desc("Experimental option, enable ThinLTO caching. Note: the cache "51 "currently does not take the mcmodel setting into account, so you "52 "might get false hits if different mcmodels are used in different "53 "builds using the same cache directory."));54 55static cl::opt<int> ThinLTOCachePruningInterval(56 "legacy-thinlto-cache-pruning-interval", cl::init(1200),57 cl::desc("Set ThinLTO cache pruning interval (seconds)."));58 59static cl::opt<uint64_t> ThinLTOCacheMaxSizeBytes(60 "legacy-thinlto-cache-max-size-bytes",61 cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."));62 63static cl::opt<int> ThinLTOCacheMaxSizeFiles(64 "legacy-thinlto-cache-max-size-files", cl::init(1000000),65 cl::desc("Set ThinLTO cache pruning directory maximum number of files."));66 67static cl::opt<unsigned> ThinLTOCacheEntryExpiration(68 "legacy-thinlto-cache-entry-expiration", cl::init(604800) /* 1w */,69 cl::desc("Set ThinLTO cache entry expiration time (seconds)."));70 71#ifdef NDEBUG72static bool VerifyByDefault = false;73#else74static bool VerifyByDefault = true;75#endif76 77static cl::opt<bool> DisableVerify(78 "disable-llvm-verifier", cl::init(!VerifyByDefault),79 cl::desc("Don't run the LLVM verifier during the optimization pipeline"));80 81// Holds most recent error string.82// *** Not thread safe ***83static std::string sLastErrorString;84 85// Holds the initialization state of the LTO module.86// *** Not thread safe ***87static bool initialized = false;88 89// Represent the state of parsing command line debug options.90static enum class OptParsingState {91 NotParsed, // Initial state.92 Early, // After lto_set_debug_options is called.93 Done // After maybeParseOptions is called.94} optionParsingState = OptParsingState::NotParsed;95 96static LLVMContext *LTOContext = nullptr;97 98struct LTOToolDiagnosticHandler : public DiagnosticHandler {99 bool handleDiagnostics(const DiagnosticInfo &DI) override {100 if (DI.getSeverity() != DS_Error) {101 DiagnosticPrinterRawOStream DP(errs());102 DI.print(DP);103 errs() << '\n';104 return true;105 }106 sLastErrorString = "";107 {108 raw_string_ostream Stream(sLastErrorString);109 DiagnosticPrinterRawOStream DP(Stream);110 DI.print(DP);111 }112 return true;113 }114};115 116static SmallVector<const char *> RuntimeLibcallSymbols;117 118// Initialize the configured targets if they have not been initialized.119static void lto_initialize() {120 if (!initialized) {121#ifdef _WIN32122 // Dialog box on crash disabling doesn't work across DLL boundaries, so do123 // it here.124 llvm::sys::DisableSystemDialogsOnCrash();125#endif126 127 InitializeAllTargetInfos();128 InitializeAllTargets();129 InitializeAllTargetMCs();130 InitializeAllAsmParsers();131 InitializeAllAsmPrinters();132 InitializeAllDisassemblers();133 134 static LLVMContext Context;135 LTOContext = &Context;136 LTOContext->setDiagnosticHandler(137 std::make_unique<LTOToolDiagnosticHandler>(), true);138 RuntimeLibcallSymbols = lto::LTO::getRuntimeLibcallSymbols(Triple());139 initialized = true;140 }141}142 143namespace {144 145static void handleLibLTODiagnostic(lto_codegen_diagnostic_severity_t Severity,146 const char *Msg, void *) {147 sLastErrorString = Msg;148}149 150// This derived class owns the native object file. This helps implement the151// libLTO API semantics, which require that the code generator owns the object152// file.153struct LibLTOCodeGenerator : LTOCodeGenerator {154 LibLTOCodeGenerator() : LTOCodeGenerator(*LTOContext) { init(); }155 LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context)156 : LTOCodeGenerator(*Context), OwnedContext(std::move(Context)) {157 init();158 }159 160 // Reset the module first in case MergedModule is created in OwnedContext.161 // Module must be destructed before its context gets destructed.162 ~LibLTOCodeGenerator() { resetMergedModule(); }163 164 void init() { setDiagnosticHandler(handleLibLTODiagnostic, nullptr); }165 166 std::unique_ptr<MemoryBuffer> NativeObjectFile;167 std::unique_ptr<LLVMContext> OwnedContext;168};169 170}171 172DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t)173DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThinLTOCodeGenerator, thinlto_code_gen_t)174DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t)175 176// Convert the subtarget features into a string to pass to LTOCodeGenerator.177static void lto_add_attrs(lto_code_gen_t cg) {178 LTOCodeGenerator *CG = unwrap(cg);179 CG->setAttrs(codegen::getMAttrs());180 181 if (OptLevel < '0' || OptLevel > '3')182 report_fatal_error("Optimization level must be between 0 and 3");183 CG->setOptLevel(OptLevel - '0');184 CG->setFreestanding(EnableFreestanding);185 CG->setDisableVerify(DisableVerify);186}187 188extern const char* lto_get_version() {189 return LTOCodeGenerator::getVersionString();190}191 192const char* lto_get_error_message() {193 return sLastErrorString.c_str();194}195 196bool lto_module_is_object_file(const char* path) {197 return LTOModule::isBitcodeFile(StringRef(path));198}199 200bool lto_module_is_object_file_for_target(const char* path,201 const char* target_triplet_prefix) {202 ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(path);203 if (!Buffer)204 return false;205 return LTOModule::isBitcodeForTarget(Buffer->get(),206 StringRef(target_triplet_prefix));207}208 209bool lto_module_has_objc_category(const void *mem, size_t length) {210 std::unique_ptr<MemoryBuffer> Buffer(LTOModule::makeBuffer(mem, length));211 if (!Buffer)212 return false;213 LLVMContext Ctx;214 ErrorOr<bool> Result = expectedToErrorOrAndEmitErrors(215 Ctx, llvm::isBitcodeContainingObjCCategory(*Buffer));216 return Result && *Result;217}218 219bool lto_module_is_object_file_in_memory(const void* mem, size_t length) {220 return LTOModule::isBitcodeFile(mem, length);221}222 223bool224lto_module_is_object_file_in_memory_for_target(const void* mem,225 size_t length,226 const char* target_triplet_prefix) {227 std::unique_ptr<MemoryBuffer> buffer(LTOModule::makeBuffer(mem, length));228 if (!buffer)229 return false;230 return LTOModule::isBitcodeForTarget(buffer.get(),231 StringRef(target_triplet_prefix));232}233 234lto_module_t lto_module_create(const char* path) {235 lto_initialize();236 llvm::TargetOptions Options =237 codegen::InitTargetOptionsFromCodeGenFlags(Triple());238 ErrorOr<std::unique_ptr<LTOModule>> M =239 LTOModule::createFromFile(*LTOContext, StringRef(path), Options);240 if (!M)241 return nullptr;242 return wrap(M->release());243}244 245lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {246 lto_initialize();247 llvm::TargetOptions Options =248 codegen::InitTargetOptionsFromCodeGenFlags(Triple());249 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFile(250 *LTOContext, fd, StringRef(path), size, Options);251 if (!M)252 return nullptr;253 return wrap(M->release());254}255 256lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,257 size_t file_size,258 size_t map_size,259 off_t offset) {260 lto_initialize();261 llvm::TargetOptions Options =262 codegen::InitTargetOptionsFromCodeGenFlags(Triple());263 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFileSlice(264 *LTOContext, fd, StringRef(path), map_size, offset, Options);265 if (!M)266 return nullptr;267 return wrap(M->release());268}269 270lto_module_t lto_module_create_from_memory(const void* mem, size_t length) {271 lto_initialize();272 llvm::TargetOptions Options =273 codegen::InitTargetOptionsFromCodeGenFlags(Triple());274 ErrorOr<std::unique_ptr<LTOModule>> M =275 LTOModule::createFromBuffer(*LTOContext, mem, length, Options);276 if (!M)277 return nullptr;278 return wrap(M->release());279}280 281lto_module_t lto_module_create_from_memory_with_path(const void* mem,282 size_t length,283 const char *path) {284 lto_initialize();285 llvm::TargetOptions Options =286 codegen::InitTargetOptionsFromCodeGenFlags(Triple());287 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer(288 *LTOContext, mem, length, Options, StringRef(path));289 if (!M)290 return nullptr;291 return wrap(M->release());292}293 294lto_module_t lto_module_create_in_local_context(const void *mem, size_t length,295 const char *path) {296 lto_initialize();297 llvm::TargetOptions Options =298 codegen::InitTargetOptionsFromCodeGenFlags(Triple());299 300 // Create a local context. Ownership will be transferred to LTOModule.301 std::unique_ptr<LLVMContext> Context = std::make_unique<LLVMContext>();302 Context->setDiagnosticHandler(std::make_unique<LTOToolDiagnosticHandler>(),303 true);304 305 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createInLocalContext(306 std::move(Context), mem, length, Options, StringRef(path));307 if (!M)308 return nullptr;309 return wrap(M->release());310}311 312lto_module_t lto_module_create_in_codegen_context(const void *mem,313 size_t length,314 const char *path,315 lto_code_gen_t cg) {316 lto_initialize();317 llvm::TargetOptions Options =318 codegen::InitTargetOptionsFromCodeGenFlags(Triple());319 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer(320 unwrap(cg)->getContext(), mem, length, Options, StringRef(path));321 if (!M)322 return nullptr;323 return wrap(M->release());324}325 326void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); }327 328const char* lto_module_get_target_triple(lto_module_t mod) {329 return unwrap(mod)->getTargetTriple().str().c_str();330}331 332void lto_module_set_target_triple(lto_module_t mod, const char *triple) {333 return unwrap(mod)->setTargetTriple(Triple(StringRef(triple)));334}335 336unsigned int lto_module_get_num_symbols(lto_module_t mod) {337 return unwrap(mod)->getSymbolCount();338}339 340const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) {341 return unwrap(mod)->getSymbolName(index).data();342}343 344lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,345 unsigned int index) {346 return unwrap(mod)->getSymbolAttributes(index);347}348 349unsigned int lto_module_get_num_asm_undef_symbols(lto_module_t mod) {350 return unwrap(mod)->getAsmUndefSymbolCount();351}352 353const char *lto_module_get_asm_undef_symbol_name(lto_module_t mod,354 unsigned int index) {355 return unwrap(mod)->getAsmUndefSymbolName(index).data();356}357 358const char* lto_module_get_linkeropts(lto_module_t mod) {359 return unwrap(mod)->getLinkerOpts().data();360}361 362lto_bool_t lto_module_get_macho_cputype(lto_module_t mod,363 unsigned int *out_cputype,364 unsigned int *out_cpusubtype) {365 LTOModule *M = unwrap(mod);366 Expected<uint32_t> CPUType = M->getMachOCPUType();367 if (!CPUType) {368 sLastErrorString = toString(CPUType.takeError());369 return true;370 }371 *out_cputype = *CPUType;372 373 Expected<uint32_t> CPUSubType = M->getMachOCPUSubType();374 if (!CPUSubType) {375 sLastErrorString = toString(CPUSubType.takeError());376 return true;377 }378 *out_cpusubtype = *CPUSubType;379 380 return false;381}382 383void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,384 lto_diagnostic_handler_t diag_handler,385 void *ctxt) {386 unwrap(cg)->setDiagnosticHandler(diag_handler, ctxt);387}388 389static lto_code_gen_t createCodeGen(bool InLocalContext) {390 lto_initialize();391 392 TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());393 394 LibLTOCodeGenerator *CodeGen =395 InLocalContext ? new LibLTOCodeGenerator(std::make_unique<LLVMContext>())396 : new LibLTOCodeGenerator();397 CodeGen->setTargetOptions(Options);398 return wrap(CodeGen);399}400 401lto_code_gen_t lto_codegen_create(void) {402 return createCodeGen(/* InLocalContext */ false);403}404 405lto_code_gen_t lto_codegen_create_in_local_context(void) {406 return createCodeGen(/* InLocalContext */ true);407}408 409void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); }410 411bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) {412 return !unwrap(cg)->addModule(unwrap(mod));413}414 415void lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod) {416 unwrap(cg)->setModule(std::unique_ptr<LTOModule>(unwrap(mod)));417}418 419bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) {420 unwrap(cg)->setDebugInfo(debug);421 return false;422}423 424bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) {425 switch (model) {426 case LTO_CODEGEN_PIC_MODEL_STATIC:427 unwrap(cg)->setCodePICModel(Reloc::Static);428 return false;429 case LTO_CODEGEN_PIC_MODEL_DYNAMIC:430 unwrap(cg)->setCodePICModel(Reloc::PIC_);431 return false;432 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:433 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);434 return false;435 case LTO_CODEGEN_PIC_MODEL_DEFAULT:436 unwrap(cg)->setCodePICModel(std::nullopt);437 return false;438 }439 sLastErrorString = "Unknown PIC model";440 return true;441}442 443void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) {444 return unwrap(cg)->setCpu(cpu);445}446 447void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) {448 // In here only for backwards compatibility. We use MC now.449}450 451void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,452 int nargs) {453 // In here only for backwards compatibility. We use MC now.454}455 456void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg,457 const char *symbol) {458 unwrap(cg)->addMustPreserveSymbol(symbol);459}460 461static void maybeParseOptions(lto_code_gen_t cg) {462 if (optionParsingState != OptParsingState::Done) {463 // Parse options if any were set by the lto_codegen_debug_options* function.464 unwrap(cg)->parseCodeGenDebugOptions();465 lto_add_attrs(cg);466 optionParsingState = OptParsingState::Done;467 }468}469 470bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) {471 maybeParseOptions(cg);472 return !unwrap(cg)->writeMergedModules(path);473}474 475const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) {476 maybeParseOptions(cg);477 LibLTOCodeGenerator *CG = unwrap(cg);478 CG->NativeObjectFile = CG->compile();479 if (!CG->NativeObjectFile)480 return nullptr;481 *length = CG->NativeObjectFile->getBufferSize();482 return CG->NativeObjectFile->getBufferStart();483}484 485bool lto_codegen_optimize(lto_code_gen_t cg) {486 maybeParseOptions(cg);487 return !unwrap(cg)->optimize();488}489 490const void *lto_codegen_compile_optimized(lto_code_gen_t cg, size_t *length) {491 maybeParseOptions(cg);492 LibLTOCodeGenerator *CG = unwrap(cg);493 CG->NativeObjectFile = CG->compileOptimized();494 if (!CG->NativeObjectFile)495 return nullptr;496 *length = CG->NativeObjectFile->getBufferSize();497 return CG->NativeObjectFile->getBufferStart();498}499 500bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) {501 maybeParseOptions(cg);502 return !unwrap(cg)->compile_to_file(name);503}504 505void lto_set_debug_options(const char *const *options, int number) {506 assert(optionParsingState == OptParsingState::NotParsed &&507 "option processing already happened");508 // Need to put each suboption in a null-terminated string before passing to509 // parseCommandLineOptions().510 std::vector<std::string> Options;511 llvm::append_range(Options, ArrayRef(options, number));512 513 llvm::parseCommandLineOptions(Options);514 optionParsingState = OptParsingState::Early;515}516 517void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) {518 assert(optionParsingState != OptParsingState::Early &&519 "early option processing already happened");520 SmallVector<StringRef, 4> Options;521 for (std::pair<StringRef, StringRef> o = getToken(opt); !o.first.empty();522 o = getToken(o.second))523 Options.push_back(o.first);524 525 unwrap(cg)->setCodeGenDebugOptions(Options);526}527 528void lto_codegen_debug_options_array(lto_code_gen_t cg,529 const char *const *options, int number) {530 assert(optionParsingState != OptParsingState::Early &&531 "early option processing already happened");532 SmallVector<StringRef, 4> Options(ArrayRef(options, number));533 unwrap(cg)->setCodeGenDebugOptions(ArrayRef(Options));534}535 536unsigned int lto_api_version() { return LTO_API_VERSION; }537 538void lto_codegen_set_should_internalize(lto_code_gen_t cg,539 bool ShouldInternalize) {540 unwrap(cg)->setShouldInternalize(ShouldInternalize);541}542 543void lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,544 lto_bool_t ShouldEmbedUselists) {545 unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists);546}547 548lto_bool_t lto_module_has_ctor_dtor(lto_module_t mod) {549 return unwrap(mod)->hasCtorDtor();550}551 552// ThinLTO API below553 554thinlto_code_gen_t thinlto_create_codegen(void) {555 lto_initialize();556 ThinLTOCodeGenerator *CodeGen = new ThinLTOCodeGenerator();557 CodeGen->setTargetOptions(558 codegen::InitTargetOptionsFromCodeGenFlags(Triple()));559 CodeGen->setFreestanding(EnableFreestanding);560 561 if (OptLevel.getNumOccurrences()) {562 if (OptLevel < '0' || OptLevel > '3')563 report_fatal_error("Optimization level must be between 0 and 3");564 CodeGen->setOptLevel(OptLevel - '0');565 std::optional<CodeGenOptLevel> CGOptLevelOrNone =566 CodeGenOpt::getLevel(OptLevel - '0');567 assert(CGOptLevelOrNone);568 CodeGen->setCodeGenOptLevel(*CGOptLevelOrNone);569 }570 if (!ThinLTOCacheDir.empty()) {571 auto Err = llvm::sys::fs::create_directories(ThinLTOCacheDir);572 if (Err)573 report_fatal_error(Twine("Unable to create thinLTO cache directory: ") +574 Err.message());575 bool result;576 Err = llvm::sys::fs::is_directory(ThinLTOCacheDir, result);577 if (Err || !result)578 report_fatal_error(Twine("Unable to get status of thinLTO cache path or "579 "path is not a directory: ") +580 Err.message());581 CodeGen->setCacheDir(ThinLTOCacheDir);582 583 CodeGen->setCachePruningInterval(ThinLTOCachePruningInterval);584 CodeGen->setCacheEntryExpiration(ThinLTOCacheEntryExpiration);585 CodeGen->setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles);586 CodeGen->setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes);587 }588 589 return wrap(CodeGen);590}591 592void thinlto_codegen_dispose(thinlto_code_gen_t cg) { delete unwrap(cg); }593 594void thinlto_codegen_add_module(thinlto_code_gen_t cg, const char *Identifier,595 const char *Data, int Length) {596 unwrap(cg)->addModule(Identifier, StringRef(Data, Length));597}598 599void thinlto_codegen_process(thinlto_code_gen_t cg) { unwrap(cg)->run(); }600 601unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg) {602 return unwrap(cg)->getProducedBinaries().size();603}604LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg,605 unsigned int index) {606 assert(index < unwrap(cg)->getProducedBinaries().size() && "Index overflow");607 auto &MemBuffer = unwrap(cg)->getProducedBinaries()[index];608 return LTOObjectBuffer{MemBuffer->getBufferStart(),609 MemBuffer->getBufferSize()};610}611 612unsigned int thinlto_module_get_num_object_files(thinlto_code_gen_t cg) {613 return unwrap(cg)->getProducedBinaryFiles().size();614}615const char *thinlto_module_get_object_file(thinlto_code_gen_t cg,616 unsigned int index) {617 assert(index < unwrap(cg)->getProducedBinaryFiles().size() &&618 "Index overflow");619 return unwrap(cg)->getProducedBinaryFiles()[index].c_str();620}621 622void thinlto_codegen_disable_codegen(thinlto_code_gen_t cg,623 lto_bool_t disable) {624 unwrap(cg)->disableCodeGen(disable);625}626 627void thinlto_codegen_set_codegen_only(thinlto_code_gen_t cg,628 lto_bool_t CodeGenOnly) {629 unwrap(cg)->setCodeGenOnly(CodeGenOnly);630}631 632void thinlto_debug_options(const char *const *options, int number) {633 // if options were requested, set them634 if (number && options) {635 std::vector<const char *> CodegenArgv(1, "libLTO");636 append_range(CodegenArgv, ArrayRef<const char *>(options, number));637 cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data());638 }639}640 641lto_bool_t lto_module_is_thinlto(lto_module_t mod) {642 return unwrap(mod)->isThinLTO();643}644 645void thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg,646 const char *Name, int Length) {647 unwrap(cg)->preserveSymbol(StringRef(Name, Length));648}649 650void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,651 const char *Name, int Length) {652 unwrap(cg)->crossReferenceSymbol(StringRef(Name, Length));653}654 655void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu) {656 return unwrap(cg)->setCpu(cpu);657}658 659void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,660 const char *cache_dir) {661 return unwrap(cg)->setCacheDir(cache_dir);662}663 664void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,665 int interval) {666 return unwrap(cg)->setCachePruningInterval(interval);667}668 669void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,670 unsigned expiration) {671 return unwrap(cg)->setCacheEntryExpiration(expiration);672}673 674void thinlto_codegen_set_final_cache_size_relative_to_available_space(675 thinlto_code_gen_t cg, unsigned Percentage) {676 return unwrap(cg)->setMaxCacheSizeRelativeToAvailableSpace(Percentage);677}678 679void thinlto_codegen_set_cache_size_bytes(680 thinlto_code_gen_t cg, unsigned MaxSizeBytes) {681 return unwrap(cg)->setCacheMaxSizeBytes(MaxSizeBytes);682}683 684void thinlto_codegen_set_cache_size_megabytes(685 thinlto_code_gen_t cg, unsigned MaxSizeMegabytes) {686 uint64_t MaxSizeBytes = MaxSizeMegabytes;687 MaxSizeBytes *= 1024 * 1024;688 return unwrap(cg)->setCacheMaxSizeBytes(MaxSizeBytes);689}690 691void thinlto_codegen_set_cache_size_files(692 thinlto_code_gen_t cg, unsigned MaxSizeFiles) {693 return unwrap(cg)->setCacheMaxSizeFiles(MaxSizeFiles);694}695 696void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,697 const char *save_temps_dir) {698 return unwrap(cg)->setSaveTempsDir(save_temps_dir);699}700 701void thinlto_set_generated_objects_dir(thinlto_code_gen_t cg,702 const char *save_temps_dir) {703 unwrap(cg)->setGeneratedObjectsDirectory(save_temps_dir);704}705 706lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,707 lto_codegen_model model) {708 switch (model) {709 case LTO_CODEGEN_PIC_MODEL_STATIC:710 unwrap(cg)->setCodePICModel(Reloc::Static);711 return false;712 case LTO_CODEGEN_PIC_MODEL_DYNAMIC:713 unwrap(cg)->setCodePICModel(Reloc::PIC_);714 return false;715 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:716 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);717 return false;718 case LTO_CODEGEN_PIC_MODEL_DEFAULT:719 unwrap(cg)->setCodePICModel(std::nullopt);720 return false;721 }722 sLastErrorString = "Unknown PIC model";723 return true;724}725 726DEFINE_SIMPLE_CONVERSION_FUNCTIONS(lto::InputFile, lto_input_t)727 728lto_input_t lto_input_create(const void *buffer, size_t buffer_size, const char *path) {729 return wrap(LTOModule::createInputFile(buffer, buffer_size, path, sLastErrorString));730}731 732void lto_input_dispose(lto_input_t input) {733 delete unwrap(input);734}735 736extern unsigned lto_input_get_num_dependent_libraries(lto_input_t input) {737 return LTOModule::getDependentLibraryCount(unwrap(input));738}739 740extern const char *lto_input_get_dependent_library(lto_input_t input,741 size_t index,742 size_t *size) {743 return LTOModule::getDependentLibrary(unwrap(input), index, size);744}745 746extern const char *const *lto_runtime_lib_symbols_list(size_t *size) {747 *size = RuntimeLibcallSymbols.size();748 return RuntimeLibcallSymbols.data();749}750