]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Update the minimum external LLVM to 13
[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 LLVMRustDIBuilderCreateLexicalBlock(
914     LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
915     LLVMMetadataRef File, unsigned Line, unsigned Col) {
916   return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
917                                           unwrapDI<DIFile>(File), Line, Col));
918 }
919
920 extern "C" LLVMMetadataRef
921 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
922                                         LLVMMetadataRef Scope,
923                                         LLVMMetadataRef File) {
924   return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
925                                               unwrapDI<DIFile>(File)));
926 }
927
928 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
929     LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
930     const char *Name, size_t NameLen,
931     const char *LinkageName, size_t LinkageNameLen,
932     LLVMMetadataRef File, unsigned LineNo,
933     LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
934     LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
935   llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
936
937   llvm::DIExpression *InitExpr = nullptr;
938   if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
939     InitExpr = Builder->createConstantValueExpression(
940         IntVal->getValue().getSExtValue());
941   } else if (llvm::ConstantFP *FPVal =
942                  llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
943     InitExpr = Builder->createConstantValueExpression(
944         FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
945   }
946
947   llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
948       unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
949       StringRef(LinkageName, LinkageNameLen),
950       unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
951       /* isDefined */ true,
952       InitExpr, unwrapDIPtr<MDNode>(Decl),
953       /* templateParams */ nullptr,
954       AlignInBits);
955
956   InitVal->setMetadata("dbg", VarExpr);
957
958   return wrap(VarExpr);
959 }
960
961 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
962     LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
963     const char *Name, size_t NameLen,
964     LLVMMetadataRef File, unsigned LineNo,
965     LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
966     unsigned ArgNo, uint32_t AlignInBits) {
967   if (Tag == 0x100) { // DW_TAG_auto_variable
968     return wrap(Builder->createAutoVariable(
969         unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
970         unwrapDI<DIFile>(File), LineNo,
971         unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
972   } else {
973     return wrap(Builder->createParameterVariable(
974         unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
975         unwrapDI<DIFile>(File), LineNo,
976         unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
977   }
978 }
979
980 extern "C" LLVMMetadataRef
981 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
982                                  uint32_t AlignInBits, LLVMMetadataRef Ty,
983                                  LLVMMetadataRef Subscripts) {
984   return wrap(
985       Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
986                                DINodeArray(unwrapDI<MDTuple>(Subscripts))));
987 }
988
989 extern "C" LLVMMetadataRef
990 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
991                                      int64_t Count) {
992   return wrap(Builder->getOrCreateSubrange(Lo, Count));
993 }
994
995 extern "C" LLVMMetadataRef
996 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
997                                   LLVMMetadataRef *Ptr, unsigned Count) {
998   Metadata **DataValue = unwrap(Ptr);
999   return wrap(
1000       Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
1001 }
1002
1003 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
1004     LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
1005     uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
1006     LLVMBasicBlockRef InsertAtEnd) {
1007   return wrap(Builder->insertDeclare(
1008       unwrap(V), unwrap<DILocalVariable>(VarInfo),
1009       Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
1010       DebugLoc(cast<MDNode>(unwrap(DL))),
1011       unwrap(InsertAtEnd)));
1012 }
1013
1014 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
1015     LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
1016     int64_t Value, bool IsUnsigned) {
1017   return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
1018 }
1019
1020 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
1021     LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1022     const char *Name, size_t NameLen,
1023     LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1024     uint32_t AlignInBits, LLVMMetadataRef Elements,
1025     LLVMMetadataRef ClassTy, bool IsScoped) {
1026   return wrap(Builder->createEnumerationType(
1027       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
1028       unwrapDI<DIFile>(File), LineNumber,
1029       SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
1030       unwrapDI<DIType>(ClassTy), "", IsScoped));
1031 }
1032
1033 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
1034     LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1035     const char *Name, size_t NameLen,
1036     LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1037     uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
1038     unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
1039   return wrap(Builder->createUnionType(
1040       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1041       LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1042       DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1043       StringRef(UniqueId, UniqueIdLen)));
1044 }
1045
1046 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1047     LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1048     const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1049   bool IsDefault = false; // FIXME: should we ever set this true?
1050   return wrap(Builder->createTemplateTypeParameter(
1051       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1052 }
1053
1054 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1055     LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1056     const char *Name, size_t NameLen, bool ExportSymbols) {
1057   return wrap(Builder->createNameSpace(
1058       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1059   ));
1060 }
1061
1062 extern "C" void
1063 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1064                                      LLVMMetadataRef CompositeTy,
1065                                      LLVMMetadataRef Elements,
1066                                      LLVMMetadataRef Params) {
1067   DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1068   Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1069                          DINodeArray(unwrap<MDTuple>(Params)));
1070 }
1071
1072 extern "C" LLVMMetadataRef
1073 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1074                                      LLVMMetadataRef ScopeRef,
1075                                      LLVMMetadataRef InlinedAt) {
1076   MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1077   DILocation *Loc = DILocation::get(
1078       Scope->getContext(), Line, Column, Scope,
1079       unwrapDIPtr<MDNode>(InlinedAt));
1080   return wrap(Loc);
1081 }
1082
1083 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1084   return dwarf::DW_OP_deref;
1085 }
1086
1087 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1088   return dwarf::DW_OP_plus_uconst;
1089 }
1090
1091 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1092   RawRustStringOstream OS(Str);
1093   unwrap<llvm::Type>(Ty)->print(OS);
1094 }
1095
1096 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1097                                            RustStringRef Str) {
1098   RawRustStringOstream OS(Str);
1099   if (!V) {
1100     OS << "(null)";
1101   } else {
1102     OS << "(";
1103     unwrap<llvm::Value>(V)->getType()->print(OS);
1104     OS << ":";
1105     unwrap<llvm::Value>(V)->print(OS);
1106     OS << ")";
1107   }
1108 }
1109
1110 // LLVMArrayType function does not support 64-bit ElementCount
1111 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1112                                          uint64_t ElementCount) {
1113   return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1114 }
1115
1116 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1117
1118 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1119   RawRustStringOstream OS(Str);
1120   unwrap(T)->print(OS);
1121 }
1122
1123 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1124     LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1125     LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1126     RustStringRef FilenameOut, RustStringRef MessageOut) {
1127   // Undefined to call this not on an optimization diagnostic!
1128   llvm::DiagnosticInfoOptimizationBase *Opt =
1129       static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1130
1131   RawRustStringOstream PassNameOS(PassNameOut);
1132   PassNameOS << Opt->getPassName();
1133   *FunctionOut = wrap(&Opt->getFunction());
1134
1135   RawRustStringOstream FilenameOS(FilenameOut);
1136   DiagnosticLocation loc = Opt->getLocation();
1137   if (loc.isValid()) {
1138     *Line = loc.getLine();
1139     *Column = loc.getColumn();
1140     FilenameOS << loc.getAbsolutePath();
1141   }
1142
1143   RawRustStringOstream MessageOS(MessageOut);
1144   MessageOS << Opt->getMsg();
1145 }
1146
1147 enum class LLVMRustDiagnosticLevel {
1148     Error,
1149     Warning,
1150     Note,
1151     Remark,
1152 };
1153
1154 extern "C" void
1155 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1156                                   LLVMRustDiagnosticLevel *LevelOut,
1157                                   unsigned *CookieOut,
1158                                   LLVMTwineRef *MessageOut) {
1159   // Undefined to call this not on an inline assembly diagnostic!
1160   llvm::DiagnosticInfoInlineAsm *IA =
1161       static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1162
1163   *CookieOut = IA->getLocCookie();
1164   *MessageOut = wrap(&IA->getMsgStr());
1165
1166   switch (IA->getSeverity()) {
1167     case DS_Error:
1168       *LevelOut = LLVMRustDiagnosticLevel::Error;
1169       break;
1170     case DS_Warning:
1171       *LevelOut = LLVMRustDiagnosticLevel::Warning;
1172       break;
1173     case DS_Note:
1174       *LevelOut = LLVMRustDiagnosticLevel::Note;
1175       break;
1176     case DS_Remark:
1177       *LevelOut = LLVMRustDiagnosticLevel::Remark;
1178       break;
1179     default:
1180       report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1181   }
1182 }
1183
1184 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1185                                                     RustStringRef Str) {
1186   RawRustStringOstream OS(Str);
1187   DiagnosticPrinterRawOStream DP(OS);
1188   unwrap(DI)->print(DP);
1189 }
1190
1191 enum class LLVMRustDiagnosticKind {
1192   Other,
1193   InlineAsm,
1194   StackSize,
1195   DebugMetadataVersion,
1196   SampleProfile,
1197   OptimizationRemark,
1198   OptimizationRemarkMissed,
1199   OptimizationRemarkAnalysis,
1200   OptimizationRemarkAnalysisFPCommute,
1201   OptimizationRemarkAnalysisAliasing,
1202   OptimizationRemarkOther,
1203   OptimizationFailure,
1204   PGOProfile,
1205   Linker,
1206   Unsupported,
1207   SrcMgr,
1208 };
1209
1210 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1211   switch (Kind) {
1212   case DK_InlineAsm:
1213     return LLVMRustDiagnosticKind::InlineAsm;
1214   case DK_StackSize:
1215     return LLVMRustDiagnosticKind::StackSize;
1216   case DK_DebugMetadataVersion:
1217     return LLVMRustDiagnosticKind::DebugMetadataVersion;
1218   case DK_SampleProfile:
1219     return LLVMRustDiagnosticKind::SampleProfile;
1220   case DK_OptimizationRemark:
1221   case DK_MachineOptimizationRemark:
1222     return LLVMRustDiagnosticKind::OptimizationRemark;
1223   case DK_OptimizationRemarkMissed:
1224   case DK_MachineOptimizationRemarkMissed:
1225     return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1226   case DK_OptimizationRemarkAnalysis:
1227   case DK_MachineOptimizationRemarkAnalysis:
1228     return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1229   case DK_OptimizationRemarkAnalysisFPCommute:
1230     return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1231   case DK_OptimizationRemarkAnalysisAliasing:
1232     return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1233   case DK_PGOProfile:
1234     return LLVMRustDiagnosticKind::PGOProfile;
1235   case DK_Linker:
1236     return LLVMRustDiagnosticKind::Linker;
1237   case DK_Unsupported:
1238     return LLVMRustDiagnosticKind::Unsupported;
1239   case DK_SrcMgr:
1240     return LLVMRustDiagnosticKind::SrcMgr;
1241   default:
1242     return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1243                ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1244                : LLVMRustDiagnosticKind::Other;
1245   }
1246 }
1247
1248 extern "C" LLVMRustDiagnosticKind
1249 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1250   return toRust((DiagnosticKind)unwrap(DI)->getKind());
1251 }
1252
1253 // This is kept distinct from LLVMGetTypeKind, because when
1254 // a new type kind is added, the Rust-side enum must be
1255 // updated or UB will result.
1256 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1257   switch (unwrap(Ty)->getTypeID()) {
1258   case Type::VoidTyID:
1259     return LLVMVoidTypeKind;
1260   case Type::HalfTyID:
1261     return LLVMHalfTypeKind;
1262   case Type::FloatTyID:
1263     return LLVMFloatTypeKind;
1264   case Type::DoubleTyID:
1265     return LLVMDoubleTypeKind;
1266   case Type::X86_FP80TyID:
1267     return LLVMX86_FP80TypeKind;
1268   case Type::FP128TyID:
1269     return LLVMFP128TypeKind;
1270   case Type::PPC_FP128TyID:
1271     return LLVMPPC_FP128TypeKind;
1272   case Type::LabelTyID:
1273     return LLVMLabelTypeKind;
1274   case Type::MetadataTyID:
1275     return LLVMMetadataTypeKind;
1276   case Type::IntegerTyID:
1277     return LLVMIntegerTypeKind;
1278   case Type::FunctionTyID:
1279     return LLVMFunctionTypeKind;
1280   case Type::StructTyID:
1281     return LLVMStructTypeKind;
1282   case Type::ArrayTyID:
1283     return LLVMArrayTypeKind;
1284   case Type::PointerTyID:
1285     return LLVMPointerTypeKind;
1286   case Type::FixedVectorTyID:
1287     return LLVMVectorTypeKind;
1288   case Type::X86_MMXTyID:
1289     return LLVMX86_MMXTypeKind;
1290   case Type::TokenTyID:
1291     return LLVMTokenTypeKind;
1292   case Type::ScalableVectorTyID:
1293     return LLVMScalableVectorTypeKind;
1294   case Type::BFloatTyID:
1295     return LLVMBFloatTypeKind;
1296   case Type::X86_AMXTyID:
1297     return LLVMX86_AMXTypeKind;
1298 #if LLVM_VERSION_GE(15, 0) && LLVM_VERSION_LT(16, 0)
1299   case Type::DXILPointerTyID:
1300     report_fatal_error("Rust does not support DirectX typed pointers.");
1301     break;
1302 #endif
1303 #if LLVM_VERSION_GE(16, 0)
1304   case Type::TypedPointerTyID:
1305     report_fatal_error("Rust does not support typed pointers.");
1306     break;
1307 #endif
1308   }
1309   report_fatal_error("Unhandled TypeID.");
1310 }
1311
1312 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1313
1314 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1315     LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1316   llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1317   *Cookie = SM->getLocCookie();
1318   return wrap(&SM->getSMDiag());
1319 }
1320
1321 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1322                                            RustStringRef MessageOut,
1323                                            RustStringRef BufferOut,
1324                                            LLVMRustDiagnosticLevel* LevelOut,
1325                                            unsigned* LocOut,
1326                                            unsigned* RangesOut,
1327                                            size_t* NumRanges) {
1328   SMDiagnostic& D = *unwrap(DRef);
1329   RawRustStringOstream MessageOS(MessageOut);
1330   MessageOS << D.getMessage();
1331
1332   switch (D.getKind()) {
1333     case SourceMgr::DK_Error:
1334       *LevelOut = LLVMRustDiagnosticLevel::Error;
1335       break;
1336     case SourceMgr::DK_Warning:
1337       *LevelOut = LLVMRustDiagnosticLevel::Warning;
1338       break;
1339     case SourceMgr::DK_Note:
1340       *LevelOut = LLVMRustDiagnosticLevel::Note;
1341       break;
1342     case SourceMgr::DK_Remark:
1343       *LevelOut = LLVMRustDiagnosticLevel::Remark;
1344       break;
1345     default:
1346       report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1347   }
1348
1349   if (D.getLoc() == SMLoc())
1350     return false;
1351
1352   const SourceMgr &LSM = *D.getSourceMgr();
1353   const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1354   LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1355
1356   *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1357
1358   *NumRanges = std::min(*NumRanges, D.getRanges().size());
1359   size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1360   for (size_t i = 0; i < *NumRanges; i++) {
1361     RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1362     RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1363   }
1364
1365   return true;
1366 }
1367
1368 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1369                                                 LLVMValueRef ParentPad,
1370                                                 unsigned ArgCount,
1371                                                 LLVMValueRef *LLArgs,
1372                                                 const char *Name) {
1373   Value **Args = unwrap(LLArgs);
1374   if (ParentPad == nullptr) {
1375     Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1376     ParentPad = wrap(Constant::getNullValue(Ty));
1377   }
1378   return wrap(unwrap(B)->CreateCleanupPad(
1379       unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1380 }
1381
1382 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1383                                                 LLVMValueRef CleanupPad,
1384                                                 LLVMBasicBlockRef UnwindBB) {
1385   CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1386   return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1387 }
1388
1389 extern "C" LLVMValueRef
1390 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1391                       unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1392   Value **Args = unwrap(LLArgs);
1393   return wrap(unwrap(B)->CreateCatchPad(
1394       unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1395 }
1396
1397 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1398                                               LLVMValueRef Pad,
1399                                               LLVMBasicBlockRef BB) {
1400   return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1401                                               unwrap(BB)));
1402 }
1403
1404 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1405                                                  LLVMValueRef ParentPad,
1406                                                  LLVMBasicBlockRef BB,
1407                                                  unsigned NumHandlers,
1408                                                  const char *Name) {
1409   if (ParentPad == nullptr) {
1410     Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1411     ParentPad = wrap(Constant::getNullValue(Ty));
1412   }
1413   return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1414                                                  NumHandlers, Name));
1415 }
1416
1417 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1418                                    LLVMBasicBlockRef Handler) {
1419   Value *CatchSwitch = unwrap(CatchSwitchRef);
1420   cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1421 }
1422
1423 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1424                                                            LLVMValueRef *Inputs,
1425                                                            unsigned NumInputs) {
1426   return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1427 }
1428
1429 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1430   delete Bundle;
1431 }
1432
1433 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1434                                           LLVMValueRef *Args, unsigned NumArgs,
1435                                           OperandBundleDef *Bundle) {
1436   Value *Callee = unwrap(Fn);
1437   FunctionType *FTy = unwrap<FunctionType>(Ty);
1438   unsigned Len = Bundle ? 1 : 0;
1439   ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1440   return wrap(unwrap(B)->CreateCall(
1441       FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1442 }
1443
1444 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1445   return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1446               (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1447 }
1448
1449 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1450                                             LLVMValueRef Dst, unsigned DstAlign,
1451                                             LLVMValueRef Src, unsigned SrcAlign,
1452                                             LLVMValueRef Size, bool IsVolatile) {
1453   return wrap(unwrap(B)->CreateMemCpy(
1454       unwrap(Dst), MaybeAlign(DstAlign),
1455       unwrap(Src), MaybeAlign(SrcAlign),
1456       unwrap(Size), IsVolatile));
1457 }
1458
1459 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1460                                              LLVMValueRef Dst, unsigned DstAlign,
1461                                              LLVMValueRef Src, unsigned SrcAlign,
1462                                              LLVMValueRef Size, bool IsVolatile) {
1463   return wrap(unwrap(B)->CreateMemMove(
1464       unwrap(Dst), MaybeAlign(DstAlign),
1465       unwrap(Src), MaybeAlign(SrcAlign),
1466       unwrap(Size), IsVolatile));
1467 }
1468
1469 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1470                                             LLVMValueRef Dst, unsigned DstAlign,
1471                                             LLVMValueRef Val,
1472                                             LLVMValueRef Size, bool IsVolatile) {
1473   return wrap(unwrap(B)->CreateMemSet(
1474       unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1475 }
1476
1477 extern "C" LLVMValueRef
1478 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1479                     LLVMValueRef *Args, unsigned NumArgs,
1480                     LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1481                     OperandBundleDef *Bundle, const char *Name) {
1482   Value *Callee = unwrap(Fn);
1483   FunctionType *FTy = unwrap<FunctionType>(Ty);
1484   unsigned Len = Bundle ? 1 : 0;
1485   ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1486   return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1487                                       makeArrayRef(unwrap(Args), NumArgs),
1488                                       Bundles, Name));
1489 }
1490
1491 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1492                                                LLVMBasicBlockRef BB) {
1493   auto Point = unwrap(BB)->getFirstInsertionPt();
1494   unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1495 }
1496
1497 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1498                                   const char *Name, size_t NameLen) {
1499   Triple TargetTriple(unwrap(M)->getTargetTriple());
1500   GlobalObject *GV = unwrap<GlobalObject>(V);
1501   if (TargetTriple.supportsCOMDAT()) {
1502     StringRef NameRef(Name, NameLen);
1503     GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1504   }
1505 }
1506
1507 enum class LLVMRustLinkage {
1508   ExternalLinkage = 0,
1509   AvailableExternallyLinkage = 1,
1510   LinkOnceAnyLinkage = 2,
1511   LinkOnceODRLinkage = 3,
1512   WeakAnyLinkage = 4,
1513   WeakODRLinkage = 5,
1514   AppendingLinkage = 6,
1515   InternalLinkage = 7,
1516   PrivateLinkage = 8,
1517   ExternalWeakLinkage = 9,
1518   CommonLinkage = 10,
1519 };
1520
1521 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1522   switch (Linkage) {
1523   case LLVMExternalLinkage:
1524     return LLVMRustLinkage::ExternalLinkage;
1525   case LLVMAvailableExternallyLinkage:
1526     return LLVMRustLinkage::AvailableExternallyLinkage;
1527   case LLVMLinkOnceAnyLinkage:
1528     return LLVMRustLinkage::LinkOnceAnyLinkage;
1529   case LLVMLinkOnceODRLinkage:
1530     return LLVMRustLinkage::LinkOnceODRLinkage;
1531   case LLVMWeakAnyLinkage:
1532     return LLVMRustLinkage::WeakAnyLinkage;
1533   case LLVMWeakODRLinkage:
1534     return LLVMRustLinkage::WeakODRLinkage;
1535   case LLVMAppendingLinkage:
1536     return LLVMRustLinkage::AppendingLinkage;
1537   case LLVMInternalLinkage:
1538     return LLVMRustLinkage::InternalLinkage;
1539   case LLVMPrivateLinkage:
1540     return LLVMRustLinkage::PrivateLinkage;
1541   case LLVMExternalWeakLinkage:
1542     return LLVMRustLinkage::ExternalWeakLinkage;
1543   case LLVMCommonLinkage:
1544     return LLVMRustLinkage::CommonLinkage;
1545   default:
1546     report_fatal_error("Invalid LLVMRustLinkage value!");
1547   }
1548 }
1549
1550 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1551   switch (Linkage) {
1552   case LLVMRustLinkage::ExternalLinkage:
1553     return LLVMExternalLinkage;
1554   case LLVMRustLinkage::AvailableExternallyLinkage:
1555     return LLVMAvailableExternallyLinkage;
1556   case LLVMRustLinkage::LinkOnceAnyLinkage:
1557     return LLVMLinkOnceAnyLinkage;
1558   case LLVMRustLinkage::LinkOnceODRLinkage:
1559     return LLVMLinkOnceODRLinkage;
1560   case LLVMRustLinkage::WeakAnyLinkage:
1561     return LLVMWeakAnyLinkage;
1562   case LLVMRustLinkage::WeakODRLinkage:
1563     return LLVMWeakODRLinkage;
1564   case LLVMRustLinkage::AppendingLinkage:
1565     return LLVMAppendingLinkage;
1566   case LLVMRustLinkage::InternalLinkage:
1567     return LLVMInternalLinkage;
1568   case LLVMRustLinkage::PrivateLinkage:
1569     return LLVMPrivateLinkage;
1570   case LLVMRustLinkage::ExternalWeakLinkage:
1571     return LLVMExternalWeakLinkage;
1572   case LLVMRustLinkage::CommonLinkage:
1573     return LLVMCommonLinkage;
1574   }
1575   report_fatal_error("Invalid LLVMRustLinkage value!");
1576 }
1577
1578 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1579   return toRust(LLVMGetLinkage(V));
1580 }
1581
1582 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1583                                    LLVMRustLinkage RustLinkage) {
1584   LLVMSetLinkage(V, fromRust(RustLinkage));
1585 }
1586
1587 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1588                                                   LLVMValueRef ConstantVal,
1589                                                   LLVMValueRef *ConstantIndices,
1590                                                   unsigned NumIndices) {
1591   ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1592                                NumIndices);
1593   Constant *Val = unwrap<Constant>(ConstantVal);
1594   return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1595 }
1596
1597 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1598 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1599 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1600 {
1601     auto C = unwrap<llvm::ConstantInt>(CV);
1602     if (C->getBitWidth() > 128) { return false; }
1603     APInt AP;
1604 #if LLVM_VERSION_GE(15, 0)
1605     if (sext) {
1606         AP = C->getValue().sext(128);
1607     } else {
1608         AP = C->getValue().zext(128);
1609     }
1610 #else
1611     if (sext) {
1612         AP = C->getValue().sextOrSelf(128);
1613     } else {
1614         AP = C->getValue().zextOrSelf(128);
1615     }
1616 #endif
1617     *low = AP.getLoBits(64).getZExtValue();
1618     *high = AP.getHiBits(64).getZExtValue();
1619     return true;
1620 }
1621
1622 enum class LLVMRustVisibility {
1623   Default = 0,
1624   Hidden = 1,
1625   Protected = 2,
1626 };
1627
1628 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1629   switch (Vis) {
1630   case LLVMDefaultVisibility:
1631     return LLVMRustVisibility::Default;
1632   case LLVMHiddenVisibility:
1633     return LLVMRustVisibility::Hidden;
1634   case LLVMProtectedVisibility:
1635     return LLVMRustVisibility::Protected;
1636   }
1637   report_fatal_error("Invalid LLVMRustVisibility value!");
1638 }
1639
1640 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1641   switch (Vis) {
1642   case LLVMRustVisibility::Default:
1643     return LLVMDefaultVisibility;
1644   case LLVMRustVisibility::Hidden:
1645     return LLVMHiddenVisibility;
1646   case LLVMRustVisibility::Protected:
1647     return LLVMProtectedVisibility;
1648   }
1649   report_fatal_error("Invalid LLVMRustVisibility value!");
1650 }
1651
1652 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1653   return toRust(LLVMGetVisibility(V));
1654 }
1655
1656 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1657 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1658                                              LLVMTypeRef DestTy, bool isSigned) {
1659   return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1660 }
1661
1662 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1663                                       LLVMRustVisibility RustVisibility) {
1664   LLVMSetVisibility(V, fromRust(RustVisibility));
1665 }
1666
1667 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1668   unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1669 }
1670
1671 struct LLVMRustModuleBuffer {
1672   std::string data;
1673 };
1674
1675 extern "C" LLVMRustModuleBuffer*
1676 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1677   auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1678   {
1679     raw_string_ostream OS(Ret->data);
1680     {
1681       legacy::PassManager PM;
1682       PM.add(createBitcodeWriterPass(OS));
1683       PM.run(*unwrap(M));
1684     }
1685   }
1686   return Ret.release();
1687 }
1688
1689 extern "C" void
1690 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1691   delete Buffer;
1692 }
1693
1694 extern "C" const void*
1695 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1696   return Buffer->data.data();
1697 }
1698
1699 extern "C" size_t
1700 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1701   return Buffer->data.length();
1702 }
1703
1704 extern "C" uint64_t
1705 LLVMRustModuleCost(LLVMModuleRef M) {
1706   auto f = unwrap(M)->functions();
1707   return std::distance(std::begin(f), std::end(f));
1708 }
1709
1710 // Vector reductions:
1711 extern "C" LLVMValueRef
1712 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1713     return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1714 }
1715 extern "C" LLVMValueRef
1716 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1717     return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1718 }
1719 extern "C" LLVMValueRef
1720 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1721     return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1722 }
1723 extern "C" LLVMValueRef
1724 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1725     return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1726 }
1727 extern "C" LLVMValueRef
1728 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1729     return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1730 }
1731 extern "C" LLVMValueRef
1732 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1733     return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1734 }
1735 extern "C" LLVMValueRef
1736 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1737     return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1738 }
1739 extern "C" LLVMValueRef
1740 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1741     return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1742 }
1743 extern "C" LLVMValueRef
1744 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1745     return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1746 }
1747 extern "C" LLVMValueRef
1748 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1749   Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1750   I->setHasNoNaNs(NoNaN);
1751   return wrap(I);
1752 }
1753 extern "C" LLVMValueRef
1754 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1755   Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1756   I->setHasNoNaNs(NoNaN);
1757   return wrap(I);
1758 }
1759
1760 extern "C" LLVMValueRef
1761 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1762     return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1763 }
1764 extern "C" LLVMValueRef
1765 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1766     return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1767 }
1768
1769 // This struct contains all necessary info about a symbol exported from a DLL.
1770 struct LLVMRustCOFFShortExport {
1771   const char* name;
1772   bool ordinal_present;
1773   // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1774   uint16_t ordinal;
1775 };
1776
1777 // Machine must be a COFF machine type, as defined in PE specs.
1778 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1779   const char* ImportName,
1780   const char* Path,
1781   const LLVMRustCOFFShortExport* Exports,
1782   size_t NumExports,
1783   uint16_t Machine,
1784   bool MinGW)
1785 {
1786   std::vector<llvm::object::COFFShortExport> ConvertedExports;
1787   ConvertedExports.reserve(NumExports);
1788
1789   for (size_t i = 0; i < NumExports; ++i) {
1790     bool ordinal_present = Exports[i].ordinal_present;
1791     uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1792     ConvertedExports.push_back(llvm::object::COFFShortExport{
1793       Exports[i].name,  // Name
1794       std::string{},    // ExtName
1795       std::string{},    // SymbolName
1796       std::string{},    // AliasTarget
1797       ordinal,          // Ordinal
1798       ordinal_present,  // Noname
1799       false,            // Data
1800       false,            // Private
1801       false             // Constant
1802     });
1803   }
1804
1805   auto Error = llvm::object::writeImportLibrary(
1806     ImportName,
1807     Path,
1808     ConvertedExports,
1809     static_cast<llvm::COFF::MachineTypes>(Machine),
1810     MinGW);
1811   if (Error) {
1812     std::string errorString;
1813     llvm::raw_string_ostream stream(errorString);
1814     stream << Error;
1815     stream.flush();
1816     LLVMRustSetLastError(errorString.c_str());
1817     return LLVMRustResult::Failure;
1818   } else {
1819     return LLVMRustResult::Success;
1820   }
1821 }
1822
1823 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1824 extern "C" DiagnosticHandler *
1825 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1826   std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1827   return DH.release();
1828 }
1829
1830 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1831 // handling. Ownership of the handler is moved to the LLVMContext.
1832 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1833                                                     DiagnosticHandler *DH) {
1834   unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1835 }
1836
1837 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1838
1839 // Configures a diagnostic handler that invokes provided callback when a
1840 // backend needs to emit a diagnostic.
1841 //
1842 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1843 // the RemarkPasses array specifies individual passes for which remarks will be
1844 // enabled.
1845 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1846     LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1847     void *DiagnosticHandlerContext, bool RemarkAllPasses,
1848     const char * const * RemarkPasses, size_t RemarkPassesLen) {
1849
1850   class RustDiagnosticHandler final : public DiagnosticHandler {
1851   public:
1852     RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1853                           void *DiagnosticHandlerContext,
1854                           bool RemarkAllPasses,
1855                           std::vector<std::string> RemarkPasses)
1856         : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1857           DiagnosticHandlerContext(DiagnosticHandlerContext),
1858           RemarkAllPasses(RemarkAllPasses),
1859           RemarkPasses(RemarkPasses) {}
1860
1861     virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1862       if (DiagnosticHandlerCallback) {
1863         DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1864         return true;
1865       }
1866       return false;
1867     }
1868
1869     bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1870       return isRemarkEnabled(PassName);
1871     }
1872
1873     bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1874       return isRemarkEnabled(PassName);
1875     }
1876
1877     bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1878       return isRemarkEnabled(PassName);
1879     }
1880
1881     bool isAnyRemarkEnabled() const override {
1882       return RemarkAllPasses || !RemarkPasses.empty();
1883     }
1884
1885   private:
1886     bool isRemarkEnabled(StringRef PassName) const {
1887       if (RemarkAllPasses)
1888         return true;
1889
1890       for (auto &Pass : RemarkPasses)
1891         if (Pass == PassName)
1892           return true;
1893
1894       return false;
1895     }
1896
1897     LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1898     void *DiagnosticHandlerContext = nullptr;
1899
1900     bool RemarkAllPasses = false;
1901     std::vector<std::string> RemarkPasses;
1902   };
1903
1904   std::vector<std::string> Passes;
1905   for (size_t I = 0; I != RemarkPassesLen; ++I)
1906     Passes.push_back(RemarkPasses[I]);
1907
1908   unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1909       DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
1910 }
1911
1912 extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
1913   RawRustStringOstream OS(Str);
1914   GlobalValue *GV = unwrap<GlobalValue>(V);
1915   Mangler().getNameWithPrefix(OS, GV, true);
1916 }
1917
1918 // LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just
1919 // use its implementation.
1920 #if LLVM_VERSION_LT(15, 0)
1921 extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
1922     return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));
1923 }
1924 #endif
1925
1926 extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
1927 #if LLVM_VERSION_GE(15, 0)
1928     auto *CB = unwrap<CallBase>(CallSite);
1929     switch (CB->getIntrinsicID()) {
1930         case Intrinsic::arm_ldrex:
1931             return 0;
1932         case Intrinsic::arm_strex:
1933             return 1;
1934     }
1935 #endif
1936     return -1;
1937 }