0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1 //===-lto.cpp - LLVM Link Time Optimizer ----------------------------------===//
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
2 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
3 // The LLVM Compiler Infrastructure
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
4 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
5 // This file is distributed under the University of Illinois Open Source
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
6 // License. See LICENSE.TXT for details.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
7 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
8 //===----------------------------------------------------------------------===//
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
9 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
10 // This file implements the Link Time Optimization library. This library is
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
11 // intended to be used by linker to optimize code at link time.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
12 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
13 //===----------------------------------------------------------------------===//
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
14
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
15 #include "llvm-c/lto.h"
|
95
|
16 #include "llvm/ADT/STLExtras.h"
|
120
|
17 #include "llvm/Bitcode/BitcodeReader.h"
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
18 #include "llvm/CodeGen/CommandFlags.h"
|
100
|
19 #include "llvm/IR/DiagnosticInfo.h"
|
|
20 #include "llvm/IR/DiagnosticPrinter.h"
|
83
|
21 #include "llvm/IR/LLVMContext.h"
|
120
|
22 #include "llvm/LTO/legacy/LTOCodeGenerator.h"
|
|
23 #include "llvm/LTO/legacy/LTOModule.h"
|
|
24 #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
|
77
|
25 #include "llvm/Support/MemoryBuffer.h"
|
83
|
26 #include "llvm/Support/Signals.h"
|
77
|
27 #include "llvm/Support/TargetSelect.h"
|
120
|
28 #include "llvm/Support/raw_ostream.h"
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
29
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
30 // extra command-line flags needed for LTOCodeGenerator
|
95
|
31 static cl::opt<char>
|
|
32 OptLevel("O",
|
|
33 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
|
|
34 "(default = '-O2')"),
|
|
35 cl::Prefix,
|
|
36 cl::ZeroOrMore,
|
|
37 cl::init('2'));
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
38
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
39 static cl::opt<bool>
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
40 DisableInline("disable-inlining", cl::init(false),
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
41 cl::desc("Do not run the inliner pass"));
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
42
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
43 static cl::opt<bool>
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
44 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
45 cl::desc("Do not run the GVN load PRE pass"));
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
46
|
83
|
47 static cl::opt<bool>
|
|
48 DisableLTOVectorization("disable-lto-vectorization", cl::init(false),
|
|
49 cl::desc("Do not run loop or slp vectorization during LTO"));
|
|
50
|
95
|
51 #ifdef NDEBUG
|
|
52 static bool VerifyByDefault = false;
|
|
53 #else
|
|
54 static bool VerifyByDefault = true;
|
|
55 #endif
|
|
56
|
|
57 static cl::opt<bool> DisableVerify(
|
|
58 "disable-llvm-verifier", cl::init(!VerifyByDefault),
|
|
59 cl::desc("Don't run the LLVM verifier during the optimization pipeline"));
|
|
60
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
61 // Holds most recent error string.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
62 // *** Not thread safe ***
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
63 static std::string sLastErrorString;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
64
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
65 // Holds the initialization state of the LTO module.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
66 // *** Not thread safe ***
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
67 static bool initialized = false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
68
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
69 // Holds the command-line option parsing state of the LTO module.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
70 static bool parsedOptions = false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
71
|
100
|
72 static LLVMContext *LTOContext = nullptr;
|
|
73
|
|
74 static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
|
|
75 if (DI.getSeverity() != DS_Error) {
|
|
76 DiagnosticPrinterRawOStream DP(errs());
|
|
77 DI.print(DP);
|
|
78 errs() << '\n';
|
|
79 return;
|
|
80 }
|
|
81 sLastErrorString = "";
|
|
82 {
|
|
83 raw_string_ostream Stream(sLastErrorString);
|
|
84 DiagnosticPrinterRawOStream DP(Stream);
|
|
85 DI.print(DP);
|
|
86 }
|
|
87 }
|
|
88
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
89 // Initialize the configured targets if they have not been initialized.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
90 static void lto_initialize() {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
91 if (!initialized) {
|
83
|
92 #ifdef LLVM_ON_WIN32
|
|
93 // Dialog box on crash disabling doesn't work across DLL boundaries, so do
|
|
94 // it here.
|
|
95 llvm::sys::DisableSystemDialogsOnCrash();
|
|
96 #endif
|
|
97
|
77
|
98 InitializeAllTargetInfos();
|
|
99 InitializeAllTargets();
|
|
100 InitializeAllTargetMCs();
|
|
101 InitializeAllAsmParsers();
|
|
102 InitializeAllAsmPrinters();
|
|
103 InitializeAllDisassemblers();
|
100
|
104
|
120
|
105 static LLVMContext Context;
|
|
106 LTOContext = &Context;
|
100
|
107 LTOContext->setDiagnosticHandler(diagnosticHandler, nullptr, true);
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
108 initialized = true;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
109 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
110 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
111
|
95
|
112 namespace {
|
|
113
|
100
|
114 static void handleLibLTODiagnostic(lto_codegen_diagnostic_severity_t Severity,
|
|
115 const char *Msg, void *) {
|
|
116 sLastErrorString = Msg;
|
|
117 }
|
|
118
|
95
|
119 // This derived class owns the native object file. This helps implement the
|
|
120 // libLTO API semantics, which require that the code generator owns the object
|
|
121 // file.
|
|
122 struct LibLTOCodeGenerator : LTOCodeGenerator {
|
120
|
123 LibLTOCodeGenerator() : LTOCodeGenerator(*LTOContext) { init(); }
|
95
|
124 LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context)
|
100
|
125 : LTOCodeGenerator(*Context), OwnedContext(std::move(Context)) {
|
120
|
126 init();
|
|
127 }
|
100
|
128
|
|
129 // Reset the module first in case MergedModule is created in OwnedContext.
|
|
130 // Module must be destructed before its context gets destructed.
|
|
131 ~LibLTOCodeGenerator() { resetMergedModule(); }
|
95
|
132
|
120
|
133 void init() { setDiagnosticHandler(handleLibLTODiagnostic, nullptr); }
|
|
134
|
95
|
135 std::unique_ptr<MemoryBuffer> NativeObjectFile;
|
100
|
136 std::unique_ptr<LLVMContext> OwnedContext;
|
95
|
137 };
|
|
138
|
|
139 }
|
|
140
|
|
141 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t)
|
120
|
142 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThinLTOCodeGenerator, thinlto_code_gen_t)
|
77
|
143 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t)
|
|
144
|
|
145 // Convert the subtarget features into a string to pass to LTOCodeGenerator.
|
|
146 static void lto_add_attrs(lto_code_gen_t cg) {
|
|
147 LTOCodeGenerator *CG = unwrap(cg);
|
|
148 if (MAttrs.size()) {
|
|
149 std::string attrs;
|
|
150 for (unsigned i = 0; i < MAttrs.size(); ++i) {
|
|
151 if (i > 0)
|
|
152 attrs.append(",");
|
|
153 attrs.append(MAttrs[i]);
|
|
154 }
|
|
155
|
120
|
156 CG->setAttr(attrs);
|
77
|
157 }
|
95
|
158
|
|
159 if (OptLevel < '0' || OptLevel > '3')
|
|
160 report_fatal_error("Optimization level must be between 0 and 3");
|
|
161 CG->setOptLevel(OptLevel - '0');
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
162 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
163
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
164 extern const char* lto_get_version() {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
165 return LTOCodeGenerator::getVersionString();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
166 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
167
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
168 const char* lto_get_error_message() {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
169 return sLastErrorString.c_str();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
170 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
171
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
172 bool lto_module_is_object_file(const char* path) {
|
120
|
173 return LTOModule::isBitcodeFile(StringRef(path));
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
174 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
175
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
176 bool lto_module_is_object_file_for_target(const char* path,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
177 const char* target_triplet_prefix) {
|
77
|
178 ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(path);
|
|
179 if (!Buffer)
|
|
180 return false;
|
120
|
181 return LTOModule::isBitcodeForTarget(Buffer->get(),
|
|
182 StringRef(target_triplet_prefix));
|
|
183 }
|
|
184
|
|
185 bool lto_module_has_objc_category(const void *mem, size_t length) {
|
|
186 std::unique_ptr<MemoryBuffer> Buffer(LTOModule::makeBuffer(mem, length));
|
|
187 if (!Buffer)
|
|
188 return false;
|
|
189 LLVMContext Ctx;
|
|
190 ErrorOr<bool> Result = expectedToErrorOrAndEmitErrors(
|
|
191 Ctx, llvm::isBitcodeContainingObjCCategory(*Buffer));
|
|
192 return Result && *Result;
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
193 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
194
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
195 bool lto_module_is_object_file_in_memory(const void* mem, size_t length) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
196 return LTOModule::isBitcodeFile(mem, length);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
197 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
198
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
199 bool
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
200 lto_module_is_object_file_in_memory_for_target(const void* mem,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
201 size_t length,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
202 const char* target_triplet_prefix) {
|
77
|
203 std::unique_ptr<MemoryBuffer> buffer(LTOModule::makeBuffer(mem, length));
|
|
204 if (!buffer)
|
|
205 return false;
|
120
|
206 return LTOModule::isBitcodeForTarget(buffer.get(),
|
|
207 StringRef(target_triplet_prefix));
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
208 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
209
|
77
|
210 lto_module_t lto_module_create(const char* path) {
|
|
211 lto_initialize();
|
|
212 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
|
100
|
213 ErrorOr<std::unique_ptr<LTOModule>> M =
|
120
|
214 LTOModule::createFromFile(*LTOContext, StringRef(path), Options);
|
100
|
215 if (!M)
|
|
216 return nullptr;
|
|
217 return wrap(M->release());
|
77
|
218 }
|
|
219
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
220 lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
221 lto_initialize();
|
77
|
222 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
|
120
|
223 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFile(
|
|
224 *LTOContext, fd, StringRef(path), size, Options);
|
100
|
225 if (!M)
|
|
226 return nullptr;
|
|
227 return wrap(M->release());
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
228 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
229
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
230 lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
231 size_t file_size,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
232 size_t map_size,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
233 off_t offset) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
234 lto_initialize();
|
77
|
235 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
|
100
|
236 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFileSlice(
|
120
|
237 *LTOContext, fd, StringRef(path), map_size, offset, Options);
|
100
|
238 if (!M)
|
|
239 return nullptr;
|
|
240 return wrap(M->release());
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
241 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
242
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
243 lto_module_t lto_module_create_from_memory(const void* mem, size_t length) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
244 lto_initialize();
|
77
|
245 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
|
100
|
246 ErrorOr<std::unique_ptr<LTOModule>> M =
|
|
247 LTOModule::createFromBuffer(*LTOContext, mem, length, Options);
|
|
248 if (!M)
|
|
249 return nullptr;
|
|
250 return wrap(M->release());
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
251 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
252
|
77
|
253 lto_module_t lto_module_create_from_memory_with_path(const void* mem,
|
|
254 size_t length,
|
|
255 const char *path) {
|
|
256 lto_initialize();
|
|
257 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
|
120
|
258 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer(
|
|
259 *LTOContext, mem, length, Options, StringRef(path));
|
100
|
260 if (!M)
|
|
261 return nullptr;
|
|
262 return wrap(M->release());
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
263 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
264
|
83
|
265 lto_module_t lto_module_create_in_local_context(const void *mem, size_t length,
|
|
266 const char *path) {
|
|
267 lto_initialize();
|
|
268 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
|
120
|
269
|
|
270 // Create a local context. Ownership will be transfered to LTOModule.
|
|
271 std::unique_ptr<LLVMContext> Context = llvm::make_unique<LLVMContext>();
|
|
272 Context->setDiagnosticHandler(diagnosticHandler, nullptr, true);
|
|
273
|
|
274 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createInLocalContext(
|
|
275 std::move(Context), mem, length, Options, StringRef(path));
|
100
|
276 if (!M)
|
|
277 return nullptr;
|
|
278 return wrap(M->release());
|
83
|
279 }
|
|
280
|
|
281 lto_module_t lto_module_create_in_codegen_context(const void *mem,
|
|
282 size_t length,
|
|
283 const char *path,
|
|
284 lto_code_gen_t cg) {
|
|
285 lto_initialize();
|
|
286 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
|
120
|
287 ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer(
|
|
288 unwrap(cg)->getContext(), mem, length, Options, StringRef(path));
|
100
|
289 return wrap(M->release());
|
83
|
290 }
|
|
291
|
77
|
292 void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); }
|
|
293
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
294 const char* lto_module_get_target_triple(lto_module_t mod) {
|
77
|
295 return unwrap(mod)->getTargetTriple().c_str();
|
|
296 }
|
|
297
|
|
298 void lto_module_set_target_triple(lto_module_t mod, const char *triple) {
|
120
|
299 return unwrap(mod)->setTargetTriple(StringRef(triple));
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
300 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
301
|
77
|
302 unsigned int lto_module_get_num_symbols(lto_module_t mod) {
|
|
303 return unwrap(mod)->getSymbolCount();
|
|
304 }
|
|
305
|
|
306 const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) {
|
120
|
307 return unwrap(mod)->getSymbolName(index).data();
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
308 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
309
|
77
|
310 lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,
|
|
311 unsigned int index) {
|
|
312 return unwrap(mod)->getSymbolAttributes(index);
|
|
313 }
|
|
314
|
95
|
315 const char* lto_module_get_linkeropts(lto_module_t mod) {
|
120
|
316 return unwrap(mod)->getLinkerOpts().data();
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
317 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
318
|
77
|
319 void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
|
|
320 lto_diagnostic_handler_t diag_handler,
|
|
321 void *ctxt) {
|
|
322 unwrap(cg)->setDiagnosticHandler(diag_handler, ctxt);
|
|
323 }
|
|
324
|
83
|
325 static lto_code_gen_t createCodeGen(bool InLocalContext) {
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
326 lto_initialize();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
327
|
77
|
328 TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
329
|
95
|
330 LibLTOCodeGenerator *CodeGen =
|
|
331 InLocalContext ? new LibLTOCodeGenerator(make_unique<LLVMContext>())
|
|
332 : new LibLTOCodeGenerator();
|
|
333 CodeGen->setTargetOptions(Options);
|
77
|
334 return wrap(CodeGen);
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
335 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
336
|
83
|
337 lto_code_gen_t lto_codegen_create(void) {
|
|
338 return createCodeGen(/* InLocalContext */ false);
|
|
339 }
|
|
340
|
|
341 lto_code_gen_t lto_codegen_create_in_local_context(void) {
|
|
342 return createCodeGen(/* InLocalContext */ true);
|
|
343 }
|
|
344
|
77
|
345 void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); }
|
|
346
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
347 bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) {
|
83
|
348 return !unwrap(cg)->addModule(unwrap(mod));
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
349 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
350
|
95
|
351 void lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod) {
|
|
352 unwrap(cg)->setModule(std::unique_ptr<LTOModule>(unwrap(mod)));
|
|
353 }
|
|
354
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
355 bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) {
|
77
|
356 unwrap(cg)->setDebugInfo(debug);
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
357 return false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
358 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
359
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
360 bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) {
|
95
|
361 switch (model) {
|
|
362 case LTO_CODEGEN_PIC_MODEL_STATIC:
|
|
363 unwrap(cg)->setCodePICModel(Reloc::Static);
|
|
364 return false;
|
|
365 case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
|
|
366 unwrap(cg)->setCodePICModel(Reloc::PIC_);
|
|
367 return false;
|
|
368 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
|
|
369 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
|
|
370 return false;
|
|
371 case LTO_CODEGEN_PIC_MODEL_DEFAULT:
|
120
|
372 unwrap(cg)->setCodePICModel(None);
|
95
|
373 return false;
|
|
374 }
|
|
375 sLastErrorString = "Unknown PIC model";
|
|
376 return true;
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
377 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
378
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
379 void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) {
|
77
|
380 return unwrap(cg)->setCpu(cpu);
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
381 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
382
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
383 void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
384 // In here only for backwards compatibility. We use MC now.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
385 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
386
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
387 void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
388 int nargs) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
389 // In here only for backwards compatibility. We use MC now.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
390 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
391
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
392 void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
393 const char *symbol) {
|
77
|
394 unwrap(cg)->addMustPreserveSymbol(symbol);
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
395 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
396
|
95
|
397 static void maybeParseOptions(lto_code_gen_t cg) {
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
398 if (!parsedOptions) {
|
77
|
399 unwrap(cg)->parseCodeGenDebugOptions();
|
|
400 lto_add_attrs(cg);
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
401 parsedOptions = true;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
402 }
|
95
|
403 }
|
|
404
|
|
405 bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) {
|
|
406 maybeParseOptions(cg);
|
100
|
407 return !unwrap(cg)->writeMergedModules(path);
|
95
|
408 }
|
|
409
|
|
410 const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) {
|
|
411 maybeParseOptions(cg);
|
|
412 LibLTOCodeGenerator *CG = unwrap(cg);
|
|
413 CG->NativeObjectFile =
|
|
414 CG->compile(DisableVerify, DisableInline, DisableGVNLoadPRE,
|
100
|
415 DisableLTOVectorization);
|
95
|
416 if (!CG->NativeObjectFile)
|
|
417 return nullptr;
|
|
418 *length = CG->NativeObjectFile->getBufferSize();
|
|
419 return CG->NativeObjectFile->getBufferStart();
|
83
|
420 }
|
|
421
|
|
422 bool lto_codegen_optimize(lto_code_gen_t cg) {
|
95
|
423 maybeParseOptions(cg);
|
|
424 return !unwrap(cg)->optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
|
100
|
425 DisableLTOVectorization);
|
83
|
426 }
|
|
427
|
|
428 const void *lto_codegen_compile_optimized(lto_code_gen_t cg, size_t *length) {
|
95
|
429 maybeParseOptions(cg);
|
|
430 LibLTOCodeGenerator *CG = unwrap(cg);
|
100
|
431 CG->NativeObjectFile = CG->compileOptimized();
|
95
|
432 if (!CG->NativeObjectFile)
|
|
433 return nullptr;
|
|
434 *length = CG->NativeObjectFile->getBufferSize();
|
|
435 return CG->NativeObjectFile->getBufferStart();
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
436 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
437
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
438 bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) {
|
95
|
439 maybeParseOptions(cg);
|
83
|
440 return !unwrap(cg)->compile_to_file(
|
95
|
441 name, DisableVerify, DisableInline, DisableGVNLoadPRE,
|
100
|
442 DisableLTOVectorization);
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
443 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
444
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
445 void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) {
|
77
|
446 unwrap(cg)->setCodeGenDebugOptions(opt);
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
447 }
|
83
|
448
|
|
449 unsigned int lto_api_version() { return LTO_API_VERSION; }
|
95
|
450
|
|
451 void lto_codegen_set_should_internalize(lto_code_gen_t cg,
|
|
452 bool ShouldInternalize) {
|
|
453 unwrap(cg)->setShouldInternalize(ShouldInternalize);
|
|
454 }
|
|
455
|
|
456 void lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
|
|
457 lto_bool_t ShouldEmbedUselists) {
|
|
458 unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists);
|
|
459 }
|
120
|
460
|
|
461 // ThinLTO API below
|
|
462
|
|
463 thinlto_code_gen_t thinlto_create_codegen(void) {
|
|
464 lto_initialize();
|
|
465 ThinLTOCodeGenerator *CodeGen = new ThinLTOCodeGenerator();
|
|
466 CodeGen->setTargetOptions(InitTargetOptionsFromCodeGenFlags());
|
|
467
|
|
468 return wrap(CodeGen);
|
|
469 }
|
|
470
|
|
471 void thinlto_codegen_dispose(thinlto_code_gen_t cg) { delete unwrap(cg); }
|
|
472
|
|
473 void thinlto_codegen_add_module(thinlto_code_gen_t cg, const char *Identifier,
|
|
474 const char *Data, int Length) {
|
|
475 unwrap(cg)->addModule(Identifier, StringRef(Data, Length));
|
|
476 }
|
|
477
|
|
478 void thinlto_codegen_process(thinlto_code_gen_t cg) { unwrap(cg)->run(); }
|
|
479
|
|
480 unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg) {
|
|
481 return unwrap(cg)->getProducedBinaries().size();
|
|
482 }
|
|
483 LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg,
|
|
484 unsigned int index) {
|
|
485 assert(index < unwrap(cg)->getProducedBinaries().size() && "Index overflow");
|
|
486 auto &MemBuffer = unwrap(cg)->getProducedBinaries()[index];
|
|
487 return LTOObjectBuffer{MemBuffer->getBufferStart(),
|
|
488 MemBuffer->getBufferSize()};
|
|
489 }
|
|
490
|
|
491 void thinlto_codegen_disable_codegen(thinlto_code_gen_t cg,
|
|
492 lto_bool_t disable) {
|
|
493 unwrap(cg)->disableCodeGen(disable);
|
|
494 }
|
|
495
|
|
496 void thinlto_codegen_set_codegen_only(thinlto_code_gen_t cg,
|
|
497 lto_bool_t CodeGenOnly) {
|
|
498 unwrap(cg)->setCodeGenOnly(CodeGenOnly);
|
|
499 }
|
|
500
|
|
501 void thinlto_debug_options(const char *const *options, int number) {
|
|
502 // if options were requested, set them
|
|
503 if (number && options) {
|
|
504 std::vector<const char *> CodegenArgv(1, "libLTO");
|
|
505 for (auto Arg : ArrayRef<const char *>(options, number))
|
|
506 CodegenArgv.push_back(Arg);
|
|
507 cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data());
|
|
508 }
|
|
509 }
|
|
510
|
|
511 lto_bool_t lto_module_is_thinlto(lto_module_t mod) {
|
|
512 return unwrap(mod)->isThinLTO();
|
|
513 }
|
|
514
|
|
515 void thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg,
|
|
516 const char *Name, int Length) {
|
|
517 unwrap(cg)->preserveSymbol(StringRef(Name, Length));
|
|
518 }
|
|
519
|
|
520 void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,
|
|
521 const char *Name, int Length) {
|
|
522 unwrap(cg)->crossReferenceSymbol(StringRef(Name, Length));
|
|
523 }
|
|
524
|
|
525 void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu) {
|
|
526 return unwrap(cg)->setCpu(cpu);
|
|
527 }
|
|
528
|
|
529 void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
|
|
530 const char *cache_dir) {
|
|
531 return unwrap(cg)->setCacheDir(cache_dir);
|
|
532 }
|
|
533
|
|
534 void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
|
|
535 int interval) {
|
|
536 return unwrap(cg)->setCachePruningInterval(interval);
|
|
537 }
|
|
538
|
|
539 void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
|
|
540 unsigned expiration) {
|
|
541 return unwrap(cg)->setCacheEntryExpiration(expiration);
|
|
542 }
|
|
543
|
|
544 void thinlto_codegen_set_final_cache_size_relative_to_available_space(
|
|
545 thinlto_code_gen_t cg, unsigned Percentage) {
|
|
546 return unwrap(cg)->setMaxCacheSizeRelativeToAvailableSpace(Percentage);
|
|
547 }
|
|
548
|
|
549 void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,
|
|
550 const char *save_temps_dir) {
|
|
551 return unwrap(cg)->setSaveTempsDir(save_temps_dir);
|
|
552 }
|
|
553
|
|
554 lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,
|
|
555 lto_codegen_model model) {
|
|
556 switch (model) {
|
|
557 case LTO_CODEGEN_PIC_MODEL_STATIC:
|
|
558 unwrap(cg)->setCodePICModel(Reloc::Static);
|
|
559 return false;
|
|
560 case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
|
|
561 unwrap(cg)->setCodePICModel(Reloc::PIC_);
|
|
562 return false;
|
|
563 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
|
|
564 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
|
|
565 return false;
|
|
566 case LTO_CODEGEN_PIC_MODEL_DEFAULT:
|
|
567 unwrap(cg)->setCodePICModel(None);
|
|
568 return false;
|
|
569 }
|
|
570 sLastErrorString = "Unknown PIC model";
|
|
571 return true;
|
|
572 }
|