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