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