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