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/CodeGen/CommandFlags.h"
17#include "llvm/LTO/LTOCodeGenerator.h"
18#include "llvm/LTO/LTOModule.h"
19#include "llvm/Support/MemoryBuffer.h"
20#include "llvm/Support/TargetSelect.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    InitializeAllTargetInfos();
50    InitializeAllTargets();
51    InitializeAllTargetMCs();
52    InitializeAllAsmParsers();
53    InitializeAllAsmPrinters();
54    InitializeAllDisassemblers();
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  ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(path);
92  if (!Buffer)
93    return false;
94  return LTOModule::isBitcodeForTarget(Buffer->get(), target_triplet_prefix);
95}
96
97bool lto_module_is_object_file_in_memory(const void* mem, size_t length) {
98  return LTOModule::isBitcodeFile(mem, length);
99}
100
101bool
102lto_module_is_object_file_in_memory_for_target(const void* mem,
103                                            size_t length,
104                                            const char* target_triplet_prefix) {
105  std::unique_ptr<MemoryBuffer> buffer(LTOModule::makeBuffer(mem, length));
106  if (!buffer)
107    return false;
108  return LTOModule::isBitcodeForTarget(buffer.get(), target_triplet_prefix);
109}
110
111lto_module_t lto_module_create(const char* path) {
112  lto_initialize();
113  llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
114  return wrap(LTOModule::createFromFile(path, Options, sLastErrorString));
115}
116
117lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {
118  lto_initialize();
119  llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
120  return wrap(
121      LTOModule::createFromOpenFile(fd, path, size, Options, sLastErrorString));
122}
123
124lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
125                                                 size_t file_size,
126                                                 size_t map_size,
127                                                 off_t offset) {
128  lto_initialize();
129  llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
130  return wrap(LTOModule::createFromOpenFileSlice(fd, path, map_size, offset,
131                                                 Options, sLastErrorString));
132}
133
134lto_module_t lto_module_create_from_memory(const void* mem, size_t length) {
135  lto_initialize();
136  llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
137  return wrap(LTOModule::createFromBuffer(mem, length, Options, sLastErrorString));
138}
139
140lto_module_t lto_module_create_from_memory_with_path(const void* mem,
141                                                     size_t length,
142                                                     const char *path) {
143  lto_initialize();
144  llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
145  return wrap(
146      LTOModule::createFromBuffer(mem, length, Options, sLastErrorString, path));
147}
148
149void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); }
150
151const char* lto_module_get_target_triple(lto_module_t mod) {
152  return unwrap(mod)->getTargetTriple().c_str();
153}
154
155void lto_module_set_target_triple(lto_module_t mod, const char *triple) {
156  return unwrap(mod)->setTargetTriple(triple);
157}
158
159unsigned int lto_module_get_num_symbols(lto_module_t mod) {
160  return unwrap(mod)->getSymbolCount();
161}
162
163const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) {
164  return unwrap(mod)->getSymbolName(index);
165}
166
167lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,
168                                                      unsigned int index) {
169  return unwrap(mod)->getSymbolAttributes(index);
170}
171
172unsigned int lto_module_get_num_deplibs(lto_module_t mod) {
173  return unwrap(mod)->getDependentLibraryCount();
174}
175
176const char* lto_module_get_deplib(lto_module_t mod, unsigned int index) {
177  return unwrap(mod)->getDependentLibrary(index);
178}
179
180unsigned int lto_module_get_num_linkeropts(lto_module_t mod) {
181  return unwrap(mod)->getLinkerOptCount();
182}
183
184const char* lto_module_get_linkeropt(lto_module_t mod, unsigned int index) {
185  return unwrap(mod)->getLinkerOpt(index);
186}
187
188void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
189                                        lto_diagnostic_handler_t diag_handler,
190                                        void *ctxt) {
191  unwrap(cg)->setDiagnosticHandler(diag_handler, ctxt);
192}
193
194lto_code_gen_t lto_codegen_create(void) {
195  lto_initialize();
196
197  TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
198
199  LTOCodeGenerator *CodeGen = new LTOCodeGenerator();
200  if (CodeGen)
201    CodeGen->setTargetOptions(Options);
202  return wrap(CodeGen);
203}
204
205void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); }
206
207bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) {
208  return !unwrap(cg)->addModule(unwrap(mod), sLastErrorString);
209}
210
211bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) {
212  unwrap(cg)->setDebugInfo(debug);
213  return false;
214}
215
216bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) {
217  unwrap(cg)->setCodePICModel(model);
218  return false;
219}
220
221void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) {
222  return unwrap(cg)->setCpu(cpu);
223}
224
225void lto_codegen_set_attr(lto_code_gen_t cg, const char *attr) {
226  return unwrap(cg)->setAttr(attr);
227}
228
229void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) {
230  // In here only for backwards compatibility. We use MC now.
231}
232
233void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
234                                    int nargs) {
235  // In here only for backwards compatibility. We use MC now.
236}
237
238void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg,
239                                          const char *symbol) {
240  unwrap(cg)->addMustPreserveSymbol(symbol);
241}
242
243bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) {
244  if (!parsedOptions) {
245    unwrap(cg)->parseCodeGenDebugOptions();
246    lto_add_attrs(cg);
247    parsedOptions = true;
248  }
249  return !unwrap(cg)->writeMergedModules(path, sLastErrorString);
250}
251
252const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) {
253  if (!parsedOptions) {
254    unwrap(cg)->parseCodeGenDebugOptions();
255    lto_add_attrs(cg);
256    parsedOptions = true;
257  }
258  return unwrap(cg)->compile(length, DisableOpt, DisableInline,
259                             DisableGVNLoadPRE, sLastErrorString);
260}
261
262bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) {
263  if (!parsedOptions) {
264    unwrap(cg)->parseCodeGenDebugOptions();
265    lto_add_attrs(cg);
266    parsedOptions = true;
267  }
268  return !unwrap(cg)->compile_to_file(name, DisableOpt, DisableInline,
269                                      DisableGVNLoadPRE, sLastErrorString);
270}
271
272void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) {
273  unwrap(cg)->setCodeGenDebugOptions(opt);
274}
275