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