xref: /openbsd/gnu/llvm/llvm/tools/lto/lto.cpp (revision 771fbea0)
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the Link Time Optimization library. This library is
10 // 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/StringExtras.h"
17 #include "llvm/Bitcode/BitcodeReader.h"
18 #include "llvm/CodeGen/CommandFlags.h"
19 #include "llvm/IR/DiagnosticInfo.h"
20 #include "llvm/IR/DiagnosticPrinter.h"
21 #include "llvm/IR/LLVMContext.h"
22 #include "llvm/LTO/LTO.h"
23 #include "llvm/LTO/legacy/LTOCodeGenerator.h"
24 #include "llvm/LTO/legacy/LTOModule.h"
25 #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
26 #include "llvm/Support/MemoryBuffer.h"
27 #include "llvm/Support/Signals.h"
28 #include "llvm/Support/TargetSelect.h"
29 #include "llvm/Support/raw_ostream.h"
30 
31 using namespace llvm;
32 
33 static codegen::RegisterCodeGenFlags CGF;
34 
35 // extra command-line flags needed for LTOCodeGenerator
36 static cl::opt<char>
37 OptLevel("O",
38          cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
39                   "(default = '-O2')"),
40          cl::Prefix,
41          cl::ZeroOrMore,
42          cl::init('2'));
43 
44 static cl::opt<bool>
45 DisableInline("disable-inlining", cl::init(false),
46   cl::desc("Do not run the inliner pass"));
47 
48 static cl::opt<bool>
49 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
50   cl::desc("Do not run the GVN load PRE pass"));
51 
52 static cl::opt<bool> DisableLTOVectorization(
53     "disable-lto-vectorization", cl::init(false),
54     cl::desc("Do not run loop or slp vectorization during LTO"));
55 
56 static cl::opt<bool> EnableFreestanding(
57     "lto-freestanding", cl::init(false),
58     cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
59 
60 #ifdef NDEBUG
61 static bool VerifyByDefault = false;
62 #else
63 static bool VerifyByDefault = true;
64 #endif
65 
66 static cl::opt<bool> DisableVerify(
67     "disable-llvm-verifier", cl::init(!VerifyByDefault),
68     cl::desc("Don't run the LLVM verifier during the optimization pipeline"));
69 
70 // Holds most recent error string.
71 // *** Not thread safe ***
72 static std::string sLastErrorString;
73 
74 // Holds the initialization state of the LTO module.
75 // *** Not thread safe ***
76 static bool initialized = false;
77 
78 // Holds the command-line option parsing state of the LTO module.
79 static bool parsedOptions = false;
80 
81 static LLVMContext *LTOContext = nullptr;
82 
83 struct LTOToolDiagnosticHandler : public DiagnosticHandler {
84   bool handleDiagnostics(const DiagnosticInfo &DI) override {
85     if (DI.getSeverity() != DS_Error) {
86       DiagnosticPrinterRawOStream DP(errs());
87       DI.print(DP);
88       errs() << '\n';
89       return true;
90     }
91     sLastErrorString = "";
92     {
93       raw_string_ostream Stream(sLastErrorString);
94       DiagnosticPrinterRawOStream DP(Stream);
95       DI.print(DP);
96     }
97     return true;
98   }
99 };
100 
101 // Initialize the configured targets if they have not been initialized.
102 static void lto_initialize() {
103   if (!initialized) {
104 #ifdef _WIN32
105     // Dialog box on crash disabling doesn't work across DLL boundaries, so do
106     // it here.
107     llvm::sys::DisableSystemDialogsOnCrash();
108 #endif
109 
110     InitializeAllTargetInfos();
111     InitializeAllTargets();
112     InitializeAllTargetMCs();
113     InitializeAllAsmParsers();
114     InitializeAllAsmPrinters();
115     InitializeAllDisassemblers();
116 
117     static LLVMContext Context;
118     LTOContext = &Context;
119     LTOContext->setDiagnosticHandler(
120         std::make_unique<LTOToolDiagnosticHandler>(), true);
121     initialized = true;
122   }
123 }
124 
125 namespace {
126 
127 static void handleLibLTODiagnostic(lto_codegen_diagnostic_severity_t Severity,
128                                    const char *Msg, void *) {
129   sLastErrorString = Msg;
130 }
131 
132 // This derived class owns the native object file. This helps implement the
133 // libLTO API semantics, which require that the code generator owns the object
134 // file.
135 struct LibLTOCodeGenerator : LTOCodeGenerator {
136   LibLTOCodeGenerator() : LTOCodeGenerator(*LTOContext) { init(); }
137   LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context)
138       : LTOCodeGenerator(*Context), OwnedContext(std::move(Context)) {
139     init();
140   }
141 
142   // Reset the module first in case MergedModule is created in OwnedContext.
143   // Module must be destructed before its context gets destructed.
144   ~LibLTOCodeGenerator() { resetMergedModule(); }
145 
146   void init() { setDiagnosticHandler(handleLibLTODiagnostic, nullptr); }
147 
148   std::unique_ptr<MemoryBuffer> NativeObjectFile;
149   std::unique_ptr<LLVMContext> OwnedContext;
150 };
151 
152 }
153 
154 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t)
155 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThinLTOCodeGenerator, thinlto_code_gen_t)
156 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t)
157 
158 // Convert the subtarget features into a string to pass to LTOCodeGenerator.
159 static void lto_add_attrs(lto_code_gen_t cg) {
160   LTOCodeGenerator *CG = unwrap(cg);
161   auto MAttrs = codegen::getMAttrs();
162   if (!MAttrs.empty()) {
163     std::string attrs = join(MAttrs, ",");
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 = codegen::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 = codegen::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 = codegen::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 = codegen::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 = codegen::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 = codegen::InitTargetOptionsFromCodeGenFlags();
278 
279   // Create a local context. Ownership will be transferred to LTOModule.
280   std::unique_ptr<LLVMContext> Context = std::make_unique<LLVMContext>();
281   Context->setDiagnosticHandler(std::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 = codegen::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 lto_bool_t lto_module_get_macho_cputype(lto_module_t mod,
330                                         unsigned int *out_cputype,
331                                         unsigned int *out_cpusubtype) {
332   LTOModule *M = unwrap(mod);
333   Expected<uint32_t> CPUType = M->getMachOCPUType();
334   if (!CPUType) {
335     sLastErrorString = toString(CPUType.takeError());
336     return true;
337   }
338   *out_cputype = *CPUType;
339 
340   Expected<uint32_t> CPUSubType = M->getMachOCPUSubType();
341   if (!CPUSubType) {
342     sLastErrorString = toString(CPUSubType.takeError());
343     return true;
344   }
345   *out_cpusubtype = *CPUSubType;
346 
347   return false;
348 }
349 
350 void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
351                                         lto_diagnostic_handler_t diag_handler,
352                                         void *ctxt) {
353   unwrap(cg)->setDiagnosticHandler(diag_handler, ctxt);
354 }
355 
356 static lto_code_gen_t createCodeGen(bool InLocalContext) {
357   lto_initialize();
358 
359   TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags();
360 
361   LibLTOCodeGenerator *CodeGen =
362       InLocalContext ? new LibLTOCodeGenerator(std::make_unique<LLVMContext>())
363                      : new LibLTOCodeGenerator();
364   CodeGen->setTargetOptions(Options);
365   return wrap(CodeGen);
366 }
367 
368 lto_code_gen_t lto_codegen_create(void) {
369   return createCodeGen(/* InLocalContext */ false);
370 }
371 
372 lto_code_gen_t lto_codegen_create_in_local_context(void) {
373   return createCodeGen(/* InLocalContext */ true);
374 }
375 
376 void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); }
377 
378 bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) {
379   return !unwrap(cg)->addModule(unwrap(mod));
380 }
381 
382 void lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod) {
383   unwrap(cg)->setModule(std::unique_ptr<LTOModule>(unwrap(mod)));
384 }
385 
386 bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) {
387   unwrap(cg)->setDebugInfo(debug);
388   return false;
389 }
390 
391 bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) {
392   switch (model) {
393   case LTO_CODEGEN_PIC_MODEL_STATIC:
394     unwrap(cg)->setCodePICModel(Reloc::Static);
395     return false;
396   case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
397     unwrap(cg)->setCodePICModel(Reloc::PIC_);
398     return false;
399   case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
400     unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
401     return false;
402   case LTO_CODEGEN_PIC_MODEL_DEFAULT:
403     unwrap(cg)->setCodePICModel(None);
404     return false;
405   }
406   sLastErrorString = "Unknown PIC model";
407   return true;
408 }
409 
410 void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) {
411   return unwrap(cg)->setCpu(cpu);
412 }
413 
414 void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) {
415   // In here only for backwards compatibility. We use MC now.
416 }
417 
418 void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
419                                     int nargs) {
420   // In here only for backwards compatibility. We use MC now.
421 }
422 
423 void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg,
424                                           const char *symbol) {
425   unwrap(cg)->addMustPreserveSymbol(symbol);
426 }
427 
428 static void maybeParseOptions(lto_code_gen_t cg) {
429   if (!parsedOptions) {
430     unwrap(cg)->parseCodeGenDebugOptions();
431     lto_add_attrs(cg);
432     parsedOptions = true;
433   }
434 }
435 
436 bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) {
437   maybeParseOptions(cg);
438   return !unwrap(cg)->writeMergedModules(path);
439 }
440 
441 const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) {
442   maybeParseOptions(cg);
443   LibLTOCodeGenerator *CG = unwrap(cg);
444   CG->NativeObjectFile =
445       CG->compile(DisableVerify, DisableInline, DisableGVNLoadPRE,
446                   DisableLTOVectorization);
447   if (!CG->NativeObjectFile)
448     return nullptr;
449   *length = CG->NativeObjectFile->getBufferSize();
450   return CG->NativeObjectFile->getBufferStart();
451 }
452 
453 bool lto_codegen_optimize(lto_code_gen_t cg) {
454   maybeParseOptions(cg);
455   return !unwrap(cg)->optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
456                                DisableLTOVectorization);
457 }
458 
459 const void *lto_codegen_compile_optimized(lto_code_gen_t cg, size_t *length) {
460   maybeParseOptions(cg);
461   LibLTOCodeGenerator *CG = unwrap(cg);
462   CG->NativeObjectFile = CG->compileOptimized();
463   if (!CG->NativeObjectFile)
464     return nullptr;
465   *length = CG->NativeObjectFile->getBufferSize();
466   return CG->NativeObjectFile->getBufferStart();
467 }
468 
469 bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) {
470   maybeParseOptions(cg);
471   return !unwrap(cg)->compile_to_file(
472       name, DisableVerify, DisableInline, DisableGVNLoadPRE,
473       DisableLTOVectorization);
474 }
475 
476 void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) {
477   SmallVector<StringRef, 4> Options;
478   for (std::pair<StringRef, StringRef> o = getToken(opt); !o.first.empty();
479        o = getToken(o.second))
480     Options.push_back(o.first);
481 
482   unwrap(cg)->setCodeGenDebugOptions(Options);
483 }
484 
485 void lto_codegen_debug_options_array(lto_code_gen_t cg,
486                                      const char *const *options, int number) {
487   SmallVector<StringRef, 4> Options;
488   for (int i = 0; i < number; ++i)
489     Options.push_back(options[i]);
490   unwrap(cg)->setCodeGenDebugOptions(makeArrayRef(Options));
491 }
492 
493 unsigned int lto_api_version() { return LTO_API_VERSION; }
494 
495 void lto_codegen_set_should_internalize(lto_code_gen_t cg,
496                                         bool ShouldInternalize) {
497   unwrap(cg)->setShouldInternalize(ShouldInternalize);
498 }
499 
500 void lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
501                                            lto_bool_t ShouldEmbedUselists) {
502   unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists);
503 }
504 
505 // ThinLTO API below
506 
507 thinlto_code_gen_t thinlto_create_codegen(void) {
508   lto_initialize();
509   ThinLTOCodeGenerator *CodeGen = new ThinLTOCodeGenerator();
510   CodeGen->setTargetOptions(codegen::InitTargetOptionsFromCodeGenFlags());
511   CodeGen->setFreestanding(EnableFreestanding);
512 
513   if (OptLevel.getNumOccurrences()) {
514     if (OptLevel < '0' || OptLevel > '3')
515       report_fatal_error("Optimization level must be between 0 and 3");
516     CodeGen->setOptLevel(OptLevel - '0');
517     switch (OptLevel) {
518     case '0':
519       CodeGen->setCodeGenOptLevel(CodeGenOpt::None);
520       break;
521     case '1':
522       CodeGen->setCodeGenOptLevel(CodeGenOpt::Less);
523       break;
524     case '2':
525       CodeGen->setCodeGenOptLevel(CodeGenOpt::Default);
526       break;
527     case '3':
528       CodeGen->setCodeGenOptLevel(CodeGenOpt::Aggressive);
529       break;
530     }
531   }
532   return wrap(CodeGen);
533 }
534 
535 void thinlto_codegen_dispose(thinlto_code_gen_t cg) { delete unwrap(cg); }
536 
537 void thinlto_codegen_add_module(thinlto_code_gen_t cg, const char *Identifier,
538                                 const char *Data, int Length) {
539   unwrap(cg)->addModule(Identifier, StringRef(Data, Length));
540 }
541 
542 void thinlto_codegen_process(thinlto_code_gen_t cg) { unwrap(cg)->run(); }
543 
544 unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg) {
545   return unwrap(cg)->getProducedBinaries().size();
546 }
547 LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg,
548                                           unsigned int index) {
549   assert(index < unwrap(cg)->getProducedBinaries().size() && "Index overflow");
550   auto &MemBuffer = unwrap(cg)->getProducedBinaries()[index];
551   return LTOObjectBuffer{MemBuffer->getBufferStart(),
552                          MemBuffer->getBufferSize()};
553 }
554 
555 unsigned int thinlto_module_get_num_object_files(thinlto_code_gen_t cg) {
556   return unwrap(cg)->getProducedBinaryFiles().size();
557 }
558 const char *thinlto_module_get_object_file(thinlto_code_gen_t cg,
559                                            unsigned int index) {
560   assert(index < unwrap(cg)->getProducedBinaryFiles().size() &&
561          "Index overflow");
562   return unwrap(cg)->getProducedBinaryFiles()[index].c_str();
563 }
564 
565 void thinlto_codegen_disable_codegen(thinlto_code_gen_t cg,
566                                      lto_bool_t disable) {
567   unwrap(cg)->disableCodeGen(disable);
568 }
569 
570 void thinlto_codegen_set_codegen_only(thinlto_code_gen_t cg,
571                                       lto_bool_t CodeGenOnly) {
572   unwrap(cg)->setCodeGenOnly(CodeGenOnly);
573 }
574 
575 void thinlto_debug_options(const char *const *options, int number) {
576   // if options were requested, set them
577   if (number && options) {
578     std::vector<const char *> CodegenArgv(1, "libLTO");
579     for (auto Arg : ArrayRef<const char *>(options, number))
580       CodegenArgv.push_back(Arg);
581     cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data());
582   }
583 }
584 
585 lto_bool_t lto_module_is_thinlto(lto_module_t mod) {
586   return unwrap(mod)->isThinLTO();
587 }
588 
589 void thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg,
590                                               const char *Name, int Length) {
591   unwrap(cg)->preserveSymbol(StringRef(Name, Length));
592 }
593 
594 void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,
595                                                  const char *Name, int Length) {
596   unwrap(cg)->crossReferenceSymbol(StringRef(Name, Length));
597 }
598 
599 void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu) {
600   return unwrap(cg)->setCpu(cpu);
601 }
602 
603 void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
604                                    const char *cache_dir) {
605   return unwrap(cg)->setCacheDir(cache_dir);
606 }
607 
608 void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
609                                                 int interval) {
610   return unwrap(cg)->setCachePruningInterval(interval);
611 }
612 
613 void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
614                                                 unsigned expiration) {
615   return unwrap(cg)->setCacheEntryExpiration(expiration);
616 }
617 
618 void thinlto_codegen_set_final_cache_size_relative_to_available_space(
619     thinlto_code_gen_t cg, unsigned Percentage) {
620   return unwrap(cg)->setMaxCacheSizeRelativeToAvailableSpace(Percentage);
621 }
622 
623 void thinlto_codegen_set_cache_size_bytes(
624     thinlto_code_gen_t cg, unsigned MaxSizeBytes) {
625   return unwrap(cg)->setCacheMaxSizeBytes(MaxSizeBytes);
626 }
627 
628 void thinlto_codegen_set_cache_size_megabytes(
629     thinlto_code_gen_t cg, unsigned MaxSizeMegabytes) {
630   uint64_t MaxSizeBytes = MaxSizeMegabytes;
631   MaxSizeBytes *= 1024 * 1024;
632   return unwrap(cg)->setCacheMaxSizeBytes(MaxSizeBytes);
633 }
634 
635 void thinlto_codegen_set_cache_size_files(
636     thinlto_code_gen_t cg, unsigned MaxSizeFiles) {
637   return unwrap(cg)->setCacheMaxSizeFiles(MaxSizeFiles);
638 }
639 
640 void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,
641                                        const char *save_temps_dir) {
642   return unwrap(cg)->setSaveTempsDir(save_temps_dir);
643 }
644 
645 void thinlto_set_generated_objects_dir(thinlto_code_gen_t cg,
646                                        const char *save_temps_dir) {
647   unwrap(cg)->setGeneratedObjectsDirectory(save_temps_dir);
648 }
649 
650 lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,
651                                          lto_codegen_model model) {
652   switch (model) {
653   case LTO_CODEGEN_PIC_MODEL_STATIC:
654     unwrap(cg)->setCodePICModel(Reloc::Static);
655     return false;
656   case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
657     unwrap(cg)->setCodePICModel(Reloc::PIC_);
658     return false;
659   case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
660     unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
661     return false;
662   case LTO_CODEGEN_PIC_MODEL_DEFAULT:
663     unwrap(cg)->setCodePICModel(None);
664     return false;
665   }
666   sLastErrorString = "Unknown PIC model";
667   return true;
668 }
669 
670 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(lto::InputFile, lto_input_t)
671 
672 lto_input_t lto_input_create(const void *buffer, size_t buffer_size, const char *path) {
673   return wrap(LTOModule::createInputFile(buffer, buffer_size, path, sLastErrorString));
674 }
675 
676 void lto_input_dispose(lto_input_t input) {
677   delete unwrap(input);
678 }
679 
680 extern unsigned lto_input_get_num_dependent_libraries(lto_input_t input) {
681   return LTOModule::getDependentLibraryCount(unwrap(input));
682 }
683 
684 extern const char *lto_input_get_dependent_library(lto_input_t input,
685                                                    size_t index,
686                                                    size_t *size) {
687   return LTOModule::getDependentLibrary(unwrap(input), index, size);
688 }
689 
690 extern const char *const *lto_runtime_lib_symbols_list(size_t *size) {
691   auto symbols = lto::LTO::getRuntimeLibcallSymbols();
692   *size = symbols.size();
693   return symbols.data();
694 }
695