xref: /llvm-project-15.0.7/llvm/tools/lto/lto.cpp (revision 4d75e8d6)
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/CodeGen/CommandFlags.h"
18 #include "llvm/IR/DiagnosticInfo.h"
19 #include "llvm/IR/DiagnosticPrinter.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/LTO/LTOCodeGenerator.h"
22 #include "llvm/LTO/LTOModule.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/Signals.h"
25 #include "llvm/Support/TargetSelect.h"
26 #include "llvm/Support/raw_ostream.h"
27 
28 // extra command-line flags needed for LTOCodeGenerator
29 static cl::opt<char>
30 OptLevel("O",
31          cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
32                   "(default = '-O2')"),
33          cl::Prefix,
34          cl::ZeroOrMore,
35          cl::init('2'));
36 
37 static cl::opt<bool>
38 DisableInline("disable-inlining", cl::init(false),
39   cl::desc("Do not run the inliner pass"));
40 
41 static cl::opt<bool>
42 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
43   cl::desc("Do not run the GVN load PRE pass"));
44 
45 static cl::opt<bool>
46 DisableLTOVectorization("disable-lto-vectorization", cl::init(false),
47   cl::desc("Do not run loop or slp vectorization during LTO"));
48 
49 #ifdef NDEBUG
50 static bool VerifyByDefault = false;
51 #else
52 static bool VerifyByDefault = true;
53 #endif
54 
55 static cl::opt<bool> DisableVerify(
56     "disable-llvm-verifier", cl::init(!VerifyByDefault),
57     cl::desc("Don't run the LLVM verifier during the optimization pipeline"));
58 
59 // Holds most recent error string.
60 // *** Not thread safe ***
61 static std::string sLastErrorString;
62 
63 // Holds the initialization state of the LTO module.
64 // *** Not thread safe ***
65 static bool initialized = false;
66 
67 // Holds the command-line option parsing state of the LTO module.
68 static bool parsedOptions = false;
69 
70 static LLVMContext *LTOContext = nullptr;
71 
72 static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
73   if (DI.getSeverity() != DS_Error) {
74     DiagnosticPrinterRawOStream DP(errs());
75     DI.print(DP);
76     errs() << '\n';
77     return;
78   }
79   sLastErrorString = "";
80   {
81     raw_string_ostream Stream(sLastErrorString);
82     DiagnosticPrinterRawOStream DP(Stream);
83     DI.print(DP);
84   }
85 }
86 
87 // Initialize the configured targets if they have not been initialized.
88 static void lto_initialize() {
89   if (!initialized) {
90 #ifdef LLVM_ON_WIN32
91     // Dialog box on crash disabling doesn't work across DLL boundaries, so do
92     // it here.
93     llvm::sys::DisableSystemDialogsOnCrash();
94 #endif
95 
96     InitializeAllTargetInfos();
97     InitializeAllTargets();
98     InitializeAllTargetMCs();
99     InitializeAllAsmParsers();
100     InitializeAllAsmPrinters();
101     InitializeAllDisassemblers();
102 
103     LTOContext = &getGlobalContext();
104     LTOContext->setDiagnosticHandler(diagnosticHandler, nullptr, true);
105     initialized = true;
106   }
107 }
108 
109 namespace {
110 
111 static void handleLibLTODiagnostic(lto_codegen_diagnostic_severity_t Severity,
112                                    const char *Msg, void *) {
113   sLastErrorString = Msg;
114 }
115 
116 // This derived class owns the native object file. This helps implement the
117 // libLTO API semantics, which require that the code generator owns the object
118 // file.
119 struct LibLTOCodeGenerator : LTOCodeGenerator {
120   LibLTOCodeGenerator() : LTOCodeGenerator(*LTOContext) {
121     setDiagnosticHandler(handleLibLTODiagnostic, nullptr); }
122   LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context)
123       : LTOCodeGenerator(*Context), OwnedContext(std::move(Context)) {
124     setDiagnosticHandler(handleLibLTODiagnostic, nullptr); }
125 
126   // Reset the module first in case MergedModule is created in OwnedContext.
127   // Module must be destructed before its context gets destructed.
128   ~LibLTOCodeGenerator() { resetMergedModule(); }
129 
130   std::unique_ptr<MemoryBuffer> NativeObjectFile;
131   std::unique_ptr<LLVMContext> OwnedContext;
132 };
133 
134 }
135 
136 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t)
137 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t)
138 
139 // Convert the subtarget features into a string to pass to LTOCodeGenerator.
140 static void lto_add_attrs(lto_code_gen_t cg) {
141   LTOCodeGenerator *CG = unwrap(cg);
142   if (MAttrs.size()) {
143     std::string attrs;
144     for (unsigned i = 0; i < MAttrs.size(); ++i) {
145       if (i > 0)
146         attrs.append(",");
147       attrs.append(MAttrs[i]);
148     }
149 
150     CG->setAttr(attrs.c_str());
151   }
152 
153   if (OptLevel < '0' || OptLevel > '3')
154     report_fatal_error("Optimization level must be between 0 and 3");
155   CG->setOptLevel(OptLevel - '0');
156 }
157 
158 extern const char* lto_get_version() {
159   return LTOCodeGenerator::getVersionString();
160 }
161 
162 const char* lto_get_error_message() {
163   return sLastErrorString.c_str();
164 }
165 
166 bool lto_module_is_object_file(const char* path) {
167   return LTOModule::isBitcodeFile(path);
168 }
169 
170 bool lto_module_is_object_file_for_target(const char* path,
171                                           const char* target_triplet_prefix) {
172   ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(path);
173   if (!Buffer)
174     return false;
175   return LTOModule::isBitcodeForTarget(Buffer->get(), target_triplet_prefix);
176 }
177 
178 bool lto_module_is_object_file_in_memory(const void* mem, size_t length) {
179   return LTOModule::isBitcodeFile(mem, length);
180 }
181 
182 bool
183 lto_module_is_object_file_in_memory_for_target(const void* mem,
184                                             size_t length,
185                                             const char* target_triplet_prefix) {
186   std::unique_ptr<MemoryBuffer> buffer(LTOModule::makeBuffer(mem, length));
187   if (!buffer)
188     return false;
189   return LTOModule::isBitcodeForTarget(buffer.get(), target_triplet_prefix);
190 }
191 
192 lto_module_t lto_module_create(const char* path) {
193   lto_initialize();
194   llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
195   ErrorOr<std::unique_ptr<LTOModule>> M =
196       LTOModule::createFromFile(*LTOContext, path, Options);
197   if (!M)
198     return nullptr;
199   return wrap(M->release());
200 }
201 
202 lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {
203   lto_initialize();
204   llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
205   ErrorOr<std::unique_ptr<LTOModule>> M =
206       LTOModule::createFromOpenFile(*LTOContext, fd, path, size, Options);
207   if (!M)
208     return nullptr;
209   return wrap(M->release());
210 }
211 
212 lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
213                                                  size_t file_size,
214                                                  size_t map_size,
215                                                  off_t offset) {
216   lto_initialize();
217   llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
218   ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFileSlice(
219       *LTOContext, fd, path, map_size, offset, Options);
220   if (!M)
221     return nullptr;
222   return wrap(M->release());
223 }
224 
225 lto_module_t lto_module_create_from_memory(const void* mem, size_t length) {
226   lto_initialize();
227   llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
228   ErrorOr<std::unique_ptr<LTOModule>> M =
229       LTOModule::createFromBuffer(*LTOContext, mem, length, Options);
230   if (!M)
231     return nullptr;
232   return wrap(M->release());
233 }
234 
235 lto_module_t lto_module_create_from_memory_with_path(const void* mem,
236                                                      size_t length,
237                                                      const char *path) {
238   lto_initialize();
239   llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
240   ErrorOr<std::unique_ptr<LTOModule>> M =
241       LTOModule::createFromBuffer(*LTOContext, mem, length, Options, path);
242   if (!M)
243     return nullptr;
244   return wrap(M->release());
245 }
246 
247 lto_module_t lto_module_create_in_local_context(const void *mem, size_t length,
248                                                 const char *path) {
249   lto_initialize();
250   llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
251   ErrorOr<std::unique_ptr<LTOModule>> M =
252       LTOModule::createInLocalContext(mem, length, Options, path);
253   if (!M)
254     return nullptr;
255   return wrap(M->release());
256 }
257 
258 lto_module_t lto_module_create_in_codegen_context(const void *mem,
259                                                   size_t length,
260                                                   const char *path,
261                                                   lto_code_gen_t cg) {
262   lto_initialize();
263   llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
264   ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createInContext(
265       mem, length, Options, path, &unwrap(cg)->getContext());
266   return wrap(M->release());
267 }
268 
269 void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); }
270 
271 const char* lto_module_get_target_triple(lto_module_t mod) {
272   return unwrap(mod)->getTargetTriple().c_str();
273 }
274 
275 void lto_module_set_target_triple(lto_module_t mod, const char *triple) {
276   return unwrap(mod)->setTargetTriple(triple);
277 }
278 
279 unsigned int lto_module_get_num_symbols(lto_module_t mod) {
280   return unwrap(mod)->getSymbolCount();
281 }
282 
283 const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) {
284   return unwrap(mod)->getSymbolName(index);
285 }
286 
287 lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,
288                                                       unsigned int index) {
289   return unwrap(mod)->getSymbolAttributes(index);
290 }
291 
292 const char* lto_module_get_linkeropts(lto_module_t mod) {
293   return unwrap(mod)->getLinkerOpts();
294 }
295 
296 void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
297                                         lto_diagnostic_handler_t diag_handler,
298                                         void *ctxt) {
299   unwrap(cg)->setDiagnosticHandler(diag_handler, ctxt);
300 }
301 
302 static lto_code_gen_t createCodeGen(bool InLocalContext) {
303   lto_initialize();
304 
305   TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
306 
307   LibLTOCodeGenerator *CodeGen =
308       InLocalContext ? new LibLTOCodeGenerator(make_unique<LLVMContext>())
309                      : new LibLTOCodeGenerator();
310   CodeGen->setTargetOptions(Options);
311   return wrap(CodeGen);
312 }
313 
314 lto_code_gen_t lto_codegen_create(void) {
315   return createCodeGen(/* InLocalContext */ false);
316 }
317 
318 lto_code_gen_t lto_codegen_create_in_local_context(void) {
319   return createCodeGen(/* InLocalContext */ true);
320 }
321 
322 void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); }
323 
324 bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) {
325   return !unwrap(cg)->addModule(unwrap(mod));
326 }
327 
328 void lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod) {
329   unwrap(cg)->setModule(std::unique_ptr<LTOModule>(unwrap(mod)));
330 }
331 
332 bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) {
333   unwrap(cg)->setDebugInfo(debug);
334   return false;
335 }
336 
337 bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) {
338   switch (model) {
339   case LTO_CODEGEN_PIC_MODEL_STATIC:
340     unwrap(cg)->setCodePICModel(Reloc::Static);
341     return false;
342   case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
343     unwrap(cg)->setCodePICModel(Reloc::PIC_);
344     return false;
345   case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
346     unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
347     return false;
348   case LTO_CODEGEN_PIC_MODEL_DEFAULT:
349     unwrap(cg)->setCodePICModel(Reloc::Default);
350     return false;
351   }
352   sLastErrorString = "Unknown PIC model";
353   return true;
354 }
355 
356 void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) {
357   return unwrap(cg)->setCpu(cpu);
358 }
359 
360 void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) {
361   // In here only for backwards compatibility. We use MC now.
362 }
363 
364 void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
365                                     int nargs) {
366   // In here only for backwards compatibility. We use MC now.
367 }
368 
369 void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg,
370                                           const char *symbol) {
371   unwrap(cg)->addMustPreserveSymbol(symbol);
372 }
373 
374 static void maybeParseOptions(lto_code_gen_t cg) {
375   if (!parsedOptions) {
376     unwrap(cg)->parseCodeGenDebugOptions();
377     lto_add_attrs(cg);
378     parsedOptions = true;
379   }
380 }
381 
382 bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) {
383   maybeParseOptions(cg);
384   return !unwrap(cg)->writeMergedModules(path);
385 }
386 
387 const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) {
388   maybeParseOptions(cg);
389   LibLTOCodeGenerator *CG = unwrap(cg);
390   CG->NativeObjectFile =
391       CG->compile(DisableVerify, DisableInline, DisableGVNLoadPRE,
392                   DisableLTOVectorization);
393   if (!CG->NativeObjectFile)
394     return nullptr;
395   *length = CG->NativeObjectFile->getBufferSize();
396   return CG->NativeObjectFile->getBufferStart();
397 }
398 
399 bool lto_codegen_optimize(lto_code_gen_t cg) {
400   maybeParseOptions(cg);
401   return !unwrap(cg)->optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
402                                DisableLTOVectorization);
403 }
404 
405 const void *lto_codegen_compile_optimized(lto_code_gen_t cg, size_t *length) {
406   maybeParseOptions(cg);
407   LibLTOCodeGenerator *CG = unwrap(cg);
408   CG->NativeObjectFile = CG->compileOptimized();
409   if (!CG->NativeObjectFile)
410     return nullptr;
411   *length = CG->NativeObjectFile->getBufferSize();
412   return CG->NativeObjectFile->getBufferStart();
413 }
414 
415 bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) {
416   maybeParseOptions(cg);
417   return !unwrap(cg)->compile_to_file(
418       name, DisableVerify, DisableInline, DisableGVNLoadPRE,
419       DisableLTOVectorization);
420 }
421 
422 void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) {
423   unwrap(cg)->setCodeGenDebugOptions(opt);
424 }
425 
426 unsigned int lto_api_version() { return LTO_API_VERSION; }
427 
428 void lto_codegen_set_should_internalize(lto_code_gen_t cg,
429                                         bool ShouldInternalize) {
430   unwrap(cg)->setShouldInternalize(ShouldInternalize);
431 }
432 
433 void lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
434                                            lto_bool_t ShouldEmbedUselists) {
435   unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists);
436 }
437