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