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