Home | History | Annotate | Download | only in lto
      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