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