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