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