xref: /llvm-project/llvm/tools/lto/lto.cpp (revision 66e9078f827383f77c1c239f6c09f2b07a963649)
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/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/MemoryBuffer.h"
28 #include "llvm/Support/Signals.h"
29 #include "llvm/Support/TargetSelect.h"
30 #include "llvm/Support/raw_ostream.h"
31 
32 using namespace llvm;
33 
34 static codegen::RegisterCodeGenFlags CGF;
35 
36 // extra command-line flags needed for LTOCodeGenerator
37 static cl::opt<char>
38     OptLevel("O",
39              cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
40                       "(default = '-O2')"),
41              cl::Prefix, cl::init('2'));
42 
43 static cl::opt<bool> EnableFreestanding(
44     "lto-freestanding", cl::init(false),
45     cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
46 
47 #ifdef NDEBUG
48 static bool VerifyByDefault = false;
49 #else
50 static bool VerifyByDefault = true;
51 #endif
52 
53 static cl::opt<bool> DisableVerify(
54     "disable-llvm-verifier", cl::init(!VerifyByDefault),
55     cl::desc("Don't run the LLVM verifier during the optimization pipeline"));
56 
57 // Holds most recent error string.
58 // *** Not thread safe ***
59 static std::string sLastErrorString;
60 
61 // Holds the initialization state of the LTO module.
62 // *** Not thread safe ***
63 static bool initialized = false;
64 
65 // Represent the state of parsing command line debug options.
66 static enum class OptParsingState {
67   NotParsed, // Initial state.
68   Early,     // After lto_set_debug_options is called.
69   Done       // After maybeParseOptions is called.
70 } optionParsingState = OptParsingState::NotParsed;
71 
72 static LLVMContext *LTOContext = nullptr;
73 
74 struct LTOToolDiagnosticHandler : public DiagnosticHandler {
75   bool handleDiagnostics(const DiagnosticInfo &DI) override {
76     if (DI.getSeverity() != DS_Error) {
77       DiagnosticPrinterRawOStream DP(errs());
78       DI.print(DP);
79       errs() << '\n';
80       return true;
81     }
82     sLastErrorString = "";
83     {
84       raw_string_ostream Stream(sLastErrorString);
85       DiagnosticPrinterRawOStream DP(Stream);
86       DI.print(DP);
87     }
88     return true;
89   }
90 };
91 
92 static SmallVector<const char *> RuntimeLibcallSymbols;
93 
94 // Initialize the configured targets if they have not been initialized.
95 static void lto_initialize() {
96   if (!initialized) {
97 #ifdef _WIN32
98     // Dialog box on crash disabling doesn't work across DLL boundaries, so do
99     // it here.
100     llvm::sys::DisableSystemDialogsOnCrash();
101 #endif
102 
103     InitializeAllTargetInfos();
104     InitializeAllTargets();
105     InitializeAllTargetMCs();
106     InitializeAllAsmParsers();
107     InitializeAllAsmPrinters();
108     InitializeAllDisassemblers();
109 
110     static LLVMContext Context;
111     LTOContext = &Context;
112     LTOContext->setDiagnosticHandler(
113         std::make_unique<LTOToolDiagnosticHandler>(), true);
114     RuntimeLibcallSymbols = lto::LTO::getRuntimeLibcallSymbols(Triple());
115     initialized = true;
116   }
117 }
118 
119 namespace {
120 
121 static void handleLibLTODiagnostic(lto_codegen_diagnostic_severity_t Severity,
122                                    const char *Msg, void *) {
123   sLastErrorString = Msg;
124 }
125 
126 // This derived class owns the native object file. This helps implement the
127 // libLTO API semantics, which require that the code generator owns the object
128 // file.
129 struct LibLTOCodeGenerator : LTOCodeGenerator {
130   LibLTOCodeGenerator() : LTOCodeGenerator(*LTOContext) { init(); }
131   LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context)
132       : LTOCodeGenerator(*Context), OwnedContext(std::move(Context)) {
133     init();
134   }
135 
136   // Reset the module first in case MergedModule is created in OwnedContext.
137   // Module must be destructed before its context gets destructed.
138   ~LibLTOCodeGenerator() { resetMergedModule(); }
139 
140   void init() { setDiagnosticHandler(handleLibLTODiagnostic, nullptr); }
141 
142   std::unique_ptr<MemoryBuffer> NativeObjectFile;
143   std::unique_ptr<LLVMContext> OwnedContext;
144 };
145 
146 }
147 
148 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t)
149 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThinLTOCodeGenerator, thinlto_code_gen_t)
150 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t)
151 
152 // Convert the subtarget features into a string to pass to LTOCodeGenerator.
153 static void lto_add_attrs(lto_code_gen_t cg) {
154   LTOCodeGenerator *CG = unwrap(cg);
155   CG->setAttrs(codegen::getMAttrs());
156 
157   if (OptLevel < '0' || OptLevel > '3')
158     report_fatal_error("Optimization level must be between 0 and 3");
159   CG->setOptLevel(OptLevel - '0');
160   CG->setFreestanding(EnableFreestanding);
161   CG->setDisableVerify(DisableVerify);
162 }
163 
164 extern const char* lto_get_version() {
165   return LTOCodeGenerator::getVersionString();
166 }
167 
168 const char* lto_get_error_message() {
169   return sLastErrorString.c_str();
170 }
171 
172 bool lto_module_is_object_file(const char* path) {
173   return LTOModule::isBitcodeFile(StringRef(path));
174 }
175 
176 bool lto_module_is_object_file_for_target(const char* path,
177                                           const char* target_triplet_prefix) {
178   ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(path);
179   if (!Buffer)
180     return false;
181   return LTOModule::isBitcodeForTarget(Buffer->get(),
182                                        StringRef(target_triplet_prefix));
183 }
184 
185 bool lto_module_has_objc_category(const void *mem, size_t length) {
186   std::unique_ptr<MemoryBuffer> Buffer(LTOModule::makeBuffer(mem, length));
187   if (!Buffer)
188     return false;
189   LLVMContext Ctx;
190   ErrorOr<bool> Result = expectedToErrorOrAndEmitErrors(
191       Ctx, llvm::isBitcodeContainingObjCCategory(*Buffer));
192   return Result && *Result;
193 }
194 
195 bool lto_module_is_object_file_in_memory(const void* mem, size_t length) {
196   return LTOModule::isBitcodeFile(mem, length);
197 }
198 
199 bool
200 lto_module_is_object_file_in_memory_for_target(const void* mem,
201                                             size_t length,
202                                             const char* target_triplet_prefix) {
203   std::unique_ptr<MemoryBuffer> buffer(LTOModule::makeBuffer(mem, length));
204   if (!buffer)
205     return false;
206   return LTOModule::isBitcodeForTarget(buffer.get(),
207                                        StringRef(target_triplet_prefix));
208 }
209 
210 lto_module_t lto_module_create(const char* path) {
211   lto_initialize();
212   llvm::TargetOptions Options =
213       codegen::InitTargetOptionsFromCodeGenFlags(Triple());
214   ErrorOr<std::unique_ptr<LTOModule>> M =
215       LTOModule::createFromFile(*LTOContext, StringRef(path), Options);
216   if (!M)
217     return nullptr;
218   return wrap(M->release());
219 }
220 
221 lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {
222   lto_initialize();
223   llvm::TargetOptions Options =
224       codegen::InitTargetOptionsFromCodeGenFlags(Triple());
225   ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFile(
226       *LTOContext, fd, StringRef(path), size, Options);
227   if (!M)
228     return nullptr;
229   return wrap(M->release());
230 }
231 
232 lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
233                                                  size_t file_size,
234                                                  size_t map_size,
235                                                  off_t offset) {
236   lto_initialize();
237   llvm::TargetOptions Options =
238       codegen::InitTargetOptionsFromCodeGenFlags(Triple());
239   ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFileSlice(
240       *LTOContext, fd, StringRef(path), map_size, offset, Options);
241   if (!M)
242     return nullptr;
243   return wrap(M->release());
244 }
245 
246 lto_module_t lto_module_create_from_memory(const void* mem, size_t length) {
247   lto_initialize();
248   llvm::TargetOptions Options =
249       codegen::InitTargetOptionsFromCodeGenFlags(Triple());
250   ErrorOr<std::unique_ptr<LTOModule>> M =
251       LTOModule::createFromBuffer(*LTOContext, mem, length, Options);
252   if (!M)
253     return nullptr;
254   return wrap(M->release());
255 }
256 
257 lto_module_t lto_module_create_from_memory_with_path(const void* mem,
258                                                      size_t length,
259                                                      const char *path) {
260   lto_initialize();
261   llvm::TargetOptions Options =
262       codegen::InitTargetOptionsFromCodeGenFlags(Triple());
263   ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer(
264       *LTOContext, mem, length, Options, StringRef(path));
265   if (!M)
266     return nullptr;
267   return wrap(M->release());
268 }
269 
270 lto_module_t lto_module_create_in_local_context(const void *mem, size_t length,
271                                                 const char *path) {
272   lto_initialize();
273   llvm::TargetOptions Options =
274       codegen::InitTargetOptionsFromCodeGenFlags(Triple());
275 
276   // Create a local context. Ownership will be transferred to LTOModule.
277   std::unique_ptr<LLVMContext> Context = std::make_unique<LLVMContext>();
278   Context->setDiagnosticHandler(std::make_unique<LTOToolDiagnosticHandler>(),
279                                 true);
280 
281   ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createInLocalContext(
282       std::move(Context), mem, length, Options, StringRef(path));
283   if (!M)
284     return nullptr;
285   return wrap(M->release());
286 }
287 
288 lto_module_t lto_module_create_in_codegen_context(const void *mem,
289                                                   size_t length,
290                                                   const char *path,
291                                                   lto_code_gen_t cg) {
292   lto_initialize();
293   llvm::TargetOptions Options =
294       codegen::InitTargetOptionsFromCodeGenFlags(Triple());
295   ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer(
296       unwrap(cg)->getContext(), mem, length, Options, StringRef(path));
297   if (!M)
298     return nullptr;
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(Triple());
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(std::nullopt);
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 (optionParsingState != OptParsingState::Done) {
430     // Parse options if any were set by the lto_codegen_debug_options* function.
431     unwrap(cg)->parseCodeGenDebugOptions();
432     lto_add_attrs(cg);
433     optionParsingState = OptParsingState::Done;
434   }
435 }
436 
437 bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) {
438   maybeParseOptions(cg);
439   return !unwrap(cg)->writeMergedModules(path);
440 }
441 
442 const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) {
443   maybeParseOptions(cg);
444   LibLTOCodeGenerator *CG = unwrap(cg);
445   CG->NativeObjectFile = CG->compile();
446   if (!CG->NativeObjectFile)
447     return nullptr;
448   *length = CG->NativeObjectFile->getBufferSize();
449   return CG->NativeObjectFile->getBufferStart();
450 }
451 
452 bool lto_codegen_optimize(lto_code_gen_t cg) {
453   maybeParseOptions(cg);
454   return !unwrap(cg)->optimize();
455 }
456 
457 const void *lto_codegen_compile_optimized(lto_code_gen_t cg, size_t *length) {
458   maybeParseOptions(cg);
459   LibLTOCodeGenerator *CG = unwrap(cg);
460   CG->NativeObjectFile = CG->compileOptimized();
461   if (!CG->NativeObjectFile)
462     return nullptr;
463   *length = CG->NativeObjectFile->getBufferSize();
464   return CG->NativeObjectFile->getBufferStart();
465 }
466 
467 bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) {
468   maybeParseOptions(cg);
469   return !unwrap(cg)->compile_to_file(name);
470 }
471 
472 void lto_set_debug_options(const char *const *options, int number) {
473   assert(optionParsingState == OptParsingState::NotParsed &&
474          "option processing already happened");
475   // Need to put each suboption in a null-terminated string before passing to
476   // parseCommandLineOptions().
477   std::vector<std::string> Options;
478   for (int i = 0; i < number; ++i)
479     Options.push_back(options[i]);
480 
481   llvm::parseCommandLineOptions(Options);
482   optionParsingState = OptParsingState::Early;
483 }
484 
485 void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) {
486   assert(optionParsingState != OptParsingState::Early &&
487          "early option processing already happened");
488   SmallVector<StringRef, 4> Options;
489   for (std::pair<StringRef, StringRef> o = getToken(opt); !o.first.empty();
490        o = getToken(o.second))
491     Options.push_back(o.first);
492 
493   unwrap(cg)->setCodeGenDebugOptions(Options);
494 }
495 
496 void lto_codegen_debug_options_array(lto_code_gen_t cg,
497                                      const char *const *options, int number) {
498   assert(optionParsingState != OptParsingState::Early &&
499          "early option processing already happened");
500   SmallVector<StringRef, 4> Options;
501   for (int i = 0; i < number; ++i)
502     Options.push_back(options[i]);
503   unwrap(cg)->setCodeGenDebugOptions(ArrayRef(Options));
504 }
505 
506 unsigned int lto_api_version() { return LTO_API_VERSION; }
507 
508 void lto_codegen_set_should_internalize(lto_code_gen_t cg,
509                                         bool ShouldInternalize) {
510   unwrap(cg)->setShouldInternalize(ShouldInternalize);
511 }
512 
513 void lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
514                                            lto_bool_t ShouldEmbedUselists) {
515   unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists);
516 }
517 
518 lto_bool_t lto_module_has_ctor_dtor(lto_module_t mod) {
519   return unwrap(mod)->hasCtorDtor();
520 }
521 
522 // ThinLTO API below
523 
524 thinlto_code_gen_t thinlto_create_codegen(void) {
525   lto_initialize();
526   ThinLTOCodeGenerator *CodeGen = new ThinLTOCodeGenerator();
527   CodeGen->setTargetOptions(
528       codegen::InitTargetOptionsFromCodeGenFlags(Triple()));
529   CodeGen->setFreestanding(EnableFreestanding);
530 
531   if (OptLevel.getNumOccurrences()) {
532     if (OptLevel < '0' || OptLevel > '3')
533       report_fatal_error("Optimization level must be between 0 and 3");
534     CodeGen->setOptLevel(OptLevel - '0');
535     std::optional<CodeGenOptLevel> CGOptLevelOrNone =
536         CodeGenOpt::getLevel(OptLevel - '0');
537     assert(CGOptLevelOrNone);
538     CodeGen->setCodeGenOptLevel(*CGOptLevelOrNone);
539   }
540   return wrap(CodeGen);
541 }
542 
543 void thinlto_codegen_dispose(thinlto_code_gen_t cg) { delete unwrap(cg); }
544 
545 void thinlto_codegen_add_module(thinlto_code_gen_t cg, const char *Identifier,
546                                 const char *Data, int Length) {
547   unwrap(cg)->addModule(Identifier, StringRef(Data, Length));
548 }
549 
550 void thinlto_codegen_process(thinlto_code_gen_t cg) { unwrap(cg)->run(); }
551 
552 unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg) {
553   return unwrap(cg)->getProducedBinaries().size();
554 }
555 LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg,
556                                           unsigned int index) {
557   assert(index < unwrap(cg)->getProducedBinaries().size() && "Index overflow");
558   auto &MemBuffer = unwrap(cg)->getProducedBinaries()[index];
559   return LTOObjectBuffer{MemBuffer->getBufferStart(),
560                          MemBuffer->getBufferSize()};
561 }
562 
563 unsigned int thinlto_module_get_num_object_files(thinlto_code_gen_t cg) {
564   return unwrap(cg)->getProducedBinaryFiles().size();
565 }
566 const char *thinlto_module_get_object_file(thinlto_code_gen_t cg,
567                                            unsigned int index) {
568   assert(index < unwrap(cg)->getProducedBinaryFiles().size() &&
569          "Index overflow");
570   return unwrap(cg)->getProducedBinaryFiles()[index].c_str();
571 }
572 
573 void thinlto_codegen_disable_codegen(thinlto_code_gen_t cg,
574                                      lto_bool_t disable) {
575   unwrap(cg)->disableCodeGen(disable);
576 }
577 
578 void thinlto_codegen_set_codegen_only(thinlto_code_gen_t cg,
579                                       lto_bool_t CodeGenOnly) {
580   unwrap(cg)->setCodeGenOnly(CodeGenOnly);
581 }
582 
583 void thinlto_debug_options(const char *const *options, int number) {
584   // if options were requested, set them
585   if (number && options) {
586     std::vector<const char *> CodegenArgv(1, "libLTO");
587     append_range(CodegenArgv, ArrayRef<const char *>(options, number));
588     cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data());
589   }
590 }
591 
592 lto_bool_t lto_module_is_thinlto(lto_module_t mod) {
593   return unwrap(mod)->isThinLTO();
594 }
595 
596 void thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg,
597                                               const char *Name, int Length) {
598   unwrap(cg)->preserveSymbol(StringRef(Name, Length));
599 }
600 
601 void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,
602                                                  const char *Name, int Length) {
603   unwrap(cg)->crossReferenceSymbol(StringRef(Name, Length));
604 }
605 
606 void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu) {
607   return unwrap(cg)->setCpu(cpu);
608 }
609 
610 void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
611                                    const char *cache_dir) {
612   return unwrap(cg)->setCacheDir(cache_dir);
613 }
614 
615 void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
616                                                 int interval) {
617   return unwrap(cg)->setCachePruningInterval(interval);
618 }
619 
620 void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
621                                                 unsigned expiration) {
622   return unwrap(cg)->setCacheEntryExpiration(expiration);
623 }
624 
625 void thinlto_codegen_set_final_cache_size_relative_to_available_space(
626     thinlto_code_gen_t cg, unsigned Percentage) {
627   return unwrap(cg)->setMaxCacheSizeRelativeToAvailableSpace(Percentage);
628 }
629 
630 void thinlto_codegen_set_cache_size_bytes(
631     thinlto_code_gen_t cg, unsigned MaxSizeBytes) {
632   return unwrap(cg)->setCacheMaxSizeBytes(MaxSizeBytes);
633 }
634 
635 void thinlto_codegen_set_cache_size_megabytes(
636     thinlto_code_gen_t cg, unsigned MaxSizeMegabytes) {
637   uint64_t MaxSizeBytes = MaxSizeMegabytes;
638   MaxSizeBytes *= 1024 * 1024;
639   return unwrap(cg)->setCacheMaxSizeBytes(MaxSizeBytes);
640 }
641 
642 void thinlto_codegen_set_cache_size_files(
643     thinlto_code_gen_t cg, unsigned MaxSizeFiles) {
644   return unwrap(cg)->setCacheMaxSizeFiles(MaxSizeFiles);
645 }
646 
647 void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,
648                                        const char *save_temps_dir) {
649   return unwrap(cg)->setSaveTempsDir(save_temps_dir);
650 }
651 
652 void thinlto_set_generated_objects_dir(thinlto_code_gen_t cg,
653                                        const char *save_temps_dir) {
654   unwrap(cg)->setGeneratedObjectsDirectory(save_temps_dir);
655 }
656 
657 lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,
658                                          lto_codegen_model model) {
659   switch (model) {
660   case LTO_CODEGEN_PIC_MODEL_STATIC:
661     unwrap(cg)->setCodePICModel(Reloc::Static);
662     return false;
663   case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
664     unwrap(cg)->setCodePICModel(Reloc::PIC_);
665     return false;
666   case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
667     unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
668     return false;
669   case LTO_CODEGEN_PIC_MODEL_DEFAULT:
670     unwrap(cg)->setCodePICModel(std::nullopt);
671     return false;
672   }
673   sLastErrorString = "Unknown PIC model";
674   return true;
675 }
676 
677 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(lto::InputFile, lto_input_t)
678 
679 lto_input_t lto_input_create(const void *buffer, size_t buffer_size, const char *path) {
680   return wrap(LTOModule::createInputFile(buffer, buffer_size, path, sLastErrorString));
681 }
682 
683 void lto_input_dispose(lto_input_t input) {
684   delete unwrap(input);
685 }
686 
687 extern unsigned lto_input_get_num_dependent_libraries(lto_input_t input) {
688   return LTOModule::getDependentLibraryCount(unwrap(input));
689 }
690 
691 extern const char *lto_input_get_dependent_library(lto_input_t input,
692                                                    size_t index,
693                                                    size_t *size) {
694   return LTOModule::getDependentLibrary(unwrap(input), index, size);
695 }
696 
697 extern const char *const *lto_runtime_lib_symbols_list(size_t *size) {
698   *size = RuntimeLibcallSymbols.size();
699   return RuntimeLibcallSymbols.data();
700 }
701