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