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