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