1 #include "LLVMWrapper.h"
2 #include "llvm/IR/DebugInfoMetadata.h"
3 #include "llvm/IR/DiagnosticInfo.h"
4 #include "llvm/IR/DiagnosticPrinter.h"
5 #include "llvm/IR/GlobalVariable.h"
6 #include "llvm/IR/Instructions.h"
7 #include "llvm/IR/Intrinsics.h"
8 #include "llvm/Object/Archive.h"
9 #include "llvm/Object/ObjectFile.h"
10 #include "llvm/Bitcode/BitcodeWriterPass.h"
11 #include "llvm/Support/Signals.h"
12 #include "llvm/ADT/Optional.h"
16 //===----------------------------------------------------------------------===
18 // This file defines alternate interfaces to core functions that are more
19 // readily callable by Rust's FFI.
21 //===----------------------------------------------------------------------===
24 using namespace llvm::sys;
25 using namespace llvm::object;
27 // LLVMAtomicOrdering is already an enum - don't create another
29 static AtomicOrdering fromRust(LLVMAtomicOrdering 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;
47 report_fatal_error("Invalid LLVMAtomicOrdering value!");
50 static LLVM_THREAD_LOCAL char *LastError;
52 // Custom error handler for fatal LLVM errors.
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,
58 // Do the same thing that the default error handler does.
59 std::cerr << "LLVM ERROR: " << Reason << std::endl;
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
64 sys::RunInterruptHandlers();
69 extern "C" void LLVMRustInstallFatalErrorHandler() {
70 install_fatal_error_handler(FatalErrorHandler);
73 extern "C" LLVMMemoryBufferRef
74 LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
75 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr =
76 MemoryBuffer::getFile(Path, -1, false);
78 LLVMRustSetLastError(BufOr.getError().message().c_str());
81 return wrap(BufOr.get().release());
84 extern "C" char *LLVMRustGetLastError(void) {
85 char *Ret = LastError;
90 extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) {
91 return unwrap(M)->getInstructionCount();
94 extern "C" void LLVMRustSetLastError(const char *Err) {
95 free((void *)LastError);
96 LastError = strdup(Err);
99 extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
100 auto ctx = new LLVMContext();
101 ctx->setDiscardValueNames(shouldDiscardNames);
105 extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
106 const char *Triple) {
107 unwrap(M)->setTargetTriple(Triple::normalize(Triple));
110 extern "C" void LLVMRustPrintPassTimings() {
111 raw_fd_ostream OS(2, false); // stderr.
112 TimerGroup::printAll(OS);
115 extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
117 return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
120 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
123 LLVMTypeRef FunctionTy) {
124 return wrap(unwrap(M)
125 ->getOrInsertFunction(StringRef(Name, NameLen),
126 unwrap<FunctionType>(FunctionTy))
131 extern "C" LLVMValueRef
132 LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
133 StringRef NameRef(Name, NameLen);
134 return wrap(unwrap(M)->getOrInsertGlobal(NameRef, unwrap(Ty)));
137 extern "C" LLVMValueRef
138 LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
139 return wrap(new GlobalVariable(*unwrap(M),
142 GlobalValue::PrivateLinkage,
146 extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
147 return wrap(Type::getMetadataTy(*unwrap(C)));
150 static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
153 return Attribute::AlwaysInline;
155 return Attribute::ByVal;
157 return Attribute::Cold;
159 return Attribute::InlineHint;
161 return Attribute::MinSize;
163 return Attribute::Naked;
165 return Attribute::NoAlias;
167 return Attribute::NoCapture;
169 return Attribute::NoInline;
171 return Attribute::NonNull;
173 return Attribute::NoRedZone;
175 return Attribute::NoReturn;
177 return Attribute::NoUnwind;
178 case OptimizeForSize:
179 return Attribute::OptimizeForSize;
181 return Attribute::ReadOnly;
183 return Attribute::SExt;
185 return Attribute::StructRet;
187 return Attribute::UWTable;
189 return Attribute::ZExt;
191 return Attribute::InReg;
193 return Attribute::SanitizeThread;
194 case SanitizeAddress:
195 return Attribute::SanitizeAddress;
197 return Attribute::SanitizeMemory;
199 return Attribute::NonLazyBind;
201 return Attribute::OptimizeNone;
203 return Attribute::ReturnsTwice;
205 return Attribute::ReadNone;
206 case InaccessibleMemOnly:
207 return Attribute::InaccessibleMemOnly;
208 case SanitizeHWAddress:
209 return Attribute::SanitizeHWAddress;
211 return Attribute::WillReturn;
213 report_fatal_error("bad AttributeKind");
216 extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
217 LLVMRustAttribute RustAttr) {
218 CallBase *Call = unwrap<CallBase>(Instr);
219 Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
220 Call->addAttribute(Index, Attr);
223 extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index,
225 CallBase *Call = unwrap<CallBase>(Instr);
226 Attribute Attr = Attribute::get(Call->getContext(), Name);
227 Call->addAttribute(Index, Attr);
231 extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
234 CallBase *Call = unwrap<CallBase>(Instr);
236 B.addAlignmentAttr(Bytes);
237 Call->setAttributes(Call->getAttributes().addAttributes(
238 Call->getContext(), Index, B));
241 extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
244 CallBase *Call = unwrap<CallBase>(Instr);
246 B.addDereferenceableAttr(Bytes);
247 Call->setAttributes(Call->getAttributes().addAttributes(
248 Call->getContext(), Index, B));
251 extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
254 CallBase *Call = unwrap<CallBase>(Instr);
256 B.addDereferenceableOrNullAttr(Bytes);
257 Call->setAttributes(Call->getAttributes().addAttributes(
258 Call->getContext(), Index, B));
261 extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
263 CallBase *Call = unwrap<CallBase>(Instr);
264 Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
265 Call->addAttribute(Index, Attr);
268 extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index,
270 CallBase *Call = unwrap<CallBase>(Instr);
271 #if LLVM_VERSION_GE(12, 0)
272 Attribute Attr = Attribute::getWithStructRetType(Call->getContext(), unwrap(Ty));
274 Attribute Attr = Attribute::get(Call->getContext(), Attribute::StructRet);
276 Call->addAttribute(Index, Attr);
279 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
280 LLVMRustAttribute RustAttr) {
281 Function *A = unwrap<Function>(Fn);
282 Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
284 A->addAttributes(Index, B);
287 extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
290 Function *A = unwrap<Function>(Fn);
292 B.addAlignmentAttr(Bytes);
293 A->addAttributes(Index, B);
296 extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
298 Function *A = unwrap<Function>(Fn);
300 B.addDereferenceableAttr(Bytes);
301 A->addAttributes(Index, B);
304 extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
307 Function *A = unwrap<Function>(Fn);
309 B.addDereferenceableOrNullAttr(Bytes);
310 A->addAttributes(Index, B);
313 extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
315 Function *F = unwrap<Function>(Fn);
316 Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
317 F->addAttribute(Index, Attr);
320 extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index,
322 Function *F = unwrap<Function>(Fn);
323 #if LLVM_VERSION_GE(12, 0)
324 Attribute Attr = Attribute::getWithStructRetType(F->getContext(), unwrap(Ty));
326 Attribute Attr = Attribute::get(F->getContext(), Attribute::StructRet);
328 F->addAttribute(Index, Attr);
331 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
335 Function *F = unwrap<Function>(Fn);
337 B.addAttribute(Name, Value);
338 F->addAttributes(Index, B);
341 extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
343 LLVMRustAttribute RustAttr) {
344 Function *F = unwrap<Function>(Fn);
345 Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr));
347 auto PAL = F->getAttributes();
348 auto PALNew = PAL.removeAttributes(F->getContext(), Index, B);
349 F->setAttributes(PALNew);
352 // enable fpmath flag UnsafeAlgebra
353 extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) {
354 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
359 extern "C" LLVMValueRef
360 LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef Source, const char *Name,
361 LLVMAtomicOrdering Order) {
362 Value *Ptr = unwrap(Source);
363 Type *Ty = Ptr->getType()->getPointerElementType();
364 LoadInst *LI = unwrap(B)->CreateLoad(Ty, Ptr, Name);
365 LI->setAtomic(fromRust(Order));
369 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
372 LLVMAtomicOrdering Order) {
373 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
374 SI->setAtomic(fromRust(Order));
378 // FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
379 // once we raise our minimum support to LLVM 10.
380 extern "C" LLVMValueRef
381 LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
382 LLVMValueRef Old, LLVMValueRef Source,
383 LLVMAtomicOrdering Order,
384 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
385 #if LLVM_VERSION_GE(13,0)
386 // Rust probably knows the alignment of the target value and should be able to
387 // specify something more precise than MaybeAlign here. See also
388 // https://reviews.llvm.org/D97224 which may be a useful reference.
389 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
390 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
391 fromRust(FailureOrder));
393 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
394 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
395 fromRust(FailureOrder));
401 enum class LLVMRustSynchronizationScope {
406 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
408 case LLVMRustSynchronizationScope::SingleThread:
409 return SyncScope::SingleThread;
410 case LLVMRustSynchronizationScope::CrossThread:
411 return SyncScope::System;
413 report_fatal_error("bad SynchronizationScope.");
417 extern "C" LLVMValueRef
418 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
419 LLVMRustSynchronizationScope Scope) {
420 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
423 enum class LLVMRustAsmDialect {
428 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
430 case LLVMRustAsmDialect::Att:
431 return InlineAsm::AD_ATT;
432 case LLVMRustAsmDialect::Intel:
433 return InlineAsm::AD_Intel;
435 report_fatal_error("bad AsmDialect.");
439 extern "C" LLVMValueRef
440 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
441 char *Constraints, size_t ConstraintsLen,
442 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
443 LLVMRustAsmDialect Dialect) {
444 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
445 StringRef(AsmString, AsmStringLen),
446 StringRef(Constraints, ConstraintsLen),
447 HasSideEffects, IsAlignStack, fromRust(Dialect)));
450 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
451 size_t ConstraintsLen) {
452 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
453 StringRef(Constraints, ConstraintsLen));
456 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
458 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
461 typedef DIBuilder *LLVMRustDIBuilderRef;
463 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
464 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
467 #define DIDescriptor DIScope
468 #define DIArray DINodeArray
469 #define unwrapDI unwrapDIPtr
471 // These values **must** match debuginfo::DIFlags! They also *happen*
472 // to match LLVM, but that isn't required as we do giant sets of
473 // matching below. The value shouldn't be directly passed to LLVM.
474 enum class LLVMRustDIFlags : uint32_t {
479 FlagFwdDecl = (1 << 2),
480 FlagAppleBlock = (1 << 3),
481 FlagBlockByrefStruct = (1 << 4),
482 FlagVirtual = (1 << 5),
483 FlagArtificial = (1 << 6),
484 FlagExplicit = (1 << 7),
485 FlagPrototyped = (1 << 8),
486 FlagObjcClassComplete = (1 << 9),
487 FlagObjectPointer = (1 << 10),
488 FlagVector = (1 << 11),
489 FlagStaticMember = (1 << 12),
490 FlagLValueReference = (1 << 13),
491 FlagRValueReference = (1 << 14),
492 FlagExternalTypeRef = (1 << 15),
493 FlagIntroducedVirtual = (1 << 18),
494 FlagBitField = (1 << 19),
495 FlagNoReturn = (1 << 20),
496 // Do not add values that are not supported by the minimum LLVM
497 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
500 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
501 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
502 static_cast<uint32_t>(B));
505 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
506 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
507 static_cast<uint32_t>(B));
510 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
514 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
516 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
517 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
520 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
521 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
523 switch (visibility(Flags)) {
524 case LLVMRustDIFlags::FlagPrivate:
525 Result |= DINode::DIFlags::FlagPrivate;
527 case LLVMRustDIFlags::FlagProtected:
528 Result |= DINode::DIFlags::FlagProtected;
530 case LLVMRustDIFlags::FlagPublic:
531 Result |= DINode::DIFlags::FlagPublic;
534 // The rest are handled below
538 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
539 Result |= DINode::DIFlags::FlagFwdDecl;
541 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
542 Result |= DINode::DIFlags::FlagAppleBlock;
544 #if LLVM_VERSION_LT(10, 0)
545 if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) {
546 Result |= DINode::DIFlags::FlagBlockByrefStruct;
549 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
550 Result |= DINode::DIFlags::FlagVirtual;
552 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
553 Result |= DINode::DIFlags::FlagArtificial;
555 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
556 Result |= DINode::DIFlags::FlagExplicit;
558 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
559 Result |= DINode::DIFlags::FlagPrototyped;
561 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
562 Result |= DINode::DIFlags::FlagObjcClassComplete;
564 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
565 Result |= DINode::DIFlags::FlagObjectPointer;
567 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
568 Result |= DINode::DIFlags::FlagVector;
570 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
571 Result |= DINode::DIFlags::FlagStaticMember;
573 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
574 Result |= DINode::DIFlags::FlagLValueReference;
576 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
577 Result |= DINode::DIFlags::FlagRValueReference;
579 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
580 Result |= DINode::DIFlags::FlagIntroducedVirtual;
582 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
583 Result |= DINode::DIFlags::FlagBitField;
585 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
586 Result |= DINode::DIFlags::FlagNoReturn;
592 // These values **must** match debuginfo::DISPFlags! They also *happen*
593 // to match LLVM, but that isn't required as we do giant sets of
594 // matching below. The value shouldn't be directly passed to LLVM.
595 enum class LLVMRustDISPFlags : uint32_t {
598 SPFlagPureVirtual = 2,
599 SPFlagLocalToUnit = (1 << 2),
600 SPFlagDefinition = (1 << 3),
601 SPFlagOptimized = (1 << 4),
602 SPFlagMainSubprogram = (1 << 5),
603 // Do not add values that are not supported by the minimum LLVM
604 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
605 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
608 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
609 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
610 static_cast<uint32_t>(B));
613 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
614 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
615 static_cast<uint32_t>(B));
618 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
622 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
624 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
625 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
628 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
629 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
631 switch (virtuality(SPFlags)) {
632 case LLVMRustDISPFlags::SPFlagVirtual:
633 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
635 case LLVMRustDISPFlags::SPFlagPureVirtual:
636 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
639 // The rest are handled below
643 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
644 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
646 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
647 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
649 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
650 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
652 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
653 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
659 enum class LLVMRustDebugEmissionKind {
665 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
667 case LLVMRustDebugEmissionKind::NoDebug:
668 return DICompileUnit::DebugEmissionKind::NoDebug;
669 case LLVMRustDebugEmissionKind::FullDebug:
670 return DICompileUnit::DebugEmissionKind::FullDebug;
671 case LLVMRustDebugEmissionKind::LineTablesOnly:
672 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
674 report_fatal_error("bad DebugEmissionKind.");
678 enum class LLVMRustChecksumKind {
685 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
687 case LLVMRustChecksumKind::None:
689 case LLVMRustChecksumKind::MD5:
690 return DIFile::ChecksumKind::CSK_MD5;
691 case LLVMRustChecksumKind::SHA1:
692 return DIFile::ChecksumKind::CSK_SHA1;
693 #if (LLVM_VERSION_MAJOR >= 11)
694 case LLVMRustChecksumKind::SHA256:
695 return DIFile::ChecksumKind::CSK_SHA256;
698 report_fatal_error("bad ChecksumKind.");
702 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
703 return DEBUG_METADATA_VERSION;
706 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
708 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
710 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
712 extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
714 unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
717 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
718 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
721 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
722 return new DIBuilder(*unwrap(M));
725 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
729 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
733 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
734 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
735 const char *Producer, size_t ProducerLen, bool isOptimized,
736 const char *Flags, unsigned RuntimeVer,
737 const char *SplitName, size_t SplitNameLen,
738 LLVMRustDebugEmissionKind Kind,
739 uint64_t DWOId, bool SplitDebugInlining) {
740 auto *File = unwrapDI<DIFile>(FileRef);
742 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
743 isOptimized, Flags, RuntimeVer,
744 StringRef(SplitName, SplitNameLen),
745 fromRust(Kind), DWOId, SplitDebugInlining));
748 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
749 LLVMRustDIBuilderRef Builder,
750 const char *Filename, size_t FilenameLen,
751 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
752 const char *Checksum, size_t ChecksumLen) {
753 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
754 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
756 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
757 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
758 StringRef(Directory, DirectoryLen),
762 extern "C" LLVMMetadataRef
763 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
764 LLVMMetadataRef ParameterTypes) {
765 return wrap(Builder->createSubroutineType(
766 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
769 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
770 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
771 const char *Name, size_t NameLen,
772 const char *LinkageName, size_t LinkageNameLen,
773 LLVMMetadataRef File, unsigned LineNo,
774 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
775 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
776 LLVMMetadataRef Decl) {
777 DITemplateParameterArray TParams =
778 DITemplateParameterArray(unwrap<MDTuple>(TParam));
779 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
780 DINode::DIFlags llvmFlags = fromRust(Flags);
781 DISubprogram *Sub = Builder->createFunction(
782 unwrapDI<DIScope>(Scope),
783 StringRef(Name, NameLen),
784 StringRef(LinkageName, LinkageNameLen),
785 unwrapDI<DIFile>(File), LineNo,
786 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
787 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
789 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
793 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
794 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
795 uint64_t SizeInBits, unsigned Encoding) {
796 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
799 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
800 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
801 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
802 return wrap(Builder->createTypedef(
803 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
804 LineNo, unwrapDIPtr<DIScope>(Scope)));
807 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
808 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
809 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
810 const char *Name, size_t NameLen) {
811 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
812 SizeInBits, AlignInBits,
814 StringRef(Name, NameLen)));
817 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
818 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
819 const char *Name, size_t NameLen,
820 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
821 uint32_t AlignInBits, LLVMRustDIFlags Flags,
822 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
823 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
824 const char *UniqueId, size_t UniqueIdLen) {
825 return wrap(Builder->createStructType(
826 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
827 unwrapDI<DIFile>(File), LineNumber,
828 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
829 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
830 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
833 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
834 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
835 const char *Name, size_t NameLen,
836 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
837 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
838 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
839 return wrap(Builder->createVariantPart(
840 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
841 unwrapDI<DIFile>(File), LineNumber,
842 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
843 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
846 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
847 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
848 const char *Name, size_t NameLen,
849 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
850 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
851 LLVMMetadataRef Ty) {
852 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
853 StringRef(Name, NameLen),
854 unwrapDI<DIFile>(File), LineNo,
855 SizeInBits, AlignInBits, OffsetInBits,
856 fromRust(Flags), unwrapDI<DIType>(Ty)));
859 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
860 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
861 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
862 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
863 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
864 llvm::ConstantInt* D = nullptr;
866 D = unwrap<llvm::ConstantInt>(Discriminant);
868 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
869 StringRef(Name, NameLen),
870 unwrapDI<DIFile>(File), LineNo,
871 SizeInBits, AlignInBits, OffsetInBits, D,
872 fromRust(Flags), unwrapDI<DIType>(Ty)));
875 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
876 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
877 LLVMMetadataRef File, unsigned Line, unsigned Col) {
878 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
879 unwrapDI<DIFile>(File), Line, Col));
882 extern "C" LLVMMetadataRef
883 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
884 LLVMMetadataRef Scope,
885 LLVMMetadataRef File) {
886 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
887 unwrapDI<DIFile>(File)));
890 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
891 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
892 const char *Name, size_t NameLen,
893 const char *LinkageName, size_t LinkageNameLen,
894 LLVMMetadataRef File, unsigned LineNo,
895 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
896 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
897 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
899 llvm::DIExpression *InitExpr = nullptr;
900 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
901 InitExpr = Builder->createConstantValueExpression(
902 IntVal->getValue().getSExtValue());
903 } else if (llvm::ConstantFP *FPVal =
904 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
905 InitExpr = Builder->createConstantValueExpression(
906 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
909 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
910 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
911 StringRef(LinkageName, LinkageNameLen),
912 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
913 #if LLVM_VERSION_GE(10, 0)
914 /* isDefined */ true,
916 InitExpr, unwrapDIPtr<MDNode>(Decl),
917 /* templateParams */ nullptr,
920 InitVal->setMetadata("dbg", VarExpr);
922 return wrap(VarExpr);
925 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
926 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
927 const char *Name, size_t NameLen,
928 LLVMMetadataRef File, unsigned LineNo,
929 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
930 unsigned ArgNo, uint32_t AlignInBits) {
931 if (Tag == 0x100) { // DW_TAG_auto_variable
932 return wrap(Builder->createAutoVariable(
933 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
934 unwrapDI<DIFile>(File), LineNo,
935 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
937 return wrap(Builder->createParameterVariable(
938 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
939 unwrapDI<DIFile>(File), LineNo,
940 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
944 extern "C" LLVMMetadataRef
945 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
946 uint32_t AlignInBits, LLVMMetadataRef Ty,
947 LLVMMetadataRef Subscripts) {
949 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
950 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
953 extern "C" LLVMMetadataRef
954 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
956 return wrap(Builder->getOrCreateSubrange(Lo, Count));
959 extern "C" LLVMMetadataRef
960 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
961 LLVMMetadataRef *Ptr, unsigned Count) {
962 Metadata **DataValue = unwrap(Ptr);
964 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
967 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
968 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
969 int64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
970 LLVMBasicBlockRef InsertAtEnd) {
971 return wrap(Builder->insertDeclare(
972 unwrap(V), unwrap<DILocalVariable>(VarInfo),
973 Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
974 DebugLoc(cast<MDNode>(unwrap(DL))),
975 unwrap(InsertAtEnd)));
978 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
979 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
980 int64_t Value, bool IsUnsigned) {
981 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
984 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
985 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
986 const char *Name, size_t NameLen,
987 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
988 uint32_t AlignInBits, LLVMMetadataRef Elements,
989 LLVMMetadataRef ClassTy, bool IsScoped) {
990 return wrap(Builder->createEnumerationType(
991 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
992 unwrapDI<DIFile>(File), LineNumber,
993 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
994 unwrapDI<DIType>(ClassTy), "", IsScoped));
997 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
998 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
999 const char *Name, size_t NameLen,
1000 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1001 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
1002 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
1003 return wrap(Builder->createUnionType(
1004 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1005 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1006 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1007 StringRef(UniqueId, UniqueIdLen)));
1010 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1011 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1012 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1013 #if LLVM_VERSION_GE(11, 0)
1014 bool IsDefault = false; // FIXME: should we ever set this true?
1015 return wrap(Builder->createTemplateTypeParameter(
1016 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1018 return wrap(Builder->createTemplateTypeParameter(
1019 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty)));
1023 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1024 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1025 const char *Name, size_t NameLen, bool ExportSymbols) {
1026 return wrap(Builder->createNameSpace(
1027 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1032 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1033 LLVMMetadataRef CompositeTy,
1034 LLVMMetadataRef Elements,
1035 LLVMMetadataRef Params) {
1036 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1037 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1038 DINodeArray(unwrap<MDTuple>(Params)));
1041 extern "C" LLVMMetadataRef
1042 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1043 LLVMMetadataRef ScopeRef,
1044 LLVMMetadataRef InlinedAt) {
1045 #if LLVM_VERSION_GE(12, 0)
1046 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1047 DILocation *Loc = DILocation::get(
1048 Scope->getContext(), Line, Column, Scope,
1049 unwrapDIPtr<MDNode>(InlinedAt));
1052 DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(ScopeRef),
1053 unwrapDIPtr<MDNode>(InlinedAt));
1054 return wrap(debug_loc.getAsMDNode());
1058 extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {
1059 return dwarf::DW_OP_deref;
1062 extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1063 return dwarf::DW_OP_plus_uconst;
1066 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1067 RawRustStringOstream OS(Str);
1068 unwrap<llvm::Type>(Ty)->print(OS);
1071 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1072 RustStringRef Str) {
1073 RawRustStringOstream OS(Str);
1078 unwrap<llvm::Value>(V)->getType()->print(OS);
1080 unwrap<llvm::Value>(V)->print(OS);
1085 // Note that the two following functions look quite similar to the
1086 // LLVMGetSectionName function. Sadly, it appears that this function only
1087 // returns a char* pointer, which isn't guaranteed to be null-terminated. The
1088 // function provided by LLVM doesn't return the length, so we've created our own
1089 // function which returns the length as well as the data pointer.
1091 // For an example of this not returning a null terminated string, see
1092 // lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the
1093 // branches explicitly creates a StringRef without a null terminator, and then
1096 inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
1097 return reinterpret_cast<section_iterator *>(SI);
1100 extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI,
1102 #if LLVM_VERSION_GE(10, 0)
1103 auto NameOrErr = (*unwrap(SI))->getName();
1105 report_fatal_error(NameOrErr.takeError());
1106 *Ptr = NameOrErr->data();
1107 return NameOrErr->size();
1110 if (std::error_code EC = (*unwrap(SI))->getName(Ret))
1111 report_fatal_error(EC.message());
1117 // LLVMArrayType function does not support 64-bit ElementCount
1118 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1119 uint64_t ElementCount) {
1120 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1123 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1125 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1126 RawRustStringOstream OS(Str);
1127 unwrap(T)->print(OS);
1130 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1131 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1132 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1133 RustStringRef FilenameOut, RustStringRef MessageOut) {
1134 // Undefined to call this not on an optimization diagnostic!
1135 llvm::DiagnosticInfoOptimizationBase *Opt =
1136 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1138 RawRustStringOstream PassNameOS(PassNameOut);
1139 PassNameOS << Opt->getPassName();
1140 *FunctionOut = wrap(&Opt->getFunction());
1142 RawRustStringOstream FilenameOS(FilenameOut);
1143 DiagnosticLocation loc = Opt->getLocation();
1144 if (loc.isValid()) {
1145 *Line = loc.getLine();
1146 *Column = loc.getColumn();
1147 FilenameOS << loc.getAbsolutePath();
1150 RawRustStringOstream MessageOS(MessageOut);
1151 MessageOS << Opt->getMsg();
1154 enum class LLVMRustDiagnosticLevel {
1162 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1163 LLVMRustDiagnosticLevel *LevelOut,
1164 unsigned *CookieOut,
1165 LLVMTwineRef *MessageOut,
1166 LLVMValueRef *InstructionOut) {
1167 // Undefined to call this not on an inline assembly diagnostic!
1168 llvm::DiagnosticInfoInlineAsm *IA =
1169 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1171 *CookieOut = IA->getLocCookie();
1172 *MessageOut = wrap(&IA->getMsgStr());
1173 *InstructionOut = wrap(IA->getInstruction());
1175 switch (IA->getSeverity()) {
1177 *LevelOut = LLVMRustDiagnosticLevel::Error;
1180 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1183 *LevelOut = LLVMRustDiagnosticLevel::Note;
1186 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1189 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1193 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1194 RustStringRef Str) {
1195 RawRustStringOstream OS(Str);
1196 DiagnosticPrinterRawOStream DP(OS);
1197 unwrap(DI)->print(DP);
1200 enum class LLVMRustDiagnosticKind {
1204 DebugMetadataVersion,
1207 OptimizationRemarkMissed,
1208 OptimizationRemarkAnalysis,
1209 OptimizationRemarkAnalysisFPCommute,
1210 OptimizationRemarkAnalysisAliasing,
1211 OptimizationRemarkOther,
1212 OptimizationFailure,
1218 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1221 return LLVMRustDiagnosticKind::InlineAsm;
1223 return LLVMRustDiagnosticKind::StackSize;
1224 case DK_DebugMetadataVersion:
1225 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1226 case DK_SampleProfile:
1227 return LLVMRustDiagnosticKind::SampleProfile;
1228 case DK_OptimizationRemark:
1229 return LLVMRustDiagnosticKind::OptimizationRemark;
1230 case DK_OptimizationRemarkMissed:
1231 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1232 case DK_OptimizationRemarkAnalysis:
1233 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1234 case DK_OptimizationRemarkAnalysisFPCommute:
1235 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1236 case DK_OptimizationRemarkAnalysisAliasing:
1237 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1239 return LLVMRustDiagnosticKind::PGOProfile;
1241 return LLVMRustDiagnosticKind::Linker;
1242 case DK_Unsupported:
1243 return LLVMRustDiagnosticKind::Unsupported;
1245 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1246 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1247 : LLVMRustDiagnosticKind::Other;
1251 extern "C" LLVMRustDiagnosticKind
1252 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1253 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1256 // This is kept distinct from LLVMGetTypeKind, because when
1257 // a new type kind is added, the Rust-side enum must be
1258 // updated or UB will result.
1259 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1260 switch (unwrap(Ty)->getTypeID()) {
1261 case Type::VoidTyID:
1262 return LLVMVoidTypeKind;
1263 case Type::HalfTyID:
1264 return LLVMHalfTypeKind;
1265 case Type::FloatTyID:
1266 return LLVMFloatTypeKind;
1267 case Type::DoubleTyID:
1268 return LLVMDoubleTypeKind;
1269 case Type::X86_FP80TyID:
1270 return LLVMX86_FP80TypeKind;
1271 case Type::FP128TyID:
1272 return LLVMFP128TypeKind;
1273 case Type::PPC_FP128TyID:
1274 return LLVMPPC_FP128TypeKind;
1275 case Type::LabelTyID:
1276 return LLVMLabelTypeKind;
1277 case Type::MetadataTyID:
1278 return LLVMMetadataTypeKind;
1279 case Type::IntegerTyID:
1280 return LLVMIntegerTypeKind;
1281 case Type::FunctionTyID:
1282 return LLVMFunctionTypeKind;
1283 case Type::StructTyID:
1284 return LLVMStructTypeKind;
1285 case Type::ArrayTyID:
1286 return LLVMArrayTypeKind;
1287 case Type::PointerTyID:
1288 return LLVMPointerTypeKind;
1289 #if LLVM_VERSION_GE(11, 0)
1290 case Type::FixedVectorTyID:
1291 return LLVMVectorTypeKind;
1293 case Type::VectorTyID:
1294 return LLVMVectorTypeKind;
1296 case Type::X86_MMXTyID:
1297 return LLVMX86_MMXTypeKind;
1298 case Type::TokenTyID:
1299 return LLVMTokenTypeKind;
1300 #if LLVM_VERSION_GE(11, 0)
1301 case Type::ScalableVectorTyID:
1302 return LLVMScalableVectorTypeKind;
1303 case Type::BFloatTyID:
1304 return LLVMBFloatTypeKind;
1306 #if LLVM_VERSION_GE(12, 0)
1307 case Type::X86_AMXTyID:
1308 return LLVMX86_AMXTypeKind;
1311 report_fatal_error("Unhandled TypeID.");
1314 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1316 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1317 LLVMContextRef C, LLVMContext::InlineAsmDiagHandlerTy H, void *CX) {
1318 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1321 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1322 RustStringRef MessageOut,
1323 RustStringRef BufferOut,
1324 LLVMRustDiagnosticLevel* LevelOut,
1326 unsigned* RangesOut,
1327 size_t* NumRanges) {
1328 SMDiagnostic& D = *unwrap(DRef);
1329 RawRustStringOstream MessageOS(MessageOut);
1330 MessageOS << D.getMessage();
1332 switch (D.getKind()) {
1333 case SourceMgr::DK_Error:
1334 *LevelOut = LLVMRustDiagnosticLevel::Error;
1336 case SourceMgr::DK_Warning:
1337 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1339 case SourceMgr::DK_Note:
1340 *LevelOut = LLVMRustDiagnosticLevel::Note;
1342 case SourceMgr::DK_Remark:
1343 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1346 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1349 if (D.getLoc() == SMLoc())
1352 const SourceMgr &LSM = *D.getSourceMgr();
1353 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1354 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1356 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1358 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1359 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1360 for (size_t i = 0; i < *NumRanges; i++) {
1361 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1362 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1368 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1369 LLVMValueRef ParentPad,
1371 LLVMValueRef *LLArgs,
1373 Value **Args = unwrap(LLArgs);
1374 if (ParentPad == nullptr) {
1375 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1376 ParentPad = wrap(Constant::getNullValue(Ty));
1378 return wrap(unwrap(B)->CreateCleanupPad(
1379 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1382 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1383 LLVMValueRef CleanupPad,
1384 LLVMBasicBlockRef UnwindBB) {
1385 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1386 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1389 extern "C" LLVMValueRef
1390 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1391 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1392 Value **Args = unwrap(LLArgs);
1393 return wrap(unwrap(B)->CreateCatchPad(
1394 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1397 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1399 LLVMBasicBlockRef BB) {
1400 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1404 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1405 LLVMValueRef ParentPad,
1406 LLVMBasicBlockRef BB,
1407 unsigned NumHandlers,
1409 if (ParentPad == nullptr) {
1410 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1411 ParentPad = wrap(Constant::getNullValue(Ty));
1413 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1414 NumHandlers, Name));
1417 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1418 LLVMBasicBlockRef Handler) {
1419 Value *CatchSwitch = unwrap(CatchSwitchRef);
1420 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1423 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1424 LLVMValueRef *Inputs,
1425 unsigned NumInputs) {
1426 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1429 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1433 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
1434 LLVMValueRef *Args, unsigned NumArgs,
1435 OperandBundleDef *Bundle) {
1436 Value *Callee = unwrap(Fn);
1437 FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType());
1438 unsigned Len = Bundle ? 1 : 0;
1439 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1440 return wrap(unwrap(B)->CreateCall(
1441 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1444 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1445 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1446 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1449 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1450 LLVMValueRef Dst, unsigned DstAlign,
1451 LLVMValueRef Src, unsigned SrcAlign,
1452 LLVMValueRef Size, bool IsVolatile) {
1453 #if LLVM_VERSION_GE(10, 0)
1454 return wrap(unwrap(B)->CreateMemCpy(
1455 unwrap(Dst), MaybeAlign(DstAlign),
1456 unwrap(Src), MaybeAlign(SrcAlign),
1457 unwrap(Size), IsVolatile));
1459 return wrap(unwrap(B)->CreateMemCpy(
1460 unwrap(Dst), DstAlign,
1461 unwrap(Src), SrcAlign,
1462 unwrap(Size), IsVolatile));
1466 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1467 LLVMValueRef Dst, unsigned DstAlign,
1468 LLVMValueRef Src, unsigned SrcAlign,
1469 LLVMValueRef Size, bool IsVolatile) {
1470 #if LLVM_VERSION_GE(10, 0)
1471 return wrap(unwrap(B)->CreateMemMove(
1472 unwrap(Dst), MaybeAlign(DstAlign),
1473 unwrap(Src), MaybeAlign(SrcAlign),
1474 unwrap(Size), IsVolatile));
1476 return wrap(unwrap(B)->CreateMemMove(
1477 unwrap(Dst), DstAlign,
1478 unwrap(Src), SrcAlign,
1479 unwrap(Size), IsVolatile));
1483 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1484 LLVMValueRef Dst, unsigned DstAlign,
1486 LLVMValueRef Size, bool IsVolatile) {
1487 #if LLVM_VERSION_GE(10, 0)
1488 return wrap(unwrap(B)->CreateMemSet(
1489 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1491 return wrap(unwrap(B)->CreateMemSet(
1492 unwrap(Dst), unwrap(Val), unwrap(Size), DstAlign, IsVolatile));
1496 extern "C" LLVMValueRef
1497 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
1498 unsigned NumArgs, LLVMBasicBlockRef Then,
1499 LLVMBasicBlockRef Catch, OperandBundleDef *Bundle,
1501 Value *Callee = unwrap(Fn);
1502 FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType());
1503 unsigned Len = Bundle ? 1 : 0;
1504 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1505 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1506 makeArrayRef(unwrap(Args), NumArgs),
1510 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1511 LLVMBasicBlockRef BB) {
1512 auto Point = unwrap(BB)->getFirstInsertionPt();
1513 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1516 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1517 const char *Name, size_t NameLen) {
1518 Triple TargetTriple(unwrap(M)->getTargetTriple());
1519 GlobalObject *GV = unwrap<GlobalObject>(V);
1520 if (TargetTriple.supportsCOMDAT()) {
1521 StringRef NameRef(Name, NameLen);
1522 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1526 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1527 GlobalObject *GV = unwrap<GlobalObject>(V);
1528 GV->setComdat(nullptr);
1531 enum class LLVMRustLinkage {
1532 ExternalLinkage = 0,
1533 AvailableExternallyLinkage = 1,
1534 LinkOnceAnyLinkage = 2,
1535 LinkOnceODRLinkage = 3,
1538 AppendingLinkage = 6,
1539 InternalLinkage = 7,
1541 ExternalWeakLinkage = 9,
1545 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1547 case LLVMExternalLinkage:
1548 return LLVMRustLinkage::ExternalLinkage;
1549 case LLVMAvailableExternallyLinkage:
1550 return LLVMRustLinkage::AvailableExternallyLinkage;
1551 case LLVMLinkOnceAnyLinkage:
1552 return LLVMRustLinkage::LinkOnceAnyLinkage;
1553 case LLVMLinkOnceODRLinkage:
1554 return LLVMRustLinkage::LinkOnceODRLinkage;
1555 case LLVMWeakAnyLinkage:
1556 return LLVMRustLinkage::WeakAnyLinkage;
1557 case LLVMWeakODRLinkage:
1558 return LLVMRustLinkage::WeakODRLinkage;
1559 case LLVMAppendingLinkage:
1560 return LLVMRustLinkage::AppendingLinkage;
1561 case LLVMInternalLinkage:
1562 return LLVMRustLinkage::InternalLinkage;
1563 case LLVMPrivateLinkage:
1564 return LLVMRustLinkage::PrivateLinkage;
1565 case LLVMExternalWeakLinkage:
1566 return LLVMRustLinkage::ExternalWeakLinkage;
1567 case LLVMCommonLinkage:
1568 return LLVMRustLinkage::CommonLinkage;
1570 report_fatal_error("Invalid LLVMRustLinkage value!");
1574 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1576 case LLVMRustLinkage::ExternalLinkage:
1577 return LLVMExternalLinkage;
1578 case LLVMRustLinkage::AvailableExternallyLinkage:
1579 return LLVMAvailableExternallyLinkage;
1580 case LLVMRustLinkage::LinkOnceAnyLinkage:
1581 return LLVMLinkOnceAnyLinkage;
1582 case LLVMRustLinkage::LinkOnceODRLinkage:
1583 return LLVMLinkOnceODRLinkage;
1584 case LLVMRustLinkage::WeakAnyLinkage:
1585 return LLVMWeakAnyLinkage;
1586 case LLVMRustLinkage::WeakODRLinkage:
1587 return LLVMWeakODRLinkage;
1588 case LLVMRustLinkage::AppendingLinkage:
1589 return LLVMAppendingLinkage;
1590 case LLVMRustLinkage::InternalLinkage:
1591 return LLVMInternalLinkage;
1592 case LLVMRustLinkage::PrivateLinkage:
1593 return LLVMPrivateLinkage;
1594 case LLVMRustLinkage::ExternalWeakLinkage:
1595 return LLVMExternalWeakLinkage;
1596 case LLVMRustLinkage::CommonLinkage:
1597 return LLVMCommonLinkage;
1599 report_fatal_error("Invalid LLVMRustLinkage value!");
1602 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1603 return toRust(LLVMGetLinkage(V));
1606 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1607 LLVMRustLinkage RustLinkage) {
1608 LLVMSetLinkage(V, fromRust(RustLinkage));
1611 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1612 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1613 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1615 auto C = unwrap<llvm::ConstantInt>(CV);
1616 if (C->getBitWidth() > 128) { return false; }
1619 AP = C->getValue().sextOrSelf(128);
1621 AP = C->getValue().zextOrSelf(128);
1623 *low = AP.getLoBits(64).getZExtValue();
1624 *high = AP.getHiBits(64).getZExtValue();
1628 enum class LLVMRustVisibility {
1634 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1636 case LLVMDefaultVisibility:
1637 return LLVMRustVisibility::Default;
1638 case LLVMHiddenVisibility:
1639 return LLVMRustVisibility::Hidden;
1640 case LLVMProtectedVisibility:
1641 return LLVMRustVisibility::Protected;
1643 report_fatal_error("Invalid LLVMRustVisibility value!");
1646 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1648 case LLVMRustVisibility::Default:
1649 return LLVMDefaultVisibility;
1650 case LLVMRustVisibility::Hidden:
1651 return LLVMHiddenVisibility;
1652 case LLVMRustVisibility::Protected:
1653 return LLVMProtectedVisibility;
1655 report_fatal_error("Invalid LLVMRustVisibility value!");
1658 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1659 return toRust(LLVMGetVisibility(V));
1662 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1663 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1664 LLVMTypeRef DestTy, bool isSigned) {
1665 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1668 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1669 LLVMRustVisibility RustVisibility) {
1670 LLVMSetVisibility(V, fromRust(RustVisibility));
1673 struct LLVMRustModuleBuffer {
1677 extern "C" LLVMRustModuleBuffer*
1678 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1679 #if LLVM_VERSION_GE(10, 0)
1680 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1682 auto Ret = llvm::make_unique<LLVMRustModuleBuffer>();
1685 raw_string_ostream OS(Ret->data);
1687 legacy::PassManager PM;
1688 PM.add(createBitcodeWriterPass(OS));
1692 return Ret.release();
1696 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1700 extern "C" const void*
1701 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1702 return Buffer->data.data();
1706 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1707 return Buffer->data.length();
1711 LLVMRustModuleCost(LLVMModuleRef M) {
1712 auto f = unwrap(M)->functions();
1713 return std::distance(std::begin(f), std::end(f));
1716 // Vector reductions:
1717 extern "C" LLVMValueRef
1718 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1719 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1721 extern "C" LLVMValueRef
1722 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1723 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1725 extern "C" LLVMValueRef
1726 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1727 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1729 extern "C" LLVMValueRef
1730 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1731 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1733 extern "C" LLVMValueRef
1734 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1735 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1737 extern "C" LLVMValueRef
1738 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1739 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1741 extern "C" LLVMValueRef
1742 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1743 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1745 extern "C" LLVMValueRef
1746 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1747 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1749 extern "C" LLVMValueRef
1750 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1751 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1753 extern "C" LLVMValueRef
1754 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1755 #if LLVM_VERSION_GE(12, 0)
1756 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1757 I->setHasNoNaNs(NoNaN);
1760 return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN));
1763 extern "C" LLVMValueRef
1764 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1765 #if LLVM_VERSION_GE(12, 0)
1766 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1767 I->setHasNoNaNs(NoNaN);
1770 return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN));
1774 extern "C" LLVMValueRef
1775 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1776 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1778 extern "C" LLVMValueRef
1779 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1780 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));