blob: 0a3ba98957e7c5dde91294f4265e7011f545063e [file] [log] [blame]
Nick Kledzik77595fc2008-02-26 20:26:43 +00001//===-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.
Bill Wendling8fd3fcd2012-03-30 10:29:38 +00007//
Nick Kledzik77595fc2008-02-26 20:26:43 +00008//===----------------------------------------------------------------------===//
9//
Bill Wendling8fd3fcd2012-03-30 10:29:38 +000010// This file implements the Link Time Optimization library. This library is
Nick Kledzik77595fc2008-02-26 20:26:43 +000011// intended to be used by linker to optimize code at link time.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm-c/lto.h"
Benjamin Kramerd59c5f92015-03-01 21:28:53 +000016#include "llvm/ADT/STLExtras.h"
Teresa Johnsona5479192016-11-11 05:34:58 +000017#include "llvm/Bitcode/BitcodeReader.h"
David Blaikie461bf522018-04-11 18:49:37 +000018#include "llvm/CodeGen/CommandFlags.inc"
Rafael Espindola608d7b42015-12-04 16:14:31 +000019#include "llvm/IR/DiagnosticInfo.h"
20#include "llvm/IR/DiagnosticPrinter.h"
Duncan P. N. Exon Smithacc1d122014-12-19 07:19:50 +000021#include "llvm/IR/LLVMContext.h"
Peter Collingbourneef2acb52016-07-14 21:21:16 +000022#include "llvm/LTO/legacy/LTOCodeGenerator.h"
23#include "llvm/LTO/legacy/LTOModule.h"
24#include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
Alp Toker2255dc72014-07-04 00:58:41 +000025#include "llvm/Support/MemoryBuffer.h"
Michael J. Spencerab9c1612015-01-29 17:20:41 +000026#include "llvm/Support/Signals.h"
Rafael Espindola01ccb9c2014-06-19 19:11:22 +000027#include "llvm/Support/TargetSelect.h"
Reid Klecknercb176fd2016-01-29 00:03:34 +000028#include "llvm/Support/raw_ostream.h"
Nick Kledzik77595fc2008-02-26 20:26:43 +000029
Rafael Espindolac13c9e52013-09-30 16:39:19 +000030// extra command-line flags needed for LTOCodeGenerator
Peter Collingbourne416d8ec2015-03-19 22:01:00 +000031static cl::opt<char>
32OptLevel("O",
33 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
34 "(default = '-O2')"),
35 cl::Prefix,
36 cl::ZeroOrMore,
37 cl::init('2'));
Rafael Espindolac13c9e52013-09-30 16:39:19 +000038
39static cl::opt<bool>
40DisableInline("disable-inlining", cl::init(false),
41 cl::desc("Do not run the inliner pass"));
42
43static cl::opt<bool>
44DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
45 cl::desc("Do not run the GVN load PRE pass"));
Nick Kledzik77595fc2008-02-26 20:26:43 +000046
Mehdi Aminie4c5b692017-03-28 18:55:44 +000047static cl::opt<bool> DisableLTOVectorization(
48 "disable-lto-vectorization", cl::init(false),
49 cl::desc("Do not run loop or slp vectorization during LTO"));
50
51static cl::opt<bool> EnableFreestanding(
52 "lto-freestanding", cl::init(false),
53 cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
Arnold Schwaighoferb26fb772014-10-26 21:50:58 +000054
Duncan P. N. Exon Smith5e60a682015-09-15 23:05:59 +000055#ifdef NDEBUG
56static bool VerifyByDefault = false;
57#else
58static bool VerifyByDefault = true;
59#endif
60
61static cl::opt<bool> DisableVerify(
62 "disable-llvm-verifier", cl::init(!VerifyByDefault),
63 cl::desc("Don't run the LLVM verifier during the optimization pipeline"));
64
Bill Wendling8fd3fcd2012-03-30 10:29:38 +000065// Holds most recent error string.
66// *** Not thread safe ***
Nick Kledzik77595fc2008-02-26 20:26:43 +000067static std::string sLastErrorString;
68
Peter Collingbournecc488542013-09-24 23:52:22 +000069// Holds the initialization state of the LTO module.
70// *** Not thread safe ***
71static bool initialized = false;
72
Rafael Espindola0e95b3a2013-10-02 14:36:23 +000073// Holds the command-line option parsing state of the LTO module.
74static bool parsedOptions = false;
75
Rafael Espindola608d7b42015-12-04 16:14:31 +000076static LLVMContext *LTOContext = nullptr;
77
Vivek Pandya18b4c372017-09-15 20:10:09 +000078struct LTOToolDiagnosticHandler : public DiagnosticHandler {
79 bool handleDiagnostics(const DiagnosticInfo &DI) override {
80 if (DI.getSeverity() != DS_Error) {
81 DiagnosticPrinterRawOStream DP(errs());
82 DI.print(DP);
83 errs() << '\n';
84 return true;
85 }
86 sLastErrorString = "";
87 {
88 raw_string_ostream Stream(sLastErrorString);
89 DiagnosticPrinterRawOStream DP(Stream);
90 DI.print(DP);
91 }
92 return true;
Rafael Espindola608d7b42015-12-04 16:14:31 +000093 }
Vivek Pandya18b4c372017-09-15 20:10:09 +000094};
Rafael Espindola608d7b42015-12-04 16:14:31 +000095
Peter Collingbournecc488542013-09-24 23:52:22 +000096// Initialize the configured targets if they have not been initialized.
97static void lto_initialize() {
98 if (!initialized) {
Nico Weber63033d32018-04-29 00:45:03 +000099#ifdef _WIN32
Michael J. Spencerab9c1612015-01-29 17:20:41 +0000100 // Dialog box on crash disabling doesn't work across DLL boundaries, so do
101 // it here.
102 llvm::sys::DisableSystemDialogsOnCrash();
103#endif
104
Rafael Espindola01ccb9c2014-06-19 19:11:22 +0000105 InitializeAllTargetInfos();
106 InitializeAllTargets();
107 InitializeAllTargetMCs();
108 InitializeAllAsmParsers();
109 InitializeAllAsmPrinters();
110 InitializeAllDisassemblers();
Rafael Espindola608d7b42015-12-04 16:14:31 +0000111
Mehdi Amini8be77072016-04-14 21:59:01 +0000112 static LLVMContext Context;
113 LTOContext = &Context;
Vivek Pandya18b4c372017-09-15 20:10:09 +0000114 LTOContext->setDiagnosticHandler(
115 llvm::make_unique<LTOToolDiagnosticHandler>(), true);
Peter Collingbournecc488542013-09-24 23:52:22 +0000116 initialized = true;
117 }
118}
119
Peter Collingbourne3fcf5a92015-06-01 20:08:30 +0000120namespace {
121
Yunzhong Gao8de34ad2015-11-11 19:59:08 +0000122static void handleLibLTODiagnostic(lto_codegen_diagnostic_severity_t Severity,
123 const char *Msg, void *) {
124 sLastErrorString = Msg;
Yunzhong Gao8de34ad2015-11-11 19:59:08 +0000125}
126
Peter Collingbourne3fcf5a92015-06-01 20:08:30 +0000127// This derived class owns the native object file. This helps implement the
128// libLTO API semantics, which require that the code generator owns the object
129// file.
130struct LibLTOCodeGenerator : LTOCodeGenerator {
Duncan P. N. Exon Smith9c9a1012016-04-16 22:25:36 +0000131 LibLTOCodeGenerator() : LTOCodeGenerator(*LTOContext) { init(); }
Peter Collingbourne3fcf5a92015-06-01 20:08:30 +0000132 LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context)
Rafael Espindolac6a202e2015-12-04 02:42:28 +0000133 : LTOCodeGenerator(*Context), OwnedContext(std::move(Context)) {
Duncan P. N. Exon Smith9c9a1012016-04-16 22:25:36 +0000134 init();
135 }
Peter Collingbourne3fcf5a92015-06-01 20:08:30 +0000136
Steven Wu1208ef52015-12-09 03:37:51 +0000137 // Reset the module first in case MergedModule is created in OwnedContext.
138 // Module must be destructed before its context gets destructed.
139 ~LibLTOCodeGenerator() { resetMergedModule(); }
140
Duncan P. N. Exon Smith9c9a1012016-04-16 22:25:36 +0000141 void init() { setDiagnosticHandler(handleLibLTODiagnostic, nullptr); }
142
Peter Collingbourne3fcf5a92015-06-01 20:08:30 +0000143 std::unique_ptr<MemoryBuffer> NativeObjectFile;
Rafael Espindolac6a202e2015-12-04 02:42:28 +0000144 std::unique_ptr<LLVMContext> OwnedContext;
Peter Collingbourne3fcf5a92015-06-01 20:08:30 +0000145};
146
147}
148
149DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t)
Mehdi Amini73cf01b2016-03-09 01:37:22 +0000150DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThinLTOCodeGenerator, thinlto_code_gen_t)
Patrik Hagglund862cd002014-05-05 12:24:08 +0000151DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t)
Rafael Espindoladd326082014-05-03 14:59:52 +0000152
Tom Roeder817f5e22014-04-25 21:46:51 +0000153// Convert the subtarget features into a string to pass to LTOCodeGenerator.
154static void lto_add_attrs(lto_code_gen_t cg) {
Rafael Espindoladd326082014-05-03 14:59:52 +0000155 LTOCodeGenerator *CG = unwrap(cg);
Tom Roeder817f5e22014-04-25 21:46:51 +0000156 if (MAttrs.size()) {
157 std::string attrs;
158 for (unsigned i = 0; i < MAttrs.size(); ++i) {
159 if (i > 0)
160 attrs.append(",");
161 attrs.append(MAttrs[i]);
162 }
163
Malcolm Parsons4c127322016-11-02 16:43:50 +0000164 CG->setAttr(attrs);
Tom Roeder817f5e22014-04-25 21:46:51 +0000165 }
Peter Collingbourne416d8ec2015-03-19 22:01:00 +0000166
167 if (OptLevel < '0' || OptLevel > '3')
168 report_fatal_error("Optimization level must be between 0 and 3");
169 CG->setOptLevel(OptLevel - '0');
Mehdi Aminie4c5b692017-03-28 18:55:44 +0000170 CG->setFreestanding(EnableFreestanding);
Tom Roeder817f5e22014-04-25 21:46:51 +0000171}
172
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000173extern const char* lto_get_version() {
174 return LTOCodeGenerator::getVersionString();
Nick Kledzik77595fc2008-02-26 20:26:43 +0000175}
176
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000177const char* lto_get_error_message() {
178 return sLastErrorString.c_str();
Nick Kledzik77595fc2008-02-26 20:26:43 +0000179}
180
Reid Kleckner07d5aef2013-10-24 22:26:04 +0000181bool lto_module_is_object_file(const char* path) {
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000182 return LTOModule::isBitcodeFile(StringRef(path));
Nick Kledzik77595fc2008-02-26 20:26:43 +0000183}
184
Reid Kleckner07d5aef2013-10-24 22:26:04 +0000185bool lto_module_is_object_file_for_target(const char* path,
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000186 const char* target_triplet_prefix) {
Rafael Espindola7cba2a92014-07-06 17:43:13 +0000187 ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(path);
188 if (!Buffer)
Alp Toker2255dc72014-07-04 00:58:41 +0000189 return false;
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000190 return LTOModule::isBitcodeForTarget(Buffer->get(),
191 StringRef(target_triplet_prefix));
Nick Kledzik77595fc2008-02-26 20:26:43 +0000192}
193
Mehdi Amini45e997d2016-07-11 23:10:18 +0000194bool lto_module_has_objc_category(const void *mem, size_t length) {
195 std::unique_ptr<MemoryBuffer> Buffer(LTOModule::makeBuffer(mem, length));
196 if (!Buffer)
197 return false;
198 LLVMContext Ctx;
Peter Collingbourne9b252f02016-11-11 19:50:24 +0000199 ErrorOr<bool> Result = expectedToErrorOrAndEmitErrors(
200 Ctx, llvm::isBitcodeContainingObjCCategory(*Buffer));
201 return Result && *Result;
Mehdi Amini45e997d2016-07-11 23:10:18 +0000202}
203
Reid Kleckner07d5aef2013-10-24 22:26:04 +0000204bool lto_module_is_object_file_in_memory(const void* mem, size_t length) {
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000205 return LTOModule::isBitcodeFile(mem, length);
Nick Kledzik77595fc2008-02-26 20:26:43 +0000206}
207
Reid Kleckner07d5aef2013-10-24 22:26:04 +0000208bool
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000209lto_module_is_object_file_in_memory_for_target(const void* mem,
210 size_t length,
211 const char* target_triplet_prefix) {
Alp Toker2255dc72014-07-04 00:58:41 +0000212 std::unique_ptr<MemoryBuffer> buffer(LTOModule::makeBuffer(mem, length));
213 if (!buffer)
214 return false;
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000215 return LTOModule::isBitcodeForTarget(buffer.get(),
216 StringRef(target_triplet_prefix));
Nick Kledzik77595fc2008-02-26 20:26:43 +0000217}
218
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000219lto_module_t lto_module_create(const char* path) {
Peter Collingbournecc488542013-09-24 23:52:22 +0000220 lto_initialize();
Eli Benderskycf421742014-02-19 17:09:35 +0000221 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
Rafael Espindola608d7b42015-12-04 16:14:31 +0000222 ErrorOr<std::unique_ptr<LTOModule>> M =
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000223 LTOModule::createFromFile(*LTOContext, StringRef(path), Options);
Rafael Espindola608d7b42015-12-04 16:14:31 +0000224 if (!M)
225 return nullptr;
226 return wrap(M->release());
Nick Kledzik77595fc2008-02-26 20:26:43 +0000227}
228
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000229lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {
Peter Collingbournecc488542013-09-24 23:52:22 +0000230 lto_initialize();
Eli Benderskycf421742014-02-19 17:09:35 +0000231 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000232 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFile(
233 *LTOContext, fd, StringRef(path), size, Options);
Rafael Espindola608d7b42015-12-04 16:14:31 +0000234 if (!M)
235 return nullptr;
236 return wrap(M->release());
Rafael Espindolab4cc0312011-02-08 22:40:47 +0000237}
Nick Kledzik77595fc2008-02-26 20:26:43 +0000238
Rafael Espindolaf21b1052011-03-17 00:36:11 +0000239lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
240 size_t file_size,
241 size_t map_size,
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000242 off_t offset) {
Peter Collingbournecc488542013-09-24 23:52:22 +0000243 lto_initialize();
Eli Benderskycf421742014-02-19 17:09:35 +0000244 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
Rafael Espindola608d7b42015-12-04 16:14:31 +0000245 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFileSlice(
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000246 *LTOContext, fd, StringRef(path), map_size, offset, Options);
Rafael Espindola608d7b42015-12-04 16:14:31 +0000247 if (!M)
248 return nullptr;
249 return wrap(M->release());
Rafael Espindolaf21b1052011-03-17 00:36:11 +0000250}
251
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000252lto_module_t lto_module_create_from_memory(const void* mem, size_t length) {
Peter Collingbournecc488542013-09-24 23:52:22 +0000253 lto_initialize();
Eli Benderskycf421742014-02-19 17:09:35 +0000254 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
Rafael Espindola608d7b42015-12-04 16:14:31 +0000255 ErrorOr<std::unique_ptr<LTOModule>> M =
256 LTOModule::createFromBuffer(*LTOContext, mem, length, Options);
257 if (!M)
258 return nullptr;
259 return wrap(M->release());
Nick Kledzik77595fc2008-02-26 20:26:43 +0000260}
261
Manman Renf3fc8c92014-02-10 23:26:14 +0000262lto_module_t lto_module_create_from_memory_with_path(const void* mem,
263 size_t length,
264 const char *path) {
265 lto_initialize();
Eli Benderskycf421742014-02-19 17:09:35 +0000266 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000267 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer(
268 *LTOContext, mem, length, Options, StringRef(path));
Rafael Espindola608d7b42015-12-04 16:14:31 +0000269 if (!M)
270 return nullptr;
271 return wrap(M->release());
Manman Renf3fc8c92014-02-10 23:26:14 +0000272}
273
Duncan P. N. Exon Smith4f897092014-11-11 23:19:23 +0000274lto_module_t lto_module_create_in_local_context(const void *mem, size_t length,
275 const char *path) {
276 lto_initialize();
277 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
Petr Pavlu3a3e8dd2016-03-01 13:13:49 +0000278
Simon Pilgrim428e6932017-03-30 12:59:53 +0000279 // Create a local context. Ownership will be transferred to LTOModule.
Petr Pavlu3a3e8dd2016-03-01 13:13:49 +0000280 std::unique_ptr<LLVMContext> Context = llvm::make_unique<LLVMContext>();
Vivek Pandya18b4c372017-09-15 20:10:09 +0000281 Context->setDiagnosticHandler(llvm::make_unique<LTOToolDiagnosticHandler>(),
282 true);
Petr Pavlu3a3e8dd2016-03-01 13:13:49 +0000283
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000284 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createInLocalContext(
285 std::move(Context), mem, length, Options, StringRef(path));
Rafael Espindola608d7b42015-12-04 16:14:31 +0000286 if (!M)
287 return nullptr;
288 return wrap(M->release());
Duncan P. N. Exon Smith4f897092014-11-11 23:19:23 +0000289}
290
291lto_module_t lto_module_create_in_codegen_context(const void *mem,
292 size_t length,
293 const char *path,
294 lto_code_gen_t cg) {
295 lto_initialize();
296 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
Petr Pavlu3a3e8dd2016-03-01 13:13:49 +0000297 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer(
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000298 unwrap(cg)->getContext(), mem, length, Options, StringRef(path));
Rafael Espindola608d7b42015-12-04 16:14:31 +0000299 return wrap(M->release());
Duncan P. N. Exon Smith4f897092014-11-11 23:19:23 +0000300}
301
Rafael Espindoladd326082014-05-03 14:59:52 +0000302void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); }
Nick Kledzik77595fc2008-02-26 20:26:43 +0000303
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000304const char* lto_module_get_target_triple(lto_module_t mod) {
Rafael Espindolaa5939092014-07-04 14:19:41 +0000305 return unwrap(mod)->getTargetTriple().c_str();
Nick Kledzik77595fc2008-02-26 20:26:43 +0000306}
307
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000308void lto_module_set_target_triple(lto_module_t mod, const char *triple) {
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000309 return unwrap(mod)->setTargetTriple(StringRef(triple));
Rafael Espindolacbb170d2010-08-09 21:09:46 +0000310}
311
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000312unsigned int lto_module_get_num_symbols(lto_module_t mod) {
Rafael Espindoladd326082014-05-03 14:59:52 +0000313 return unwrap(mod)->getSymbolCount();
Nick Kledzik77595fc2008-02-26 20:26:43 +0000314}
315
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000316const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) {
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000317 return unwrap(mod)->getSymbolName(index).data();
Nick Kledzik77595fc2008-02-26 20:26:43 +0000318}
319
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000320lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,
321 unsigned int index) {
Rafael Espindoladd326082014-05-03 14:59:52 +0000322 return unwrap(mod)->getSymbolAttributes(index);
Nick Kledzik77595fc2008-02-26 20:26:43 +0000323}
324
Peter Collingbourne10e9fb12015-06-29 23:09:12 +0000325const char* lto_module_get_linkeropts(lto_module_t mod) {
Mehdi Aminic16b74e2016-10-07 19:05:14 +0000326 return unwrap(mod)->getLinkerOpts().data();
Yunzhong Gaoa747cf12014-01-21 18:31:27 +0000327}
328
Quentin Colombet4c831d92014-01-15 22:04:35 +0000329void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
330 lto_diagnostic_handler_t diag_handler,
331 void *ctxt) {
Rafael Espindoladd326082014-05-03 14:59:52 +0000332 unwrap(cg)->setDiagnosticHandler(diag_handler, ctxt);
Quentin Colombet4c831d92014-01-15 22:04:35 +0000333}
334
Duncan P. N. Exon Smithacc1d122014-12-19 07:19:50 +0000335static lto_code_gen_t createCodeGen(bool InLocalContext) {
Peter Collingbournecc488542013-09-24 23:52:22 +0000336 lto_initialize();
Rafael Espindolac13c9e52013-09-30 16:39:19 +0000337
Eli Benderskycf421742014-02-19 17:09:35 +0000338 TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
Rafael Espindolac13c9e52013-09-30 16:39:19 +0000339
Peter Collingbourne3fcf5a92015-06-01 20:08:30 +0000340 LibLTOCodeGenerator *CodeGen =
341 InLocalContext ? new LibLTOCodeGenerator(make_unique<LLVMContext>())
342 : new LibLTOCodeGenerator();
343 CodeGen->setTargetOptions(Options);
Rafael Espindoladd326082014-05-03 14:59:52 +0000344 return wrap(CodeGen);
Nick Kledzik77595fc2008-02-26 20:26:43 +0000345}
346
Duncan P. N. Exon Smithacc1d122014-12-19 07:19:50 +0000347lto_code_gen_t lto_codegen_create(void) {
348 return createCodeGen(/* InLocalContext */ false);
349}
350
351lto_code_gen_t lto_codegen_create_in_local_context(void) {
352 return createCodeGen(/* InLocalContext */ true);
353}
354
Rafael Espindoladd326082014-05-03 14:59:52 +0000355void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); }
Nick Kledzik77595fc2008-02-26 20:26:43 +0000356
Reid Kleckner07d5aef2013-10-24 22:26:04 +0000357bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) {
Rafael Espindola72478e52014-10-25 04:06:10 +0000358 return !unwrap(cg)->addModule(unwrap(mod));
Nick Kledzik77595fc2008-02-26 20:26:43 +0000359}
360
Manman Renbd26e6a2015-02-24 00:45:56 +0000361void lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod) {
Peter Collingbourne8c1602d2015-08-24 22:22:53 +0000362 unwrap(cg)->setModule(std::unique_ptr<LTOModule>(unwrap(mod)));
Manman Renbd26e6a2015-02-24 00:45:56 +0000363}
364
Reid Kleckner07d5aef2013-10-24 22:26:04 +0000365bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) {
Rafael Espindoladd326082014-05-03 14:59:52 +0000366 unwrap(cg)->setDebugInfo(debug);
Shuxin Yang235089b2013-08-07 05:19:23 +0000367 return false;
Nick Kledzik77595fc2008-02-26 20:26:43 +0000368}
369
Reid Kleckner07d5aef2013-10-24 22:26:04 +0000370bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) {
Peter Collingbourneaa7ad072015-08-21 22:57:17 +0000371 switch (model) {
372 case LTO_CODEGEN_PIC_MODEL_STATIC:
373 unwrap(cg)->setCodePICModel(Reloc::Static);
374 return false;
375 case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
376 unwrap(cg)->setCodePICModel(Reloc::PIC_);
377 return false;
378 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
379 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
380 return false;
381 case LTO_CODEGEN_PIC_MODEL_DEFAULT:
Rafael Espindolaac8db592016-05-18 22:04:49 +0000382 unwrap(cg)->setCodePICModel(None);
Peter Collingbourneaa7ad072015-08-21 22:57:17 +0000383 return false;
384 }
385 sLastErrorString = "Unknown PIC model";
386 return true;
Nick Kledzik77595fc2008-02-26 20:26:43 +0000387}
388
Bill Wendling168f1422012-03-31 10:44:20 +0000389void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) {
Rafael Espindoladd326082014-05-03 14:59:52 +0000390 return unwrap(cg)->setCpu(cpu);
Rafael Espindola2d643ef2010-08-11 00:15:13 +0000391}
392
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000393void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) {
Rafael Espindolae9efea12011-02-24 21:04:06 +0000394 // In here only for backwards compatibility. We use MC now.
Nick Kledzikcbad5862009-06-04 00:28:45 +0000395}
396
Bill Wendling168f1422012-03-31 10:44:20 +0000397void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000398 int nargs) {
Rafael Espindolae9efea12011-02-24 21:04:06 +0000399 // In here only for backwards compatibility. We use MC now.
Rafael Espindola98197e52010-08-10 18:55:09 +0000400}
401
Bill Wendling8fd3fcd2012-03-30 10:29:38 +0000402void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg,
Bill Wendling168f1422012-03-31 10:44:20 +0000403 const char *symbol) {
Rafael Espindoladd326082014-05-03 14:59:52 +0000404 unwrap(cg)->addMustPreserveSymbol(symbol);
Nick Kledzik77595fc2008-02-26 20:26:43 +0000405}
406
Peter Collingbourne10f24ca2015-03-19 22:12:08 +0000407static void maybeParseOptions(lto_code_gen_t cg) {
Rafael Espindola0e95b3a2013-10-02 14:36:23 +0000408 if (!parsedOptions) {
Rafael Espindoladd326082014-05-03 14:59:52 +0000409 unwrap(cg)->parseCodeGenDebugOptions();
Tom Roeder817f5e22014-04-25 21:46:51 +0000410 lto_add_attrs(cg);
Rafael Espindola0e95b3a2013-10-02 14:36:23 +0000411 parsedOptions = true;
412 }
Peter Collingbourne416d8ec2015-03-19 22:01:00 +0000413}
414
415bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) {
Peter Collingbourne10f24ca2015-03-19 22:12:08 +0000416 maybeParseOptions(cg);
Yunzhong Gao576772b2015-11-17 19:48:12 +0000417 return !unwrap(cg)->writeMergedModules(path);
Nick Kledzik77595fc2008-02-26 20:26:43 +0000418}
419
Bill Wendling168f1422012-03-31 10:44:20 +0000420const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) {
Peter Collingbourne10f24ca2015-03-19 22:12:08 +0000421 maybeParseOptions(cg);
Peter Collingbourne3fcf5a92015-06-01 20:08:30 +0000422 LibLTOCodeGenerator *CG = unwrap(cg);
Duncan P. N. Exon Smith5e60a682015-09-15 23:05:59 +0000423 CG->NativeObjectFile =
424 CG->compile(DisableVerify, DisableInline, DisableGVNLoadPRE,
Yunzhong Gao576772b2015-11-17 19:48:12 +0000425 DisableLTOVectorization);
Peter Collingbourne3fcf5a92015-06-01 20:08:30 +0000426 if (!CG->NativeObjectFile)
427 return nullptr;
428 *length = CG->NativeObjectFile->getBufferSize();
429 return CG->NativeObjectFile->getBufferStart();
Nick Kledzik77595fc2008-02-26 20:26:43 +0000430}
431
Manman Ren69e4dd12015-02-03 18:39:15 +0000432bool lto_codegen_optimize(lto_code_gen_t cg) {
Peter Collingbourne10f24ca2015-03-19 22:12:08 +0000433 maybeParseOptions(cg);
Duncan P. N. Exon Smith5e60a682015-09-15 23:05:59 +0000434 return !unwrap(cg)->optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
Yunzhong Gao576772b2015-11-17 19:48:12 +0000435 DisableLTOVectorization);
Manman Ren69e4dd12015-02-03 18:39:15 +0000436}
437
438const void *lto_codegen_compile_optimized(lto_code_gen_t cg, size_t *length) {
Peter Collingbourne10f24ca2015-03-19 22:12:08 +0000439 maybeParseOptions(cg);
Peter Collingbourne3fcf5a92015-06-01 20:08:30 +0000440 LibLTOCodeGenerator *CG = unwrap(cg);
Yunzhong Gao576772b2015-11-17 19:48:12 +0000441 CG->NativeObjectFile = CG->compileOptimized();
Peter Collingbourne3fcf5a92015-06-01 20:08:30 +0000442 if (!CG->NativeObjectFile)
443 return nullptr;
444 *length = CG->NativeObjectFile->getBufferSize();
445 return CG->NativeObjectFile->getBufferStart();
Manman Ren69e4dd12015-02-03 18:39:15 +0000446}
447
Reid Kleckner07d5aef2013-10-24 22:26:04 +0000448bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) {
Peter Collingbourne10f24ca2015-03-19 22:12:08 +0000449 maybeParseOptions(cg);
Arnold Schwaighoferb26fb772014-10-26 21:50:58 +0000450 return !unwrap(cg)->compile_to_file(
Duncan P. N. Exon Smith5e60a682015-09-15 23:05:59 +0000451 name, DisableVerify, DisableInline, DisableGVNLoadPRE,
Yunzhong Gao576772b2015-11-17 19:48:12 +0000452 DisableLTOVectorization);
Rafael Espindola6421a882011-03-22 20:57:13 +0000453}
454
Bill Wendling168f1422012-03-31 10:44:20 +0000455void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) {
Rafael Espindoladd326082014-05-03 14:59:52 +0000456 unwrap(cg)->setCodeGenDebugOptions(opt);
Duncan Sandsd44d4bf2009-07-03 15:38:01 +0000457}
Rafael Espindolaf2e11262015-02-03 19:25:53 +0000458
459unsigned int lto_api_version() { return LTO_API_VERSION; }
Manman Ren44b800f2015-04-17 17:10:09 +0000460
461void lto_codegen_set_should_internalize(lto_code_gen_t cg,
462 bool ShouldInternalize) {
463 unwrap(cg)->setShouldInternalize(ShouldInternalize);
464}
Duncan P. N. Exon Smith0b29dea2015-04-27 23:38:54 +0000465
466void lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
467 lto_bool_t ShouldEmbedUselists) {
468 unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists);
469}
Mehdi Amini73cf01b2016-03-09 01:37:22 +0000470
471// ThinLTO API below
472
Mehdi Amini5e01ef42016-03-09 02:36:09 +0000473thinlto_code_gen_t thinlto_create_codegen(void) {
Mehdi Amini73cf01b2016-03-09 01:37:22 +0000474 lto_initialize();
475 ThinLTOCodeGenerator *CodeGen = new ThinLTOCodeGenerator();
476 CodeGen->setTargetOptions(InitTargetOptionsFromCodeGenFlags());
Mehdi Aminie4c5b692017-03-28 18:55:44 +0000477 CodeGen->setFreestanding(EnableFreestanding);
Mehdi Amini73cf01b2016-03-09 01:37:22 +0000478
Mehdi Aminic54021d2016-12-28 19:37:16 +0000479 if (OptLevel.getNumOccurrences()) {
480 if (OptLevel < '0' || OptLevel > '3')
481 report_fatal_error("Optimization level must be between 0 and 3");
482 CodeGen->setOptLevel(OptLevel - '0');
483 switch (OptLevel) {
484 case '0':
485 CodeGen->setCodeGenOptLevel(CodeGenOpt::None);
486 break;
487 case '1':
488 CodeGen->setCodeGenOptLevel(CodeGenOpt::Less);
489 break;
490 case '2':
491 CodeGen->setCodeGenOptLevel(CodeGenOpt::Default);
492 break;
493 case '3':
494 CodeGen->setCodeGenOptLevel(CodeGenOpt::Aggressive);
495 break;
496 }
497 }
Mehdi Amini73cf01b2016-03-09 01:37:22 +0000498 return wrap(CodeGen);
499}
500
501void thinlto_codegen_dispose(thinlto_code_gen_t cg) { delete unwrap(cg); }
502
503void thinlto_codegen_add_module(thinlto_code_gen_t cg, const char *Identifier,
504 const char *Data, int Length) {
505 unwrap(cg)->addModule(Identifier, StringRef(Data, Length));
506}
507
508void thinlto_codegen_process(thinlto_code_gen_t cg) { unwrap(cg)->run(); }
509
510unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg) {
511 return unwrap(cg)->getProducedBinaries().size();
512}
513LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg,
514 unsigned int index) {
515 assert(index < unwrap(cg)->getProducedBinaries().size() && "Index overflow");
516 auto &MemBuffer = unwrap(cg)->getProducedBinaries()[index];
Mehdi Amini14e46322016-03-19 21:28:18 +0000517 return LTOObjectBuffer{MemBuffer->getBufferStart(),
Mehdi Amini73cf01b2016-03-09 01:37:22 +0000518 MemBuffer->getBufferSize()};
519}
520
Mehdi Aminidbca62e2016-12-14 04:56:42 +0000521unsigned int thinlto_module_get_num_object_files(thinlto_code_gen_t cg) {
522 return unwrap(cg)->getProducedBinaryFiles().size();
523}
524const char *thinlto_module_get_object_file(thinlto_code_gen_t cg,
525 unsigned int index) {
526 assert(index < unwrap(cg)->getProducedBinaryFiles().size() &&
527 "Index overflow");
528 return unwrap(cg)->getProducedBinaryFiles()[index].c_str();
529}
530
Mehdi Amini51f55482016-04-01 06:47:02 +0000531void thinlto_codegen_disable_codegen(thinlto_code_gen_t cg,
532 lto_bool_t disable) {
533 unwrap(cg)->disableCodeGen(disable);
534}
535
536void thinlto_codegen_set_codegen_only(thinlto_code_gen_t cg,
537 lto_bool_t CodeGenOnly) {
538 unwrap(cg)->setCodeGenOnly(CodeGenOnly);
539}
540
Mehdi Amini73cf01b2016-03-09 01:37:22 +0000541void thinlto_debug_options(const char *const *options, int number) {
542 // if options were requested, set them
543 if (number && options) {
544 std::vector<const char *> CodegenArgv(1, "libLTO");
545 for (auto Arg : ArrayRef<const char *>(options, number))
546 CodegenArgv.push_back(Arg);
547 cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data());
548 }
549}
550
Mehdi Amini51f55482016-04-01 06:47:02 +0000551lto_bool_t lto_module_is_thinlto(lto_module_t mod) {
Mehdi Amini73cf01b2016-03-09 01:37:22 +0000552 return unwrap(mod)->isThinLTO();
553}
554
555void thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg,
556 const char *Name, int Length) {
557 unwrap(cg)->preserveSymbol(StringRef(Name, Length));
558}
559
560void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,
561 const char *Name, int Length) {
562 unwrap(cg)->crossReferenceSymbol(StringRef(Name, Length));
563}
564
565void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu) {
566 return unwrap(cg)->setCpu(cpu);
567}
568
569void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
570 const char *cache_dir) {
571 return unwrap(cg)->setCacheDir(cache_dir);
572}
573
574void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
575 int interval) {
576 return unwrap(cg)->setCachePruningInterval(interval);
577}
578
579void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
580 unsigned expiration) {
581 return unwrap(cg)->setCacheEntryExpiration(expiration);
582}
583
584void thinlto_codegen_set_final_cache_size_relative_to_available_space(
585 thinlto_code_gen_t cg, unsigned Percentage) {
586 return unwrap(cg)->setMaxCacheSizeRelativeToAvailableSpace(Percentage);
587}
588
Ekaterina Romanova76899c62018-03-02 03:51:27 +0000589void thinlto_codegen_set_cache_size_bytes(
590 thinlto_code_gen_t cg, unsigned MaxSizeBytes) {
591 return unwrap(cg)->setCacheMaxSizeBytes(MaxSizeBytes);
592}
593
James Hendersonb981f4f2018-09-17 10:21:26 +0000594void thinlto_codegen_set_cache_size_megabytes(
595 thinlto_code_gen_t cg, unsigned MaxSizeMegabytes) {
596 uint64_t MaxSizeBytes = MaxSizeMegabytes;
597 MaxSizeBytes *= 1024 * 1024;
598 return unwrap(cg)->setCacheMaxSizeBytes(MaxSizeBytes);
599}
600
Ekaterina Romanova76899c62018-03-02 03:51:27 +0000601void thinlto_codegen_set_cache_size_files(
602 thinlto_code_gen_t cg, unsigned MaxSizeFiles) {
603 return unwrap(cg)->setCacheMaxSizeFiles(MaxSizeFiles);
604}
605
Mehdi Amini73cf01b2016-03-09 01:37:22 +0000606void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,
607 const char *save_temps_dir) {
608 return unwrap(cg)->setSaveTempsDir(save_temps_dir);
609}
610
Mehdi Aminidbca62e2016-12-14 04:56:42 +0000611void thinlto_set_generated_objects_dir(thinlto_code_gen_t cg,
612 const char *save_temps_dir) {
613 unwrap(cg)->setGeneratedObjectsDirectory(save_temps_dir);
614}
615
Mehdi Amini73cf01b2016-03-09 01:37:22 +0000616lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,
617 lto_codegen_model model) {
618 switch (model) {
619 case LTO_CODEGEN_PIC_MODEL_STATIC:
620 unwrap(cg)->setCodePICModel(Reloc::Static);
621 return false;
622 case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
623 unwrap(cg)->setCodePICModel(Reloc::PIC_);
624 return false;
625 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
626 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
627 return false;
628 case LTO_CODEGEN_PIC_MODEL_DEFAULT:
Rafael Espindolaac8db592016-05-18 22:04:49 +0000629 unwrap(cg)->setCodePICModel(None);
Mehdi Amini73cf01b2016-03-09 01:37:22 +0000630 return false;
631 }
632 sLastErrorString = "Unknown PIC model";
633 return true;
634}