lto.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
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-c/Core.h"
17#include "llvm-c/Target.h"
18#include "llvm/CodeGen/CommandFlags.h"
19#include "llvm/LTO/LTOCodeGenerator.h"
20#include "llvm/LTO/LTOModule.h"
21
22// extra command-line flags needed for LTOCodeGenerator
23static cl::opt<bool>
24DisableOpt("disable-opt", cl::init(false),
25  cl::desc("Do not run any optimization passes"));
26
27static cl::opt<bool>
28DisableInline("disable-inlining", cl::init(false),
29  cl::desc("Do not run the inliner pass"));
30
31static cl::opt<bool>
32DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
33  cl::desc("Do not run the GVN load PRE pass"));
34
35// Holds most recent error string.
36// *** Not thread safe ***
37static std::string sLastErrorString;
38
39// Holds the initialization state of the LTO module.
40// *** Not thread safe ***
41static bool initialized = false;
42
43// Holds the command-line option parsing state of the LTO module.
44static bool parsedOptions = false;
45
46// Initialize the configured targets if they have not been initialized.
47static void lto_initialize() {
48  if (!initialized) {
49    LLVMInitializeAllTargetInfos();
50    LLVMInitializeAllTargets();
51    LLVMInitializeAllTargetMCs();
52    LLVMInitializeAllAsmParsers();
53    LLVMInitializeAllAsmPrinters();
54    LLVMInitializeAllDisassemblers();
55    initialized = true;
56  }
57}
58
59DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOCodeGenerator, lto_code_gen_t)
60DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t)
61
62// Convert the subtarget features into a string to pass to LTOCodeGenerator.
63static void lto_add_attrs(lto_code_gen_t cg) {
64  LTOCodeGenerator *CG = unwrap(cg);
65  if (MAttrs.size()) {
66    std::string attrs;
67    for (unsigned i = 0; i < MAttrs.size(); ++i) {
68      if (i > 0)
69        attrs.append(",");
70      attrs.append(MAttrs[i]);
71    }
72
73    CG->setAttr(attrs.c_str());
74  }
75}
76
77extern const char* lto_get_version() {
78  return LTOCodeGenerator::getVersionString();
79}
80
81const char* lto_get_error_message() {
82  return sLastErrorString.c_str();
83}
84
85bool lto_module_is_object_file(const char* path) {
86  return LTOModule::isBitcodeFile(path);
87}
88
89bool lto_module_is_object_file_for_target(const char* path,
90                                          const char* target_triplet_prefix) {
91  return LTOModule::isBitcodeFileForTarget(path, target_triplet_prefix);
92}
93
94bool lto_module_is_object_file_in_memory(const void* mem, size_t length) {
95  return LTOModule::isBitcodeFile(mem, length);
96}
97
98bool
99lto_module_is_object_file_in_memory_for_target(const void* mem,
100                                            size_t length,
101                                            const char* target_triplet_prefix) {
102  return LTOModule::isBitcodeFileForTarget(mem, length, target_triplet_prefix);
103}
104
105lto_module_t lto_module_create(const char* path) {
106  lto_initialize();
107  llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
108  return wrap(LTOModule::makeLTOModule(path, Options, sLastErrorString));
109}
110
111lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {
112  lto_initialize();
113  llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
114  return wrap(
115      LTOModule::makeLTOModule(fd, path, size, Options, sLastErrorString));
116}
117
118lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
119                                                 size_t file_size,
120                                                 size_t map_size,
121                                                 off_t offset) {
122  lto_initialize();
123  llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
124  return wrap(LTOModule::makeLTOModule(fd, path, map_size, offset, Options,
125                                       sLastErrorString));
126}
127
128lto_module_t lto_module_create_from_memory(const void* mem, size_t length) {
129  lto_initialize();
130  llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
131  return wrap(LTOModule::makeLTOModule(mem, length, Options, sLastErrorString));
132}
133
134lto_module_t lto_module_create_from_memory_with_path(const void* mem,
135                                                     size_t length,
136                                                     const char *path) {
137  lto_initialize();
138  llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
139  return wrap(
140      LTOModule::makeLTOModule(mem, length, Options, sLastErrorString, path));
141}
142
143void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); }
144
145const char* lto_module_get_target_triple(lto_module_t mod) {
146  return unwrap(mod)->getTargetTriple();
147}
148
149void lto_module_set_target_triple(lto_module_t mod, const char *triple) {
150  return unwrap(mod)->setTargetTriple(triple);
151}
152
153unsigned int lto_module_get_num_symbols(lto_module_t mod) {
154  return unwrap(mod)->getSymbolCount();
155}
156
157const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) {
158  return unwrap(mod)->getSymbolName(index);
159}
160
161lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,
162                                                      unsigned int index) {
163  return unwrap(mod)->getSymbolAttributes(index);
164}
165
166unsigned int lto_module_get_num_deplibs(lto_module_t mod) {
167  return unwrap(mod)->getDependentLibraryCount();
168}
169
170const char* lto_module_get_deplib(lto_module_t mod, unsigned int index) {
171  return unwrap(mod)->getDependentLibrary(index);
172}
173
174unsigned int lto_module_get_num_linkeropts(lto_module_t mod) {
175  return unwrap(mod)->getLinkerOptCount();
176}
177
178const char* lto_module_get_linkeropt(lto_module_t mod, unsigned int index) {
179  return unwrap(mod)->getLinkerOpt(index);
180}
181
182void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
183                                        lto_diagnostic_handler_t diag_handler,
184                                        void *ctxt) {
185  unwrap(cg)->setDiagnosticHandler(diag_handler, ctxt);
186}
187
188lto_code_gen_t lto_codegen_create(void) {
189  lto_initialize();
190
191  TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
192
193  LTOCodeGenerator *CodeGen = new LTOCodeGenerator();
194  if (CodeGen)
195    CodeGen->setTargetOptions(Options);
196  return wrap(CodeGen);
197}
198
199void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); }
200
201bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) {
202  return !unwrap(cg)->addModule(unwrap(mod), sLastErrorString);
203}
204
205bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) {
206  unwrap(cg)->setDebugInfo(debug);
207  return false;
208}
209
210bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) {
211  unwrap(cg)->setCodePICModel(model);
212  return false;
213}
214
215void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) {
216  return unwrap(cg)->setCpu(cpu);
217}
218
219void lto_codegen_set_attr(lto_code_gen_t cg, const char *attr) {
220  return unwrap(cg)->setAttr(attr);
221}
222
223void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) {
224  // In here only for backwards compatibility. We use MC now.
225}
226
227void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
228                                    int nargs) {
229  // In here only for backwards compatibility. We use MC now.
230}
231
232void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg,
233                                          const char *symbol) {
234  unwrap(cg)->addMustPreserveSymbol(symbol);
235}
236
237bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) {
238  if (!parsedOptions) {
239    unwrap(cg)->parseCodeGenDebugOptions();
240    lto_add_attrs(cg);
241    parsedOptions = true;
242  }
243  return !unwrap(cg)->writeMergedModules(path, sLastErrorString);
244}
245
246const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) {
247  if (!parsedOptions) {
248    unwrap(cg)->parseCodeGenDebugOptions();
249    lto_add_attrs(cg);
250    parsedOptions = true;
251  }
252  return unwrap(cg)->compile(length, DisableOpt, DisableInline,
253                             DisableGVNLoadPRE, sLastErrorString);
254}
255
256bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) {
257  if (!parsedOptions) {
258    unwrap(cg)->parseCodeGenDebugOptions();
259    lto_add_attrs(cg);
260    parsedOptions = true;
261  }
262  return !unwrap(cg)->compile_to_file(name, DisableOpt, DisableInline,
263                                      DisableGVNLoadPRE, sLastErrorString);
264}
265
266void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) {
267  unwrap(cg)->setCodeGenDebugOptions(opt);
268}
269