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