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