]>
Commit | Line | Data |
---|---|---|
970d7e83 | 1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT |
223e47cc LB |
2 | // file at the top-level directory of this distribution and at |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
970d7e83 | 11 | #include "rustllvm.h" |
cc61c64b | 12 | #include "llvm/IR/DebugInfoMetadata.h" |
1a4d82fc JJ |
13 | #include "llvm/IR/DiagnosticInfo.h" |
14 | #include "llvm/IR/DiagnosticPrinter.h" | |
b7449926 | 15 | #include "llvm/IR/GlobalVariable.h" |
5bcae85e | 16 | #include "llvm/IR/Instructions.h" |
32a655c1 SL |
17 | #include "llvm/Object/Archive.h" |
18 | #include "llvm/Object/ObjectFile.h" | |
ea8adc8c | 19 | #include "llvm/Bitcode/BitcodeWriterPass.h" |
0bf4aa26 | 20 | #include "llvm/Support/Signals.h" |
1a4d82fc | 21 | |
1a4d82fc | 22 | #include "llvm/IR/CallSite.h" |
970d7e83 | 23 | |
3b2f2976 XL |
24 | #if LLVM_VERSION_GE(5, 0) |
25 | #include "llvm/ADT/Optional.h" | |
0531ce1d XL |
26 | #else |
27 | #include <cstdlib> | |
3b2f2976 XL |
28 | #endif |
29 | ||
0bf4aa26 XL |
30 | #include <iostream> |
31 | ||
223e47cc LB |
32 | //===----------------------------------------------------------------------=== |
33 | // | |
34 | // This file defines alternate interfaces to core functions that are more | |
35 | // readily callable by Rust's FFI. | |
36 | // | |
37 | //===----------------------------------------------------------------------=== | |
38 | ||
223e47cc LB |
39 | using namespace llvm; |
40 | using namespace llvm::sys; | |
1a4d82fc | 41 | using namespace llvm::object; |
223e47cc | 42 | |
5bcae85e SL |
43 | // LLVMAtomicOrdering is already an enum - don't create another |
44 | // one. | |
32a655c1 | 45 | static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) { |
5bcae85e | 46 | switch (Ordering) { |
32a655c1 SL |
47 | case LLVMAtomicOrderingNotAtomic: |
48 | return AtomicOrdering::NotAtomic; | |
49 | case LLVMAtomicOrderingUnordered: | |
50 | return AtomicOrdering::Unordered; | |
51 | case LLVMAtomicOrderingMonotonic: | |
52 | return AtomicOrdering::Monotonic; | |
53 | case LLVMAtomicOrderingAcquire: | |
54 | return AtomicOrdering::Acquire; | |
55 | case LLVMAtomicOrderingRelease: | |
56 | return AtomicOrdering::Release; | |
57 | case LLVMAtomicOrderingAcquireRelease: | |
58 | return AtomicOrdering::AcquireRelease; | |
59 | case LLVMAtomicOrderingSequentiallyConsistent: | |
60 | return AtomicOrdering::SequentiallyConsistent; | |
5bcae85e SL |
61 | } |
62 | ||
ff7c6d11 | 63 | report_fatal_error("Invalid LLVMAtomicOrdering value!"); |
5bcae85e SL |
64 | } |
65 | ||
abe05a73 | 66 | static LLVM_THREAD_LOCAL char *LastError; |
970d7e83 | 67 | |
0bf4aa26 XL |
68 | // Custom error handler for fatal LLVM errors. |
69 | // | |
70 | // Notably it exits the process with code 101, unlike LLVM's default of 1. | |
71 | static void FatalErrorHandler(void *UserData, | |
72 | const std::string& Reason, | |
73 | bool GenCrashDiag) { | |
74 | // Do the same thing that the default error handler does. | |
75 | std::cerr << "LLVM ERROR: " << Reason << std::endl; | |
76 | ||
77 | // Since this error handler exits the process, we have to run any cleanup that | |
78 | // LLVM would run after handling the error. This might change with an LLVM | |
79 | // upgrade. | |
80 | sys::RunInterruptHandlers(); | |
81 | ||
82 | exit(101); | |
83 | } | |
84 | ||
85 | extern "C" void LLVMRustInstallFatalErrorHandler() { | |
86 | install_fatal_error_handler(FatalErrorHandler); | |
87 | } | |
88 | ||
223e47cc LB |
89 | extern "C" LLVMMemoryBufferRef |
90 | LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { | |
32a655c1 SL |
91 | ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr = |
92 | MemoryBuffer::getFile(Path, -1, false); | |
93 | if (!BufOr) { | |
94 | LLVMRustSetLastError(BufOr.getError().message().c_str()); | |
95 | return nullptr; | |
223e47cc | 96 | } |
32a655c1 | 97 | return wrap(BufOr.get().release()); |
970d7e83 | 98 | } |
223e47cc | 99 | |
1a4d82fc | 100 | extern "C" char *LLVMRustGetLastError(void) { |
32a655c1 SL |
101 | char *Ret = LastError; |
102 | LastError = nullptr; | |
103 | return Ret; | |
223e47cc LB |
104 | } |
105 | ||
ff7c6d11 | 106 | extern "C" void LLVMRustSetLastError(const char *Err) { |
32a655c1 SL |
107 | free((void *)LastError); |
108 | LastError = strdup(Err); | |
223e47cc LB |
109 | } |
110 | ||
ff7c6d11 XL |
111 | extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) { |
112 | auto ctx = new LLVMContext(); | |
113 | ctx->setDiscardValueNames(shouldDiscardNames); | |
114 | return wrap(ctx); | |
115 | } | |
116 | ||
32a655c1 SL |
117 | extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M, |
118 | const char *Triple) { | |
119 | unwrap(M)->setTargetTriple(Triple::normalize(Triple)); | |
223e47cc LB |
120 | } |
121 | ||
223e47cc | 122 | extern "C" void LLVMRustPrintPassTimings() { |
32a655c1 | 123 | raw_fd_ostream OS(2, false); // stderr. |
223e47cc LB |
124 | TimerGroup::printAll(OS); |
125 | } | |
126 | ||
5bcae85e | 127 | extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, |
32a655c1 SL |
128 | const char *Name) { |
129 | return wrap(unwrap(M)->getNamedValue(Name)); | |
9346a6ac AL |
130 | } |
131 | ||
5bcae85e | 132 | extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, |
32a655c1 SL |
133 | const char *Name, |
134 | LLVMTypeRef FunctionTy) { | |
135 | return wrap( | |
136 | unwrap(M)->getOrInsertFunction(Name, unwrap<FunctionType>(FunctionTy))); | |
223e47cc LB |
137 | } |
138 | ||
32a655c1 SL |
139 | extern "C" LLVMValueRef |
140 | LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty) { | |
9346a6ac AL |
141 | return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty))); |
142 | } | |
143 | ||
b7449926 XL |
144 | extern "C" LLVMValueRef |
145 | LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) { | |
146 | return wrap(new GlobalVariable(*unwrap(M), | |
147 | unwrap(Ty), | |
148 | false, | |
149 | GlobalValue::PrivateLinkage, | |
150 | nullptr)); | |
151 | } | |
152 | ||
5bcae85e | 153 | extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) { |
223e47cc LB |
154 | return wrap(Type::getMetadataTy(*unwrap(C))); |
155 | } | |
970d7e83 | 156 | |
32a655c1 SL |
157 | static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { |
158 | switch (Kind) { | |
159 | case AlwaysInline: | |
160 | return Attribute::AlwaysInline; | |
161 | case ByVal: | |
162 | return Attribute::ByVal; | |
163 | case Cold: | |
164 | return Attribute::Cold; | |
165 | case InlineHint: | |
166 | return Attribute::InlineHint; | |
167 | case MinSize: | |
168 | return Attribute::MinSize; | |
169 | case Naked: | |
170 | return Attribute::Naked; | |
171 | case NoAlias: | |
172 | return Attribute::NoAlias; | |
173 | case NoCapture: | |
174 | return Attribute::NoCapture; | |
175 | case NoInline: | |
176 | return Attribute::NoInline; | |
177 | case NonNull: | |
178 | return Attribute::NonNull; | |
179 | case NoRedZone: | |
180 | return Attribute::NoRedZone; | |
181 | case NoReturn: | |
182 | return Attribute::NoReturn; | |
183 | case NoUnwind: | |
184 | return Attribute::NoUnwind; | |
185 | case OptimizeForSize: | |
186 | return Attribute::OptimizeForSize; | |
187 | case ReadOnly: | |
188 | return Attribute::ReadOnly; | |
189 | case SExt: | |
190 | return Attribute::SExt; | |
191 | case StructRet: | |
192 | return Attribute::StructRet; | |
193 | case UWTable: | |
194 | return Attribute::UWTable; | |
195 | case ZExt: | |
196 | return Attribute::ZExt; | |
197 | case InReg: | |
198 | return Attribute::InReg; | |
8bb4bdeb XL |
199 | case SanitizeThread: |
200 | return Attribute::SanitizeThread; | |
201 | case SanitizeAddress: | |
202 | return Attribute::SanitizeAddress; | |
203 | case SanitizeMemory: | |
204 | return Attribute::SanitizeMemory; | |
0bf4aa26 XL |
205 | case NonLazyBind: |
206 | return Attribute::NonLazyBind; | |
476ff2be | 207 | } |
ff7c6d11 | 208 | report_fatal_error("bad AttributeKind"); |
476ff2be SL |
209 | } |
210 | ||
32a655c1 SL |
211 | extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index, |
212 | LLVMRustAttribute RustAttr) { | |
1a4d82fc | 213 | CallSite Call = CallSite(unwrap<Instruction>(Instr)); |
32a655c1 | 214 | Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr)); |
3b2f2976 XL |
215 | #if LLVM_VERSION_GE(5, 0) |
216 | Call.addAttribute(Index, Attr); | |
217 | #else | |
476ff2be | 218 | AttrBuilder B(Attr); |
32a655c1 SL |
219 | Call.setAttributes(Call.getAttributes().addAttributes( |
220 | Call->getContext(), Index, | |
221 | AttributeSet::get(Call->getContext(), Index, B))); | |
3b2f2976 | 222 | #endif |
1a4d82fc JJ |
223 | } |
224 | ||
ff7c6d11 XL |
225 | extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr, |
226 | unsigned Index, | |
227 | uint32_t Bytes) { | |
228 | CallSite Call = CallSite(unwrap<Instruction>(Instr)); | |
229 | AttrBuilder B; | |
230 | B.addAlignmentAttr(Bytes); | |
231 | #if LLVM_VERSION_GE(5, 0) | |
232 | Call.setAttributes(Call.getAttributes().addAttributes( | |
233 | Call->getContext(), Index, B)); | |
234 | #else | |
235 | Call.setAttributes(Call.getAttributes().addAttributes( | |
236 | Call->getContext(), Index, | |
237 | AttributeSet::get(Call->getContext(), Index, B))); | |
238 | #endif | |
239 | } | |
240 | ||
5bcae85e | 241 | extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr, |
32a655c1 SL |
242 | unsigned Index, |
243 | uint64_t Bytes) { | |
1a4d82fc JJ |
244 | CallSite Call = CallSite(unwrap<Instruction>(Instr)); |
245 | AttrBuilder B; | |
32a655c1 | 246 | B.addDereferenceableAttr(Bytes); |
3b2f2976 XL |
247 | #if LLVM_VERSION_GE(5, 0) |
248 | Call.setAttributes(Call.getAttributes().addAttributes( | |
249 | Call->getContext(), Index, B)); | |
250 | #else | |
32a655c1 SL |
251 | Call.setAttributes(Call.getAttributes().addAttributes( |
252 | Call->getContext(), Index, | |
253 | AttributeSet::get(Call->getContext(), Index, B))); | |
3b2f2976 | 254 | #endif |
1a4d82fc | 255 | } |
1a4d82fc | 256 | |
ff7c6d11 XL |
257 | extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr, |
258 | unsigned Index, | |
259 | uint64_t Bytes) { | |
260 | CallSite Call = CallSite(unwrap<Instruction>(Instr)); | |
261 | AttrBuilder B; | |
262 | B.addDereferenceableOrNullAttr(Bytes); | |
263 | #if LLVM_VERSION_GE(5, 0) | |
264 | Call.setAttributes(Call.getAttributes().addAttributes( | |
265 | Call->getContext(), Index, B)); | |
266 | #else | |
267 | Call.setAttributes(Call.getAttributes().addAttributes( | |
268 | Call->getContext(), Index, | |
269 | AttributeSet::get(Call->getContext(), Index, B))); | |
270 | #endif | |
271 | } | |
272 | ||
32a655c1 SL |
273 | extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index, |
274 | LLVMRustAttribute RustAttr) { | |
1a4d82fc | 275 | Function *A = unwrap<Function>(Fn); |
32a655c1 | 276 | Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr)); |
476ff2be | 277 | AttrBuilder B(Attr); |
3b2f2976 XL |
278 | #if LLVM_VERSION_GE(5, 0) |
279 | A->addAttributes(Index, B); | |
280 | #else | |
32a655c1 | 281 | A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B)); |
3b2f2976 | 282 | #endif |
1a4d82fc JJ |
283 | } |
284 | ||
ff7c6d11 XL |
285 | extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn, |
286 | unsigned Index, | |
287 | uint32_t Bytes) { | |
288 | Function *A = unwrap<Function>(Fn); | |
289 | AttrBuilder B; | |
290 | B.addAlignmentAttr(Bytes); | |
291 | #if LLVM_VERSION_GE(5, 0) | |
292 | A->addAttributes(Index, B); | |
293 | #else | |
294 | A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B)); | |
295 | #endif | |
296 | } | |
297 | ||
32a655c1 SL |
298 | extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index, |
299 | uint64_t Bytes) { | |
1a4d82fc JJ |
300 | Function *A = unwrap<Function>(Fn); |
301 | AttrBuilder B; | |
32a655c1 | 302 | B.addDereferenceableAttr(Bytes); |
3b2f2976 XL |
303 | #if LLVM_VERSION_GE(5, 0) |
304 | A->addAttributes(Index, B); | |
305 | #else | |
32a655c1 | 306 | A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B)); |
3b2f2976 | 307 | #endif |
1a4d82fc | 308 | } |
1a4d82fc | 309 | |
ff7c6d11 XL |
310 | extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn, |
311 | unsigned Index, | |
312 | uint64_t Bytes) { | |
313 | Function *A = unwrap<Function>(Fn); | |
314 | AttrBuilder B; | |
315 | B.addDereferenceableOrNullAttr(Bytes); | |
316 | #if LLVM_VERSION_GE(5, 0) | |
317 | A->addAttributes(Index, B); | |
318 | #else | |
319 | A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B)); | |
320 | #endif | |
321 | } | |
322 | ||
5bcae85e | 323 | extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn, |
32a655c1 SL |
324 | unsigned Index, |
325 | const char *Name, | |
326 | const char *Value) { | |
62682a34 SL |
327 | Function *F = unwrap<Function>(Fn); |
328 | AttrBuilder B; | |
329 | B.addAttribute(Name, Value); | |
3b2f2976 XL |
330 | #if LLVM_VERSION_GE(5, 0) |
331 | F->addAttributes(Index, B); | |
332 | #else | |
32a655c1 | 333 | F->addAttributes(Index, AttributeSet::get(F->getContext(), Index, B)); |
3b2f2976 | 334 | #endif |
62682a34 SL |
335 | } |
336 | ||
5bcae85e | 337 | extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, |
32a655c1 SL |
338 | unsigned Index, |
339 | LLVMRustAttribute RustAttr) { | |
476ff2be | 340 | Function *F = unwrap<Function>(Fn); |
32a655c1 | 341 | Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr)); |
476ff2be | 342 | AttrBuilder B(Attr); |
3b2f2976 XL |
343 | auto PAL = F->getAttributes(); |
344 | #if LLVM_VERSION_GE(5, 0) | |
345 | auto PALNew = PAL.removeAttributes(F->getContext(), Index, B); | |
346 | #else | |
32a655c1 SL |
347 | const AttributeSet PALNew = PAL.removeAttributes( |
348 | F->getContext(), Index, AttributeSet::get(F->getContext(), Index, B)); | |
3b2f2976 | 349 | #endif |
32a655c1 | 350 | F->setAttributes(PALNew); |
1a4d82fc JJ |
351 | } |
352 | ||
54a0048b SL |
353 | // enable fpmath flag UnsafeAlgebra |
354 | extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) { | |
32a655c1 | 355 | if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) { |
2c00a5a8 XL |
356 | #if LLVM_VERSION_GE(6, 0) |
357 | I->setFast(true); | |
358 | #else | |
32a655c1 | 359 | I->setHasUnsafeAlgebra(true); |
2c00a5a8 | 360 | #endif |
32a655c1 | 361 | } |
54a0048b SL |
362 | } |
363 | ||
32a655c1 SL |
364 | extern "C" LLVMValueRef |
365 | LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef Source, const char *Name, | |
ff7c6d11 | 366 | LLVMAtomicOrdering Order) { |
32a655c1 SL |
367 | LoadInst *LI = new LoadInst(unwrap(Source), 0); |
368 | LI->setAtomic(fromRust(Order)); | |
32a655c1 | 369 | return wrap(unwrap(B)->Insert(LI, Name)); |
970d7e83 LB |
370 | } |
371 | ||
5bcae85e | 372 | extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B, |
32a655c1 SL |
373 | LLVMValueRef V, |
374 | LLVMValueRef Target, | |
ff7c6d11 | 375 | LLVMAtomicOrdering Order) { |
32a655c1 SL |
376 | StoreInst *SI = new StoreInst(unwrap(V), unwrap(Target)); |
377 | SI->setAtomic(fromRust(Order)); | |
32a655c1 SL |
378 | return wrap(unwrap(B)->Insert(SI)); |
379 | } | |
380 | ||
381 | extern "C" LLVMValueRef | |
382 | LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target, | |
383 | LLVMValueRef Old, LLVMValueRef Source, | |
384 | LLVMAtomicOrdering Order, | |
385 | LLVMAtomicOrdering FailureOrder, LLVMBool Weak) { | |
386 | AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg( | |
387 | unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order), | |
388 | fromRust(FailureOrder)); | |
389 | ACXI->setWeak(Weak); | |
390 | return wrap(ACXI); | |
223e47cc | 391 | } |
5bcae85e SL |
392 | |
393 | enum class LLVMRustSynchronizationScope { | |
32a655c1 SL |
394 | Other, |
395 | SingleThread, | |
396 | CrossThread, | |
5bcae85e SL |
397 | }; |
398 | ||
3b2f2976 XL |
399 | #if LLVM_VERSION_GE(5, 0) |
400 | static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) { | |
401 | switch (Scope) { | |
402 | case LLVMRustSynchronizationScope::SingleThread: | |
403 | return SyncScope::SingleThread; | |
404 | case LLVMRustSynchronizationScope::CrossThread: | |
405 | return SyncScope::System; | |
406 | default: | |
ff7c6d11 | 407 | report_fatal_error("bad SynchronizationScope."); |
3b2f2976 XL |
408 | } |
409 | } | |
410 | #else | |
32a655c1 SL |
411 | static SynchronizationScope fromRust(LLVMRustSynchronizationScope Scope) { |
412 | switch (Scope) { | |
413 | case LLVMRustSynchronizationScope::SingleThread: | |
414 | return SingleThread; | |
415 | case LLVMRustSynchronizationScope::CrossThread: | |
416 | return CrossThread; | |
417 | default: | |
ff7c6d11 | 418 | report_fatal_error("bad SynchronizationScope."); |
32a655c1 | 419 | } |
223e47cc | 420 | } |
3b2f2976 | 421 | #endif |
223e47cc | 422 | |
32a655c1 SL |
423 | extern "C" LLVMValueRef |
424 | LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order, | |
425 | LLVMRustSynchronizationScope Scope) { | |
426 | return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope))); | |
5bcae85e SL |
427 | } |
428 | ||
5bcae85e | 429 | enum class LLVMRustAsmDialect { |
32a655c1 SL |
430 | Other, |
431 | Att, | |
432 | Intel, | |
5bcae85e SL |
433 | }; |
434 | ||
32a655c1 SL |
435 | static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) { |
436 | switch (Dialect) { | |
437 | case LLVMRustAsmDialect::Att: | |
438 | return InlineAsm::AD_ATT; | |
439 | case LLVMRustAsmDialect::Intel: | |
440 | return InlineAsm::AD_Intel; | |
441 | default: | |
ff7c6d11 | 442 | report_fatal_error("bad AsmDialect."); |
32a655c1 | 443 | } |
5bcae85e SL |
444 | } |
445 | ||
32a655c1 SL |
446 | extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, |
447 | char *Constraints, | |
448 | LLVMBool HasSideEffects, | |
449 | LLVMBool IsAlignStack, | |
450 | LLVMRustAsmDialect Dialect) { | |
451 | return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString, Constraints, | |
452 | HasSideEffects, IsAlignStack, fromRust(Dialect))); | |
223e47cc | 453 | } |
970d7e83 | 454 | |
0bf4aa26 XL |
455 | extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, |
456 | char *Constraints) { | |
457 | return InlineAsm::Verify(unwrap<FunctionType>(Ty), Constraints); | |
458 | } | |
459 | ||
cc61c64b XL |
460 | extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm) { |
461 | unwrap(M)->appendModuleInlineAsm(StringRef(Asm)); | |
462 | } | |
463 | ||
32a655c1 | 464 | typedef DIBuilder *LLVMRustDIBuilderRef; |
970d7e83 | 465 | |
3b2f2976 XL |
466 | #if LLVM_VERSION_LT(5, 0) |
467 | typedef struct LLVMOpaqueMetadata *LLVMMetadataRef; | |
85aaf69f SL |
468 | |
469 | namespace llvm { | |
3b2f2976 | 470 | DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef) |
85aaf69f | 471 | |
3b2f2976 | 472 | inline Metadata **unwrap(LLVMMetadataRef *Vals) { |
32a655c1 | 473 | return reinterpret_cast<Metadata **>(Vals); |
85aaf69f SL |
474 | } |
475 | } | |
3b2f2976 | 476 | #endif |
85aaf69f | 477 | |
3b2f2976 | 478 | template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) { |
32a655c1 | 479 | return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr); |
62682a34 SL |
480 | } |
481 | ||
62682a34 SL |
482 | #define DIDescriptor DIScope |
483 | #define DIArray DINodeArray | |
32a655c1 | 484 | #define unwrapDI unwrapDIPtr |
62682a34 | 485 | |
476ff2be SL |
486 | // These values **must** match debuginfo::DIFlags! They also *happen* |
487 | // to match LLVM, but that isn't required as we do giant sets of | |
488 | // matching below. The value shouldn't be directly passed to LLVM. | |
489 | enum class LLVMRustDIFlags : uint32_t { | |
32a655c1 SL |
490 | FlagZero = 0, |
491 | FlagPrivate = 1, | |
492 | FlagProtected = 2, | |
493 | FlagPublic = 3, | |
494 | FlagFwdDecl = (1 << 2), | |
495 | FlagAppleBlock = (1 << 3), | |
496 | FlagBlockByrefStruct = (1 << 4), | |
497 | FlagVirtual = (1 << 5), | |
498 | FlagArtificial = (1 << 6), | |
499 | FlagExplicit = (1 << 7), | |
500 | FlagPrototyped = (1 << 8), | |
501 | FlagObjcClassComplete = (1 << 9), | |
502 | FlagObjectPointer = (1 << 10), | |
503 | FlagVector = (1 << 11), | |
504 | FlagStaticMember = (1 << 12), | |
505 | FlagLValueReference = (1 << 13), | |
506 | FlagRValueReference = (1 << 14), | |
2c00a5a8 XL |
507 | FlagExternalTypeRef = (1 << 15), |
508 | FlagIntroducedVirtual = (1 << 18), | |
509 | FlagBitField = (1 << 19), | |
510 | FlagNoReturn = (1 << 20), | |
511 | FlagMainSubprogram = (1 << 21), | |
32a655c1 | 512 | // Do not add values that are not supported by the minimum LLVM |
2c00a5a8 | 513 | // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def |
476ff2be SL |
514 | }; |
515 | ||
32a655c1 SL |
516 | inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) { |
517 | return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) & | |
518 | static_cast<uint32_t>(B)); | |
476ff2be SL |
519 | } |
520 | ||
32a655c1 SL |
521 | inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) { |
522 | return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) | | |
523 | static_cast<uint32_t>(B)); | |
476ff2be SL |
524 | } |
525 | ||
32a655c1 SL |
526 | inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) { |
527 | return A = A | B; | |
476ff2be SL |
528 | } |
529 | ||
32a655c1 | 530 | inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; } |
476ff2be | 531 | |
32a655c1 SL |
532 | inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) { |
533 | return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3); | |
476ff2be SL |
534 | } |
535 | ||
32a655c1 SL |
536 | static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) { |
537 | DINode::DIFlags Result = DINode::DIFlags::FlagZero; | |
476ff2be | 538 | |
32a655c1 SL |
539 | switch (visibility(Flags)) { |
540 | case LLVMRustDIFlags::FlagPrivate: | |
541 | Result |= DINode::DIFlags::FlagPrivate; | |
542 | break; | |
543 | case LLVMRustDIFlags::FlagProtected: | |
544 | Result |= DINode::DIFlags::FlagProtected; | |
545 | break; | |
546 | case LLVMRustDIFlags::FlagPublic: | |
547 | Result |= DINode::DIFlags::FlagPublic; | |
548 | break; | |
549 | default: | |
550 | // The rest are handled below | |
551 | break; | |
552 | } | |
476ff2be | 553 | |
32a655c1 SL |
554 | if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) { |
555 | Result |= DINode::DIFlags::FlagFwdDecl; | |
556 | } | |
557 | if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) { | |
558 | Result |= DINode::DIFlags::FlagAppleBlock; | |
559 | } | |
560 | if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) { | |
561 | Result |= DINode::DIFlags::FlagBlockByrefStruct; | |
562 | } | |
563 | if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) { | |
564 | Result |= DINode::DIFlags::FlagVirtual; | |
565 | } | |
566 | if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) { | |
567 | Result |= DINode::DIFlags::FlagArtificial; | |
568 | } | |
569 | if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) { | |
570 | Result |= DINode::DIFlags::FlagExplicit; | |
571 | } | |
572 | if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) { | |
573 | Result |= DINode::DIFlags::FlagPrototyped; | |
574 | } | |
575 | if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) { | |
576 | Result |= DINode::DIFlags::FlagObjcClassComplete; | |
577 | } | |
578 | if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) { | |
579 | Result |= DINode::DIFlags::FlagObjectPointer; | |
580 | } | |
581 | if (isSet(Flags & LLVMRustDIFlags::FlagVector)) { | |
582 | Result |= DINode::DIFlags::FlagVector; | |
583 | } | |
584 | if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) { | |
585 | Result |= DINode::DIFlags::FlagStaticMember; | |
586 | } | |
587 | if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) { | |
588 | Result |= DINode::DIFlags::FlagLValueReference; | |
589 | } | |
590 | if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) { | |
591 | Result |= DINode::DIFlags::FlagRValueReference; | |
592 | } | |
2c00a5a8 XL |
593 | #if LLVM_VERSION_LE(4, 0) |
594 | if (isSet(Flags & LLVMRustDIFlags::FlagExternalTypeRef)) { | |
595 | Result |= DINode::DIFlags::FlagExternalTypeRef; | |
596 | } | |
597 | #endif | |
598 | if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) { | |
599 | Result |= DINode::DIFlags::FlagIntroducedVirtual; | |
600 | } | |
601 | if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) { | |
602 | Result |= DINode::DIFlags::FlagBitField; | |
603 | } | |
2c00a5a8 XL |
604 | if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) { |
605 | Result |= DINode::DIFlags::FlagNoReturn; | |
606 | } | |
8bb4bdeb XL |
607 | if (isSet(Flags & LLVMRustDIFlags::FlagMainSubprogram)) { |
608 | Result |= DINode::DIFlags::FlagMainSubprogram; | |
609 | } | |
476ff2be | 610 | |
32a655c1 | 611 | return Result; |
476ff2be SL |
612 | } |
613 | ||
62682a34 | 614 | extern "C" uint32_t LLVMRustDebugMetadataVersion() { |
32a655c1 | 615 | return DEBUG_METADATA_VERSION; |
62682a34 SL |
616 | } |
617 | ||
32a655c1 | 618 | extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; } |
62682a34 | 619 | |
32a655c1 | 620 | extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; } |
1a4d82fc | 621 | |
32a655c1 SL |
622 | extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name, |
623 | uint32_t Value) { | |
624 | unwrap(M)->addModuleFlag(Module::Warning, Name, Value); | |
970d7e83 LB |
625 | } |
626 | ||
ff7c6d11 XL |
627 | extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) { |
628 | return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD))); | |
041b39d2 XL |
629 | } |
630 | ||
5bcae85e | 631 | extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) { |
32a655c1 | 632 | return new DIBuilder(*unwrap(M)); |
970d7e83 LB |
633 | } |
634 | ||
5bcae85e | 635 | extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) { |
32a655c1 | 636 | delete Builder; |
970d7e83 LB |
637 | } |
638 | ||
5bcae85e | 639 | extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) { |
32a655c1 | 640 | Builder->finalize(); |
970d7e83 LB |
641 | } |
642 | ||
3b2f2976 XL |
643 | extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit( |
644 | LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef, | |
8bb4bdeb | 645 | const char *Producer, bool isOptimized, const char *Flags, |
32a655c1 | 646 | unsigned RuntimeVer, const char *SplitName) { |
8bb4bdeb XL |
647 | auto *File = unwrapDI<DIFile>(FileRef); |
648 | ||
8bb4bdeb | 649 | return wrap(Builder->createCompileUnit(Lang, File, Producer, isOptimized, |
32a655c1 SL |
650 | Flags, RuntimeVer, SplitName)); |
651 | } | |
652 | ||
3b2f2976 | 653 | extern "C" LLVMMetadataRef |
32a655c1 SL |
654 | LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename, |
655 | const char *Directory) { | |
656 | return wrap(Builder->createFile(Filename, Directory)); | |
657 | } | |
658 | ||
3b2f2976 | 659 | extern "C" LLVMMetadataRef |
32a655c1 | 660 | LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder, |
3b2f2976 XL |
661 | LLVMMetadataRef File, |
662 | LLVMMetadataRef ParameterTypes) { | |
32a655c1 | 663 | return wrap(Builder->createSubroutineType( |
32a655c1 | 664 | DITypeRefArray(unwrap<MDTuple>(ParameterTypes)))); |
970d7e83 LB |
665 | } |
666 | ||
3b2f2976 XL |
667 | extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( |
668 | LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, | |
669 | const char *LinkageName, LLVMMetadataRef File, unsigned LineNo, | |
670 | LLVMMetadataRef Ty, bool IsLocalToUnit, bool IsDefinition, | |
32a655c1 | 671 | unsigned ScopeLine, LLVMRustDIFlags Flags, bool IsOptimized, |
3b2f2976 | 672 | LLVMValueRef Fn, LLVMMetadataRef TParam, LLVMMetadataRef Decl) { |
32a655c1 SL |
673 | DITemplateParameterArray TParams = |
674 | DITemplateParameterArray(unwrap<MDTuple>(TParam)); | |
675 | DISubprogram *Sub = Builder->createFunction( | |
676 | unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File), | |
677 | LineNo, unwrapDI<DISubroutineType>(Ty), IsLocalToUnit, IsDefinition, | |
678 | ScopeLine, fromRust(Flags), IsOptimized, TParams, | |
679 | unwrapDIPtr<DISubprogram>(Decl)); | |
680 | unwrap<Function>(Fn)->setSubprogram(Sub); | |
681 | return wrap(Sub); | |
970d7e83 LB |
682 | } |
683 | ||
3b2f2976 | 684 | extern "C" LLVMMetadataRef |
32a655c1 | 685 | LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name, |
8bb4bdeb | 686 | uint64_t SizeInBits, uint32_t AlignInBits, |
32a655c1 | 687 | unsigned Encoding) { |
8faf50e0 | 688 | return wrap(Builder->createBasicType(Name, SizeInBits, Encoding)); |
970d7e83 | 689 | } |
1a4d82fc | 690 | |
3b2f2976 XL |
691 | extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType( |
692 | LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy, | |
8bb4bdeb | 693 | uint64_t SizeInBits, uint32_t AlignInBits, const char *Name) { |
32a655c1 | 694 | return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy), |
3b2f2976 XL |
695 | SizeInBits, AlignInBits, |
696 | #if LLVM_VERSION_GE(5, 0) | |
697 | /* DWARFAddressSpace */ None, | |
698 | #endif | |
699 | Name)); | |
970d7e83 LB |
700 | } |
701 | ||
3b2f2976 XL |
702 | extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType( |
703 | LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, | |
704 | LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, | |
8bb4bdeb | 705 | uint32_t AlignInBits, LLVMRustDIFlags Flags, |
3b2f2976 XL |
706 | LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements, |
707 | unsigned RunTimeLang, LLVMMetadataRef VTableHolder, | |
1a4d82fc | 708 | const char *UniqueId) { |
32a655c1 SL |
709 | return wrap(Builder->createStructType( |
710 | unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber, | |
711 | SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom), | |
712 | DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang, | |
713 | unwrapDI<DIType>(VTableHolder), UniqueId)); | |
970d7e83 LB |
714 | } |
715 | ||
3b2f2976 XL |
716 | extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType( |
717 | LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, | |
718 | LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits, | |
8bb4bdeb | 719 | uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags, |
3b2f2976 | 720 | LLVMMetadataRef Ty) { |
32a655c1 SL |
721 | return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope), Name, |
722 | unwrapDI<DIFile>(File), LineNo, | |
723 | SizeInBits, AlignInBits, OffsetInBits, | |
724 | fromRust(Flags), unwrapDI<DIType>(Ty))); | |
970d7e83 | 725 | } |
1a4d82fc | 726 | |
3b2f2976 XL |
727 | extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock( |
728 | LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, | |
729 | LLVMMetadataRef File, unsigned Line, unsigned Col) { | |
32a655c1 SL |
730 | return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope), |
731 | unwrapDI<DIFile>(File), Line, Col)); | |
1a4d82fc JJ |
732 | } |
733 | ||
3b2f2976 | 734 | extern "C" LLVMMetadataRef |
32a655c1 | 735 | LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder, |
3b2f2976 XL |
736 | LLVMMetadataRef Scope, |
737 | LLVMMetadataRef File) { | |
32a655c1 SL |
738 | return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope), |
739 | unwrapDI<DIFile>(File))); | |
9e0c209e SL |
740 | } |
741 | ||
3b2f2976 XL |
742 | extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( |
743 | LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name, | |
744 | const char *LinkageName, LLVMMetadataRef File, unsigned LineNo, | |
745 | LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V, | |
746 | LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) { | |
cc61c64b | 747 | llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V)); |
476ff2be | 748 | |
32a655c1 SL |
749 | llvm::DIExpression *InitExpr = nullptr; |
750 | if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) { | |
751 | InitExpr = Builder->createConstantValueExpression( | |
752 | IntVal->getValue().getSExtValue()); | |
753 | } else if (llvm::ConstantFP *FPVal = | |
754 | llvm::dyn_cast<llvm::ConstantFP>(InitVal)) { | |
755 | InitExpr = Builder->createConstantValueExpression( | |
756 | FPVal->getValueAPF().bitcastToAPInt().getZExtValue()); | |
757 | } | |
476ff2be | 758 | |
cc61c64b XL |
759 | llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression( |
760 | unwrapDI<DIDescriptor>(Context), Name, LinkageName, | |
761 | unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit, | |
762 | InitExpr, unwrapDIPtr<MDNode>(Decl), AlignInBits); | |
763 | ||
764 | InitVal->setMetadata("dbg", VarExpr); | |
765 | ||
766 | return wrap(VarExpr); | |
970d7e83 | 767 | } |
1a4d82fc | 768 | |
3b2f2976 XL |
769 | extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable( |
770 | LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope, | |
771 | const char *Name, LLVMMetadataRef File, unsigned LineNo, | |
772 | LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags, | |
8bb4bdeb | 773 | unsigned ArgNo, uint32_t AlignInBits) { |
32a655c1 SL |
774 | if (Tag == 0x100) { // DW_TAG_auto_variable |
775 | return wrap(Builder->createAutoVariable( | |
776 | unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNo, | |
8faf50e0 | 777 | unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits)); |
32a655c1 SL |
778 | } else { |
779 | return wrap(Builder->createParameterVariable( | |
780 | unwrapDI<DIDescriptor>(Scope), Name, ArgNo, unwrapDI<DIFile>(File), | |
781 | LineNo, unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags))); | |
782 | } | |
970d7e83 LB |
783 | } |
784 | ||
3b2f2976 | 785 | extern "C" LLVMMetadataRef |
32a655c1 | 786 | LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size, |
3b2f2976 XL |
787 | uint32_t AlignInBits, LLVMMetadataRef Ty, |
788 | LLVMMetadataRef Subscripts) { | |
32a655c1 SL |
789 | return wrap( |
790 | Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty), | |
791 | DINodeArray(unwrapDI<MDTuple>(Subscripts)))); | |
970d7e83 LB |
792 | } |
793 | ||
3b2f2976 | 794 | extern "C" LLVMMetadataRef |
32a655c1 SL |
795 | LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo, |
796 | int64_t Count) { | |
797 | return wrap(Builder->getOrCreateSubrange(Lo, Count)); | |
970d7e83 LB |
798 | } |
799 | ||
3b2f2976 | 800 | extern "C" LLVMMetadataRef |
32a655c1 | 801 | LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder, |
3b2f2976 | 802 | LLVMMetadataRef *Ptr, unsigned Count) { |
32a655c1 SL |
803 | Metadata **DataValue = unwrap(Ptr); |
804 | return wrap( | |
805 | Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get()); | |
970d7e83 LB |
806 | } |
807 | ||
5bcae85e | 808 | extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( |
3b2f2976 | 809 | LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo, |
32a655c1 | 810 | int64_t *AddrOps, unsigned AddrOpsCount, LLVMValueRef DL, |
970d7e83 | 811 | LLVMBasicBlockRef InsertAtEnd) { |
32a655c1 SL |
812 | return wrap(Builder->insertDeclare( |
813 | unwrap(V), unwrap<DILocalVariable>(VarInfo), | |
814 | Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)), | |
815 | DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())), | |
816 | unwrap(InsertAtEnd))); | |
817 | } | |
818 | ||
3b2f2976 | 819 | extern "C" LLVMMetadataRef |
32a655c1 SL |
820 | LLVMRustDIBuilderCreateEnumerator(LLVMRustDIBuilderRef Builder, |
821 | const char *Name, uint64_t Val) { | |
822 | return wrap(Builder->createEnumerator(Name, Val)); | |
1a4d82fc JJ |
823 | } |
824 | ||
3b2f2976 XL |
825 | extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType( |
826 | LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, | |
827 | LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, | |
828 | uint32_t AlignInBits, LLVMMetadataRef Elements, | |
829 | LLVMMetadataRef ClassTy) { | |
32a655c1 SL |
830 | return wrap(Builder->createEnumerationType( |
831 | unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber, | |
832 | SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)), | |
833 | unwrapDI<DIType>(ClassTy))); | |
1a4d82fc JJ |
834 | } |
835 | ||
3b2f2976 XL |
836 | extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType( |
837 | LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, | |
838 | LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, | |
839 | uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements, | |
32a655c1 SL |
840 | unsigned RunTimeLang, const char *UniqueId) { |
841 | return wrap(Builder->createUnionType( | |
842 | unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber, | |
843 | SizeInBits, AlignInBits, fromRust(Flags), | |
844 | DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang, UniqueId)); | |
1a4d82fc JJ |
845 | } |
846 | ||
3b2f2976 XL |
847 | extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter( |
848 | LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, | |
849 | LLVMMetadataRef Ty, LLVMMetadataRef File, unsigned LineNo, | |
32a655c1 SL |
850 | unsigned ColumnNo) { |
851 | return wrap(Builder->createTemplateTypeParameter( | |
852 | unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIType>(Ty))); | |
853 | } | |
854 | ||
3b2f2976 | 855 | extern "C" LLVMMetadataRef |
32a655c1 | 856 | LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder, |
3b2f2976 XL |
857 | LLVMMetadataRef Scope, const char *Name, |
858 | LLVMMetadataRef File, unsigned LineNo) { | |
32a655c1 | 859 | return wrap(Builder->createNameSpace( |
3b2f2976 XL |
860 | unwrapDI<DIDescriptor>(Scope), Name |
861 | #if LLVM_VERSION_LT(5, 0) | |
862 | , | |
863 | unwrapDI<DIFile>(File), LineNo | |
864 | #endif | |
476ff2be | 865 | #if LLVM_VERSION_GE(4, 0) |
32a655c1 SL |
866 | , |
867 | false // ExportSymbols (only relevant for C++ anonymous namespaces) | |
476ff2be | 868 | #endif |
32a655c1 | 869 | )); |
1a4d82fc JJ |
870 | } |
871 | ||
32a655c1 SL |
872 | extern "C" void |
873 | LLVMRustDICompositeTypeSetTypeArray(LLVMRustDIBuilderRef Builder, | |
3b2f2976 XL |
874 | LLVMMetadataRef CompositeTy, |
875 | LLVMMetadataRef TyArray) { | |
32a655c1 SL |
876 | DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy); |
877 | Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(TyArray))); | |
1a4d82fc JJ |
878 | } |
879 | ||
32a655c1 SL |
880 | extern "C" LLVMValueRef |
881 | LLVMRustDIBuilderCreateDebugLocation(LLVMContextRef ContextRef, unsigned Line, | |
3b2f2976 XL |
882 | unsigned Column, LLVMMetadataRef Scope, |
883 | LLVMMetadataRef InlinedAt) { | |
32a655c1 | 884 | LLVMContext &Context = *unwrap(ContextRef); |
85aaf69f | 885 | |
32a655c1 SL |
886 | DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(Scope), |
887 | unwrapDIPtr<MDNode>(InlinedAt)); | |
85aaf69f | 888 | |
32a655c1 | 889 | return wrap(MetadataAsValue::get(Context, debug_loc.getAsMDNode())); |
85aaf69f SL |
890 | } |
891 | ||
32a655c1 SL |
892 | extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() { |
893 | return dwarf::DW_OP_deref; | |
5bcae85e SL |
894 | } |
895 | ||
2c00a5a8 XL |
896 | extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() { |
897 | #if LLVM_VERSION_GE(5, 0) | |
898 | return dwarf::DW_OP_plus_uconst; | |
899 | #else | |
900 | // older LLVM used `plus` to behave like `plus_uconst`. | |
901 | return dwarf::DW_OP_plus; | |
902 | #endif | |
903 | } | |
5bcae85e | 904 | |
32a655c1 SL |
905 | extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) { |
906 | RawRustStringOstream OS(Str); | |
907 | unwrap<llvm::Type>(Ty)->print(OS); | |
1a4d82fc JJ |
908 | } |
909 | ||
32a655c1 SL |
910 | extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, |
911 | RustStringRef Str) { | |
912 | RawRustStringOstream OS(Str); | |
7cac9316 XL |
913 | if (!V) { |
914 | OS << "(null)"; | |
915 | } else { | |
916 | OS << "("; | |
917 | unwrap<llvm::Value>(V)->getType()->print(OS); | |
918 | OS << ":"; | |
919 | unwrap<llvm::Value>(V)->print(OS); | |
920 | OS << ")"; | |
921 | } | |
1a4d82fc JJ |
922 | } |
923 | ||
1a4d82fc JJ |
924 | // Note that the two following functions look quite similar to the |
925 | // LLVMGetSectionName function. Sadly, it appears that this function only | |
926 | // returns a char* pointer, which isn't guaranteed to be null-terminated. The | |
927 | // function provided by LLVM doesn't return the length, so we've created our own | |
928 | // function which returns the length as well as the data pointer. | |
929 | // | |
930 | // For an example of this not returning a null terminated string, see | |
931 | // lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the | |
932 | // branches explicitly creates a StringRef without a null terminator, and then | |
933 | // that's returned. | |
934 | ||
935 | inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { | |
32a655c1 | 936 | return reinterpret_cast<section_iterator *>(SI); |
1a4d82fc JJ |
937 | } |
938 | ||
32a655c1 SL |
939 | extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI, |
940 | const char **Ptr) { | |
941 | StringRef Ret; | |
942 | if (std::error_code EC = (*unwrap(SI))->getName(Ret)) | |
943 | report_fatal_error(EC.message()); | |
944 | *Ptr = Ret.data(); | |
945 | return Ret.size(); | |
1a4d82fc JJ |
946 | } |
947 | ||
948 | // LLVMArrayType function does not support 64-bit ElementCount | |
32a655c1 SL |
949 | extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy, |
950 | uint64_t ElementCount) { | |
951 | return wrap(ArrayType::get(unwrap(ElementTy), ElementCount)); | |
1a4d82fc JJ |
952 | } |
953 | ||
954 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef) | |
1a4d82fc | 955 | |
32a655c1 SL |
956 | extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) { |
957 | RawRustStringOstream OS(Str); | |
958 | unwrap(T)->print(OS); | |
1a4d82fc JJ |
959 | } |
960 | ||
32a655c1 SL |
961 | extern "C" void LLVMRustUnpackOptimizationDiagnostic( |
962 | LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut, | |
3b2f2976 XL |
963 | LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column, |
964 | RustStringRef FilenameOut, RustStringRef MessageOut) { | |
32a655c1 SL |
965 | // Undefined to call this not on an optimization diagnostic! |
966 | llvm::DiagnosticInfoOptimizationBase *Opt = | |
967 | static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI)); | |
1a4d82fc | 968 | |
32a655c1 SL |
969 | RawRustStringOstream PassNameOS(PassNameOut); |
970 | PassNameOS << Opt->getPassName(); | |
971 | *FunctionOut = wrap(&Opt->getFunction()); | |
3b2f2976 XL |
972 | |
973 | RawRustStringOstream FilenameOS(FilenameOut); | |
974 | #if LLVM_VERSION_GE(5,0) | |
975 | DiagnosticLocation loc = Opt->getLocation(); | |
976 | if (loc.isValid()) { | |
977 | *Line = loc.getLine(); | |
978 | *Column = loc.getColumn(); | |
979 | FilenameOS << loc.getFilename(); | |
980 | } | |
981 | #else | |
982 | const DebugLoc &loc = Opt->getDebugLoc(); | |
983 | if (loc) { | |
984 | *Line = loc.getLine(); | |
985 | *Column = loc.getCol(); | |
986 | FilenameOS << cast<DIScope>(loc.getScope())->getFilename(); | |
987 | } | |
988 | #endif | |
989 | ||
32a655c1 SL |
990 | RawRustStringOstream MessageOS(MessageOut); |
991 | MessageOS << Opt->getMsg(); | |
1a4d82fc JJ |
992 | } |
993 | ||
85aaf69f | 994 | extern "C" void |
32a655c1 SL |
995 | LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut, |
996 | LLVMTwineRef *MessageOut, | |
997 | LLVMValueRef *InstructionOut) { | |
998 | // Undefined to call this not on an inline assembly diagnostic! | |
999 | llvm::DiagnosticInfoInlineAsm *IA = | |
1000 | static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI)); | |
85aaf69f | 1001 | |
32a655c1 SL |
1002 | *CookieOut = IA->getLocCookie(); |
1003 | *MessageOut = wrap(&IA->getMsgStr()); | |
1004 | *InstructionOut = wrap(IA->getInstruction()); | |
85aaf69f SL |
1005 | } |
1006 | ||
32a655c1 SL |
1007 | extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI, |
1008 | RustStringRef Str) { | |
1009 | RawRustStringOstream OS(Str); | |
1010 | DiagnosticPrinterRawOStream DP(OS); | |
1011 | unwrap(DI)->print(DP); | |
1a4d82fc JJ |
1012 | } |
1013 | ||
5bcae85e | 1014 | enum class LLVMRustDiagnosticKind { |
32a655c1 SL |
1015 | Other, |
1016 | InlineAsm, | |
1017 | StackSize, | |
1018 | DebugMetadataVersion, | |
1019 | SampleProfile, | |
1020 | OptimizationRemark, | |
1021 | OptimizationRemarkMissed, | |
1022 | OptimizationRemarkAnalysis, | |
1023 | OptimizationRemarkAnalysisFPCommute, | |
1024 | OptimizationRemarkAnalysisAliasing, | |
1025 | OptimizationRemarkOther, | |
1026 | OptimizationFailure, | |
0531ce1d | 1027 | PGOProfile, |
b7449926 | 1028 | Linker, |
5bcae85e SL |
1029 | }; |
1030 | ||
32a655c1 SL |
1031 | static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) { |
1032 | switch (Kind) { | |
1033 | case DK_InlineAsm: | |
1034 | return LLVMRustDiagnosticKind::InlineAsm; | |
1035 | case DK_StackSize: | |
1036 | return LLVMRustDiagnosticKind::StackSize; | |
1037 | case DK_DebugMetadataVersion: | |
1038 | return LLVMRustDiagnosticKind::DebugMetadataVersion; | |
1039 | case DK_SampleProfile: | |
1040 | return LLVMRustDiagnosticKind::SampleProfile; | |
1041 | case DK_OptimizationRemark: | |
1042 | return LLVMRustDiagnosticKind::OptimizationRemark; | |
1043 | case DK_OptimizationRemarkMissed: | |
1044 | return LLVMRustDiagnosticKind::OptimizationRemarkMissed; | |
1045 | case DK_OptimizationRemarkAnalysis: | |
1046 | return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis; | |
32a655c1 SL |
1047 | case DK_OptimizationRemarkAnalysisFPCommute: |
1048 | return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute; | |
1049 | case DK_OptimizationRemarkAnalysisAliasing: | |
1050 | return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing; | |
0531ce1d XL |
1051 | case DK_PGOProfile: |
1052 | return LLVMRustDiagnosticKind::PGOProfile; | |
b7449926 XL |
1053 | case DK_Linker: |
1054 | return LLVMRustDiagnosticKind::Linker; | |
32a655c1 | 1055 | default: |
32a655c1 SL |
1056 | return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark) |
1057 | ? LLVMRustDiagnosticKind::OptimizationRemarkOther | |
1058 | : LLVMRustDiagnosticKind::Other; | |
5bcae85e SL |
1059 | } |
1060 | } | |
1061 | ||
32a655c1 SL |
1062 | extern "C" LLVMRustDiagnosticKind |
1063 | LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) { | |
1064 | return toRust((DiagnosticKind)unwrap(DI)->getKind()); | |
5bcae85e SL |
1065 | } |
1066 | // This is kept distinct from LLVMGetTypeKind, because when | |
1067 | // a new type kind is added, the Rust-side enum must be | |
1068 | // updated or UB will result. | |
1069 | extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { | |
1070 | switch (unwrap(Ty)->getTypeID()) { | |
1071 | case Type::VoidTyID: | |
1072 | return LLVMVoidTypeKind; | |
1073 | case Type::HalfTyID: | |
1074 | return LLVMHalfTypeKind; | |
1075 | case Type::FloatTyID: | |
1076 | return LLVMFloatTypeKind; | |
1077 | case Type::DoubleTyID: | |
1078 | return LLVMDoubleTypeKind; | |
1079 | case Type::X86_FP80TyID: | |
1080 | return LLVMX86_FP80TypeKind; | |
1081 | case Type::FP128TyID: | |
1082 | return LLVMFP128TypeKind; | |
1083 | case Type::PPC_FP128TyID: | |
1084 | return LLVMPPC_FP128TypeKind; | |
1085 | case Type::LabelTyID: | |
1086 | return LLVMLabelTypeKind; | |
1087 | case Type::MetadataTyID: | |
1088 | return LLVMMetadataTypeKind; | |
1089 | case Type::IntegerTyID: | |
1090 | return LLVMIntegerTypeKind; | |
1091 | case Type::FunctionTyID: | |
1092 | return LLVMFunctionTypeKind; | |
1093 | case Type::StructTyID: | |
1094 | return LLVMStructTypeKind; | |
1095 | case Type::ArrayTyID: | |
1096 | return LLVMArrayTypeKind; | |
1097 | case Type::PointerTyID: | |
1098 | return LLVMPointerTypeKind; | |
1099 | case Type::VectorTyID: | |
1100 | return LLVMVectorTypeKind; | |
1101 | case Type::X86_MMXTyID: | |
1102 | return LLVMX86_MMXTypeKind; | |
5bcae85e SL |
1103 | case Type::TokenTyID: |
1104 | return LLVMTokenTypeKind; | |
5bcae85e | 1105 | } |
ff7c6d11 | 1106 | report_fatal_error("Unhandled TypeID."); |
1a4d82fc JJ |
1107 | } |
1108 | ||
1a4d82fc JJ |
1109 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef) |
1110 | ||
5bcae85e | 1111 | extern "C" void LLVMRustSetInlineAsmDiagnosticHandler( |
32a655c1 SL |
1112 | LLVMContextRef C, LLVMContext::InlineAsmDiagHandlerTy H, void *CX) { |
1113 | unwrap(C)->setInlineAsmDiagnosticHandler(H, CX); | |
1a4d82fc JJ |
1114 | } |
1115 | ||
32a655c1 SL |
1116 | extern "C" void LLVMRustWriteSMDiagnosticToString(LLVMSMDiagnosticRef D, |
1117 | RustStringRef Str) { | |
1118 | RawRustStringOstream OS(Str); | |
1119 | unwrap(D)->print("", OS); | |
1a4d82fc | 1120 | } |
c1a9b12d | 1121 | |
32a655c1 SL |
1122 | extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B, |
1123 | LLVMValueRef ParentPad, | |
1124 | unsigned ArgCount, | |
1125 | LLVMValueRef *LLArgs, | |
1126 | const char *Name) { | |
32a655c1 SL |
1127 | Value **Args = unwrap(LLArgs); |
1128 | if (ParentPad == nullptr) { | |
1129 | Type *Ty = Type::getTokenTy(unwrap(B)->getContext()); | |
1130 | ParentPad = wrap(Constant::getNullValue(Ty)); | |
1131 | } | |
1132 | return wrap(unwrap(B)->CreateCleanupPad( | |
1133 | unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name)); | |
7453a54e SL |
1134 | } |
1135 | ||
32a655c1 SL |
1136 | extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B, |
1137 | LLVMValueRef CleanupPad, | |
1138 | LLVMBasicBlockRef UnwindBB) { | |
32a655c1 SL |
1139 | CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad)); |
1140 | return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB))); | |
7453a54e SL |
1141 | } |
1142 | ||
1143 | extern "C" LLVMValueRef | |
32a655c1 SL |
1144 | LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad, |
1145 | unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) { | |
32a655c1 SL |
1146 | Value **Args = unwrap(LLArgs); |
1147 | return wrap(unwrap(B)->CreateCatchPad( | |
1148 | unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name)); | |
7453a54e SL |
1149 | } |
1150 | ||
32a655c1 SL |
1151 | extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B, |
1152 | LLVMValueRef Pad, | |
1153 | LLVMBasicBlockRef BB) { | |
32a655c1 SL |
1154 | return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)), |
1155 | unwrap(BB))); | |
7453a54e SL |
1156 | } |
1157 | ||
32a655c1 SL |
1158 | extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B, |
1159 | LLVMValueRef ParentPad, | |
1160 | LLVMBasicBlockRef BB, | |
1161 | unsigned NumHandlers, | |
1162 | const char *Name) { | |
32a655c1 SL |
1163 | if (ParentPad == nullptr) { |
1164 | Type *Ty = Type::getTokenTy(unwrap(B)->getContext()); | |
1165 | ParentPad = wrap(Constant::getNullValue(Ty)); | |
1166 | } | |
1167 | return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB), | |
1168 | NumHandlers, Name)); | |
7453a54e SL |
1169 | } |
1170 | ||
32a655c1 SL |
1171 | extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef, |
1172 | LLVMBasicBlockRef Handler) { | |
32a655c1 SL |
1173 | Value *CatchSwitch = unwrap(CatchSwitchRef); |
1174 | cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler)); | |
7453a54e SL |
1175 | } |
1176 | ||
32a655c1 SL |
1177 | extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name, |
1178 | LLVMValueRef *Inputs, | |
1179 | unsigned NumInputs) { | |
7453a54e SL |
1180 | return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs)); |
1181 | } | |
1182 | ||
32a655c1 | 1183 | extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) { |
7453a54e SL |
1184 | delete Bundle; |
1185 | } | |
1186 | ||
32a655c1 SL |
1187 | extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, |
1188 | LLVMValueRef *Args, unsigned NumArgs, | |
1189 | OperandBundleDef *Bundle, | |
1190 | const char *Name) { | |
1191 | unsigned Len = Bundle ? 1 : 0; | |
1192 | ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len); | |
1193 | return wrap(unwrap(B)->CreateCall( | |
1194 | unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Bundles, Name)); | |
7453a54e SL |
1195 | } |
1196 | ||
1197 | extern "C" LLVMValueRef | |
32a655c1 SL |
1198 | LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, |
1199 | unsigned NumArgs, LLVMBasicBlockRef Then, | |
1200 | LLVMBasicBlockRef Catch, OperandBundleDef *Bundle, | |
7453a54e | 1201 | const char *Name) { |
32a655c1 SL |
1202 | unsigned Len = Bundle ? 1 : 0; |
1203 | ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len); | |
1204 | return wrap(unwrap(B)->CreateInvoke(unwrap(Fn), unwrap(Then), unwrap(Catch), | |
1205 | makeArrayRef(unwrap(Args), NumArgs), | |
1206 | Bundles, Name)); | |
7453a54e | 1207 | } |
54a0048b | 1208 | |
32a655c1 SL |
1209 | extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, |
1210 | LLVMBasicBlockRef BB) { | |
1211 | auto Point = unwrap(BB)->getFirstInsertionPt(); | |
1212 | unwrap(B)->SetInsertPoint(unwrap(BB), Point); | |
54a0048b SL |
1213 | } |
1214 | ||
32a655c1 SL |
1215 | extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V, |
1216 | const char *Name) { | |
1217 | Triple TargetTriple(unwrap(M)->getTargetTriple()); | |
1218 | GlobalObject *GV = unwrap<GlobalObject>(V); | |
1219 | if (!TargetTriple.isOSBinFormatMachO()) { | |
1220 | GV->setComdat(unwrap(M)->getOrInsertComdat(Name)); | |
1221 | } | |
54a0048b SL |
1222 | } |
1223 | ||
1224 | extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) { | |
32a655c1 SL |
1225 | GlobalObject *GV = unwrap<GlobalObject>(V); |
1226 | GV->setComdat(nullptr); | |
54a0048b | 1227 | } |
9e0c209e SL |
1228 | |
1229 | enum class LLVMRustLinkage { | |
32a655c1 SL |
1230 | ExternalLinkage = 0, |
1231 | AvailableExternallyLinkage = 1, | |
1232 | LinkOnceAnyLinkage = 2, | |
1233 | LinkOnceODRLinkage = 3, | |
1234 | WeakAnyLinkage = 4, | |
1235 | WeakODRLinkage = 5, | |
1236 | AppendingLinkage = 6, | |
1237 | InternalLinkage = 7, | |
1238 | PrivateLinkage = 8, | |
1239 | ExternalWeakLinkage = 9, | |
1240 | CommonLinkage = 10, | |
9e0c209e SL |
1241 | }; |
1242 | ||
32a655c1 SL |
1243 | static LLVMRustLinkage toRust(LLVMLinkage Linkage) { |
1244 | switch (Linkage) { | |
1245 | case LLVMExternalLinkage: | |
1246 | return LLVMRustLinkage::ExternalLinkage; | |
1247 | case LLVMAvailableExternallyLinkage: | |
1248 | return LLVMRustLinkage::AvailableExternallyLinkage; | |
1249 | case LLVMLinkOnceAnyLinkage: | |
1250 | return LLVMRustLinkage::LinkOnceAnyLinkage; | |
1251 | case LLVMLinkOnceODRLinkage: | |
1252 | return LLVMRustLinkage::LinkOnceODRLinkage; | |
1253 | case LLVMWeakAnyLinkage: | |
1254 | return LLVMRustLinkage::WeakAnyLinkage; | |
1255 | case LLVMWeakODRLinkage: | |
1256 | return LLVMRustLinkage::WeakODRLinkage; | |
1257 | case LLVMAppendingLinkage: | |
1258 | return LLVMRustLinkage::AppendingLinkage; | |
1259 | case LLVMInternalLinkage: | |
1260 | return LLVMRustLinkage::InternalLinkage; | |
1261 | case LLVMPrivateLinkage: | |
1262 | return LLVMRustLinkage::PrivateLinkage; | |
1263 | case LLVMExternalWeakLinkage: | |
1264 | return LLVMRustLinkage::ExternalWeakLinkage; | |
1265 | case LLVMCommonLinkage: | |
1266 | return LLVMRustLinkage::CommonLinkage; | |
1267 | default: | |
ff7c6d11 | 1268 | report_fatal_error("Invalid LLVMRustLinkage value!"); |
32a655c1 | 1269 | } |
9e0c209e SL |
1270 | } |
1271 | ||
32a655c1 SL |
1272 | static LLVMLinkage fromRust(LLVMRustLinkage Linkage) { |
1273 | switch (Linkage) { | |
1274 | case LLVMRustLinkage::ExternalLinkage: | |
1275 | return LLVMExternalLinkage; | |
1276 | case LLVMRustLinkage::AvailableExternallyLinkage: | |
1277 | return LLVMAvailableExternallyLinkage; | |
1278 | case LLVMRustLinkage::LinkOnceAnyLinkage: | |
1279 | return LLVMLinkOnceAnyLinkage; | |
1280 | case LLVMRustLinkage::LinkOnceODRLinkage: | |
1281 | return LLVMLinkOnceODRLinkage; | |
1282 | case LLVMRustLinkage::WeakAnyLinkage: | |
1283 | return LLVMWeakAnyLinkage; | |
1284 | case LLVMRustLinkage::WeakODRLinkage: | |
1285 | return LLVMWeakODRLinkage; | |
1286 | case LLVMRustLinkage::AppendingLinkage: | |
1287 | return LLVMAppendingLinkage; | |
1288 | case LLVMRustLinkage::InternalLinkage: | |
1289 | return LLVMInternalLinkage; | |
1290 | case LLVMRustLinkage::PrivateLinkage: | |
1291 | return LLVMPrivateLinkage; | |
1292 | case LLVMRustLinkage::ExternalWeakLinkage: | |
1293 | return LLVMExternalWeakLinkage; | |
1294 | case LLVMRustLinkage::CommonLinkage: | |
1295 | return LLVMCommonLinkage; | |
1296 | } | |
ff7c6d11 | 1297 | report_fatal_error("Invalid LLVMRustLinkage value!"); |
9e0c209e SL |
1298 | } |
1299 | ||
1300 | extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) { | |
32a655c1 | 1301 | return toRust(LLVMGetLinkage(V)); |
9e0c209e SL |
1302 | } |
1303 | ||
32a655c1 SL |
1304 | extern "C" void LLVMRustSetLinkage(LLVMValueRef V, |
1305 | LLVMRustLinkage RustLinkage) { | |
1306 | LLVMSetLinkage(V, fromRust(RustLinkage)); | |
1307 | } | |
1308 | ||
1309 | // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of | |
1310 | // the common sizes (1, 8, 16, 32, 64, 128 bits) | |
1311 | extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low) | |
1312 | { | |
1313 | auto C = unwrap<llvm::ConstantInt>(CV); | |
1314 | if (C->getBitWidth() > 128) { return false; } | |
1315 | APInt AP; | |
1316 | if (sext) { | |
1317 | AP = C->getValue().sextOrSelf(128); | |
1318 | } else { | |
1319 | AP = C->getValue().zextOrSelf(128); | |
1320 | } | |
1321 | *low = AP.getLoBits(64).getZExtValue(); | |
1322 | *high = AP.getHiBits(64).getZExtValue(); | |
1323 | return true; | |
9e0c209e | 1324 | } |
476ff2be | 1325 | |
476ff2be | 1326 | enum class LLVMRustVisibility { |
32a655c1 SL |
1327 | Default = 0, |
1328 | Hidden = 1, | |
1329 | Protected = 2, | |
476ff2be SL |
1330 | }; |
1331 | ||
32a655c1 SL |
1332 | static LLVMRustVisibility toRust(LLVMVisibility Vis) { |
1333 | switch (Vis) { | |
1334 | case LLVMDefaultVisibility: | |
1335 | return LLVMRustVisibility::Default; | |
1336 | case LLVMHiddenVisibility: | |
1337 | return LLVMRustVisibility::Hidden; | |
1338 | case LLVMProtectedVisibility: | |
1339 | return LLVMRustVisibility::Protected; | |
1340 | } | |
ff7c6d11 | 1341 | report_fatal_error("Invalid LLVMRustVisibility value!"); |
476ff2be SL |
1342 | } |
1343 | ||
32a655c1 SL |
1344 | static LLVMVisibility fromRust(LLVMRustVisibility Vis) { |
1345 | switch (Vis) { | |
1346 | case LLVMRustVisibility::Default: | |
1347 | return LLVMDefaultVisibility; | |
1348 | case LLVMRustVisibility::Hidden: | |
1349 | return LLVMHiddenVisibility; | |
1350 | case LLVMRustVisibility::Protected: | |
1351 | return LLVMProtectedVisibility; | |
1352 | } | |
ff7c6d11 | 1353 | report_fatal_error("Invalid LLVMRustVisibility value!"); |
476ff2be SL |
1354 | } |
1355 | ||
1356 | extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) { | |
32a655c1 | 1357 | return toRust(LLVMGetVisibility(V)); |
476ff2be SL |
1358 | } |
1359 | ||
8bb4bdeb XL |
1360 | // Oh hey, a binding that makes sense for once? (because LLVM’s own do not) |
1361 | extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val, | |
1362 | LLVMTypeRef DestTy, bool isSigned) { | |
1363 | return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, "")); | |
1364 | } | |
1365 | ||
32a655c1 SL |
1366 | extern "C" void LLVMRustSetVisibility(LLVMValueRef V, |
1367 | LLVMRustVisibility RustVisibility) { | |
1368 | LLVMSetVisibility(V, fromRust(RustVisibility)); | |
476ff2be | 1369 | } |
ea8adc8c XL |
1370 | |
1371 | struct LLVMRustModuleBuffer { | |
1372 | std::string data; | |
1373 | }; | |
1374 | ||
1375 | extern "C" LLVMRustModuleBuffer* | |
1376 | LLVMRustModuleBufferCreate(LLVMModuleRef M) { | |
1377 | auto Ret = llvm::make_unique<LLVMRustModuleBuffer>(); | |
1378 | { | |
1379 | raw_string_ostream OS(Ret->data); | |
1380 | { | |
1381 | legacy::PassManager PM; | |
1382 | PM.add(createBitcodeWriterPass(OS)); | |
1383 | PM.run(*unwrap(M)); | |
1384 | } | |
1385 | } | |
1386 | return Ret.release(); | |
1387 | } | |
1388 | ||
1389 | extern "C" void | |
1390 | LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) { | |
1391 | delete Buffer; | |
1392 | } | |
1393 | ||
1394 | extern "C" const void* | |
1395 | LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) { | |
1396 | return Buffer->data.data(); | |
1397 | } | |
1398 | ||
1399 | extern "C" size_t | |
1400 | LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) { | |
1401 | return Buffer->data.length(); | |
1402 | } | |
1403 | ||
1404 | extern "C" uint64_t | |
1405 | LLVMRustModuleCost(LLVMModuleRef M) { | |
2c00a5a8 XL |
1406 | auto f = unwrap(M)->functions(); |
1407 | return std::distance(std::begin(f), std::end(f)); | |
ea8adc8c | 1408 | } |
0531ce1d XL |
1409 | |
1410 | // Vector reductions: | |
1411 | #if LLVM_VERSION_GE(5, 0) | |
1412 | extern "C" LLVMValueRef | |
1413 | LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { | |
1414 | return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src))); | |
1415 | } | |
1416 | extern "C" LLVMValueRef | |
1417 | LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { | |
1418 | return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src))); | |
1419 | } | |
1420 | extern "C" LLVMValueRef | |
1421 | LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) { | |
1422 | return wrap(unwrap(B)->CreateAddReduce(unwrap(Src))); | |
1423 | } | |
1424 | extern "C" LLVMValueRef | |
1425 | LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) { | |
1426 | return wrap(unwrap(B)->CreateMulReduce(unwrap(Src))); | |
1427 | } | |
1428 | extern "C" LLVMValueRef | |
1429 | LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) { | |
1430 | return wrap(unwrap(B)->CreateAndReduce(unwrap(Src))); | |
1431 | } | |
1432 | extern "C" LLVMValueRef | |
1433 | LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) { | |
1434 | return wrap(unwrap(B)->CreateOrReduce(unwrap(Src))); | |
1435 | } | |
1436 | extern "C" LLVMValueRef | |
1437 | LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) { | |
1438 | return wrap(unwrap(B)->CreateXorReduce(unwrap(Src))); | |
1439 | } | |
1440 | extern "C" LLVMValueRef | |
1441 | LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) { | |
1442 | return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned)); | |
1443 | } | |
1444 | extern "C" LLVMValueRef | |
1445 | LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) { | |
1446 | return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned)); | |
1447 | } | |
1448 | extern "C" LLVMValueRef | |
1449 | LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { | |
1450 | return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN)); | |
1451 | } | |
1452 | extern "C" LLVMValueRef | |
1453 | LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { | |
1454 | return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN)); | |
1455 | } | |
1456 | ||
1457 | #else | |
1458 | ||
1459 | extern "C" LLVMValueRef | |
1460 | LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { | |
1461 | return nullptr; | |
1462 | } | |
1463 | extern "C" LLVMValueRef | |
1464 | LLVMRustBuildVectorReduceFMul(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { | |
1465 | return nullptr; | |
1466 | } | |
1467 | extern "C" LLVMValueRef | |
1468 | LLVMRustBuildVectorReduceAdd(LLVMBuilderRef, LLVMValueRef) { | |
1469 | return nullptr; | |
1470 | } | |
1471 | extern "C" LLVMValueRef | |
1472 | LLVMRustBuildVectorReduceMul(LLVMBuilderRef, LLVMValueRef) { | |
1473 | return nullptr; | |
1474 | } | |
1475 | extern "C" LLVMValueRef | |
1476 | LLVMRustBuildVectorReduceAnd(LLVMBuilderRef, LLVMValueRef) { | |
1477 | return nullptr; | |
1478 | } | |
1479 | extern "C" LLVMValueRef | |
1480 | LLVMRustBuildVectorReduceOr(LLVMBuilderRef, LLVMValueRef) { | |
1481 | return nullptr; | |
1482 | } | |
1483 | extern "C" LLVMValueRef | |
1484 | LLVMRustBuildVectorReduceXor(LLVMBuilderRef, LLVMValueRef) { | |
1485 | return nullptr; | |
1486 | } | |
1487 | extern "C" LLVMValueRef | |
1488 | LLVMRustBuildVectorReduceMin(LLVMBuilderRef, LLVMValueRef, bool) { | |
1489 | return nullptr; | |
1490 | } | |
1491 | extern "C" LLVMValueRef | |
1492 | LLVMRustBuildVectorReduceMax(LLVMBuilderRef, LLVMValueRef, bool) { | |
1493 | return nullptr; | |
1494 | } | |
1495 | extern "C" LLVMValueRef | |
1496 | LLVMRustBuildVectorReduceFMin(LLVMBuilderRef, LLVMValueRef, bool) { | |
1497 | return nullptr; | |
1498 | } | |
1499 | extern "C" LLVMValueRef | |
1500 | LLVMRustBuildVectorReduceFMax(LLVMBuilderRef, LLVMValueRef, bool) { | |
1501 | return nullptr; | |
1502 | } | |
1503 | #endif | |
1504 | ||
1505 | #if LLVM_VERSION_LT(4, 0) | |
1506 | extern "C" LLVMValueRef | |
1507 | LLVMBuildExactUDiv(LLVMBuilderRef B, LLVMValueRef LHS, | |
1508 | LLVMValueRef RHS, const char *Name) { | |
1509 | return wrap(unwrap(B)->CreateExactUDiv(unwrap(LHS), unwrap(RHS), Name)); | |
1510 | } | |
1511 | #endif | |
1512 | ||
1513 | #if LLVM_VERSION_GE(6, 0) | |
1514 | extern "C" LLVMValueRef | |
1515 | LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { | |
1516 | return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS))); | |
1517 | } | |
1518 | extern "C" LLVMValueRef | |
1519 | LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { | |
1520 | return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS))); | |
1521 | } | |
1522 | #else | |
1523 | extern "C" LLVMValueRef | |
1524 | LLVMRustBuildMinNum(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { | |
1525 | return nullptr; | |
1526 | } | |
1527 | extern "C" LLVMValueRef | |
1528 | LLVMRustBuildMaxNum(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { | |
1529 | return nullptr; | |
1530 | } | |
1531 | #endif |