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