brintos

brintos / llvm-project-archived public Read only

0
0
Text · 25.8 KiB · 513d057 Raw
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