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