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 a fast-math flag
354 // https://llvm.org/docs/LangRef.html#fast-math-flags
355 extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
356 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
361 extern "C" LLVMValueRef
362 LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef Source, const char *Name,
363 LLVMAtomicOrdering Order) {
364 Value *Ptr = unwrap(Source);
365 Type *Ty = Ptr->getType()->getPointerElementType();
366 LoadInst *LI = unwrap(B)->CreateLoad(Ty, Ptr, Name);
367 LI->setAtomic(fromRust(Order));
371 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
374 LLVMAtomicOrdering Order) {
375 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
376 SI->setAtomic(fromRust(Order));
380 // FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
381 // once we raise our minimum support to LLVM 10.
382 extern "C" LLVMValueRef
383 LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
384 LLVMValueRef Old, LLVMValueRef Source,
385 LLVMAtomicOrdering Order,
386 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
387 #if LLVM_VERSION_GE(13,0)
388 // Rust probably knows the alignment of the target value and should be able to
389 // specify something more precise than MaybeAlign here. See also
390 // https://reviews.llvm.org/D97224 which may be a useful reference.
391 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
392 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
393 fromRust(FailureOrder));
395 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
396 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
397 fromRust(FailureOrder));
403 enum class LLVMRustSynchronizationScope {
408 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
410 case LLVMRustSynchronizationScope::SingleThread:
411 return SyncScope::SingleThread;
412 case LLVMRustSynchronizationScope::CrossThread:
413 return SyncScope::System;
415 report_fatal_error("bad SynchronizationScope.");
419 extern "C" LLVMValueRef
420 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
421 LLVMRustSynchronizationScope Scope) {
422 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
425 enum class LLVMRustAsmDialect {
430 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
432 case LLVMRustAsmDialect::Att:
433 return InlineAsm::AD_ATT;
434 case LLVMRustAsmDialect::Intel:
435 return InlineAsm::AD_Intel;
437 report_fatal_error("bad AsmDialect.");
441 extern "C" LLVMValueRef
442 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
443 char *Constraints, size_t ConstraintsLen,
444 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
445 LLVMRustAsmDialect Dialect) {
446 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
447 StringRef(AsmString, AsmStringLen),
448 StringRef(Constraints, ConstraintsLen),
449 HasSideEffects, IsAlignStack, fromRust(Dialect)));
452 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
453 size_t ConstraintsLen) {
454 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
455 StringRef(Constraints, ConstraintsLen));
458 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
460 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
463 typedef DIBuilder *LLVMRustDIBuilderRef;
465 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
466 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
469 #define DIDescriptor DIScope
470 #define DIArray DINodeArray
471 #define unwrapDI unwrapDIPtr
473 // These values **must** match debuginfo::DIFlags! They also *happen*
474 // to match LLVM, but that isn't required as we do giant sets of
475 // matching below. The value shouldn't be directly passed to LLVM.
476 enum class LLVMRustDIFlags : uint32_t {
481 FlagFwdDecl = (1 << 2),
482 FlagAppleBlock = (1 << 3),
483 FlagBlockByrefStruct = (1 << 4),
484 FlagVirtual = (1 << 5),
485 FlagArtificial = (1 << 6),
486 FlagExplicit = (1 << 7),
487 FlagPrototyped = (1 << 8),
488 FlagObjcClassComplete = (1 << 9),
489 FlagObjectPointer = (1 << 10),
490 FlagVector = (1 << 11),
491 FlagStaticMember = (1 << 12),
492 FlagLValueReference = (1 << 13),
493 FlagRValueReference = (1 << 14),
494 FlagExternalTypeRef = (1 << 15),
495 FlagIntroducedVirtual = (1 << 18),
496 FlagBitField = (1 << 19),
497 FlagNoReturn = (1 << 20),
498 // Do not add values that are not supported by the minimum LLVM
499 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
502 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
503 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
504 static_cast<uint32_t>(B));
507 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
508 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
509 static_cast<uint32_t>(B));
512 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
516 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
518 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
519 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
522 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
523 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
525 switch (visibility(Flags)) {
526 case LLVMRustDIFlags::FlagPrivate:
527 Result |= DINode::DIFlags::FlagPrivate;
529 case LLVMRustDIFlags::FlagProtected:
530 Result |= DINode::DIFlags::FlagProtected;
532 case LLVMRustDIFlags::FlagPublic:
533 Result |= DINode::DIFlags::FlagPublic;
536 // The rest are handled below
540 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
541 Result |= DINode::DIFlags::FlagFwdDecl;
543 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
544 Result |= DINode::DIFlags::FlagAppleBlock;
546 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
547 Result |= DINode::DIFlags::FlagVirtual;
549 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
550 Result |= DINode::DIFlags::FlagArtificial;
552 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
553 Result |= DINode::DIFlags::FlagExplicit;
555 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
556 Result |= DINode::DIFlags::FlagPrototyped;
558 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
559 Result |= DINode::DIFlags::FlagObjcClassComplete;
561 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
562 Result |= DINode::DIFlags::FlagObjectPointer;
564 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
565 Result |= DINode::DIFlags::FlagVector;
567 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
568 Result |= DINode::DIFlags::FlagStaticMember;
570 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
571 Result |= DINode::DIFlags::FlagLValueReference;
573 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
574 Result |= DINode::DIFlags::FlagRValueReference;
576 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
577 Result |= DINode::DIFlags::FlagIntroducedVirtual;
579 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
580 Result |= DINode::DIFlags::FlagBitField;
582 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
583 Result |= DINode::DIFlags::FlagNoReturn;
589 // These values **must** match debuginfo::DISPFlags! They also *happen*
590 // to match LLVM, but that isn't required as we do giant sets of
591 // matching below. The value shouldn't be directly passed to LLVM.
592 enum class LLVMRustDISPFlags : uint32_t {
595 SPFlagPureVirtual = 2,
596 SPFlagLocalToUnit = (1 << 2),
597 SPFlagDefinition = (1 << 3),
598 SPFlagOptimized = (1 << 4),
599 SPFlagMainSubprogram = (1 << 5),
600 // Do not add values that are not supported by the minimum LLVM
601 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
602 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
605 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
606 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
607 static_cast<uint32_t>(B));
610 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
611 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
612 static_cast<uint32_t>(B));
615 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
619 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
621 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
622 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
625 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
626 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
628 switch (virtuality(SPFlags)) {
629 case LLVMRustDISPFlags::SPFlagVirtual:
630 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
632 case LLVMRustDISPFlags::SPFlagPureVirtual:
633 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
636 // The rest are handled below
640 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
641 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
643 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
644 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
646 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
647 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
649 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
650 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
656 enum class LLVMRustDebugEmissionKind {
662 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
664 case LLVMRustDebugEmissionKind::NoDebug:
665 return DICompileUnit::DebugEmissionKind::NoDebug;
666 case LLVMRustDebugEmissionKind::FullDebug:
667 return DICompileUnit::DebugEmissionKind::FullDebug;
668 case LLVMRustDebugEmissionKind::LineTablesOnly:
669 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
671 report_fatal_error("bad DebugEmissionKind.");
675 enum class LLVMRustChecksumKind {
682 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
684 case LLVMRustChecksumKind::None:
686 case LLVMRustChecksumKind::MD5:
687 return DIFile::ChecksumKind::CSK_MD5;
688 case LLVMRustChecksumKind::SHA1:
689 return DIFile::ChecksumKind::CSK_SHA1;
690 #if (LLVM_VERSION_MAJOR >= 11)
691 case LLVMRustChecksumKind::SHA256:
692 return DIFile::ChecksumKind::CSK_SHA256;
695 report_fatal_error("bad ChecksumKind.");
699 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
700 return DEBUG_METADATA_VERSION;
703 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
705 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
707 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
709 extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
711 unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
714 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
715 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
718 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
719 return new DIBuilder(*unwrap(M));
722 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
726 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
730 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
731 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
732 const char *Producer, size_t ProducerLen, bool isOptimized,
733 const char *Flags, unsigned RuntimeVer,
734 const char *SplitName, size_t SplitNameLen,
735 LLVMRustDebugEmissionKind Kind,
736 uint64_t DWOId, bool SplitDebugInlining) {
737 auto *File = unwrapDI<DIFile>(FileRef);
739 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
740 isOptimized, Flags, RuntimeVer,
741 StringRef(SplitName, SplitNameLen),
742 fromRust(Kind), DWOId, SplitDebugInlining));
745 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
746 LLVMRustDIBuilderRef Builder,
747 const char *Filename, size_t FilenameLen,
748 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
749 const char *Checksum, size_t ChecksumLen) {
750 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
751 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
753 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
754 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
755 StringRef(Directory, DirectoryLen),
759 extern "C" LLVMMetadataRef
760 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
761 LLVMMetadataRef ParameterTypes) {
762 return wrap(Builder->createSubroutineType(
763 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
766 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
767 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
768 const char *Name, size_t NameLen,
769 const char *LinkageName, size_t LinkageNameLen,
770 LLVMMetadataRef File, unsigned LineNo,
771 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
772 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
773 LLVMMetadataRef Decl) {
774 DITemplateParameterArray TParams =
775 DITemplateParameterArray(unwrap<MDTuple>(TParam));
776 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
777 DINode::DIFlags llvmFlags = fromRust(Flags);
778 DISubprogram *Sub = Builder->createFunction(
779 unwrapDI<DIScope>(Scope),
780 StringRef(Name, NameLen),
781 StringRef(LinkageName, LinkageNameLen),
782 unwrapDI<DIFile>(File), LineNo,
783 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
784 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
786 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
790 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
791 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
792 uint64_t SizeInBits, unsigned Encoding) {
793 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
796 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
797 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
798 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
799 return wrap(Builder->createTypedef(
800 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
801 LineNo, unwrapDIPtr<DIScope>(Scope)));
804 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
805 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
806 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
807 const char *Name, size_t NameLen) {
808 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
809 SizeInBits, AlignInBits,
811 StringRef(Name, NameLen)));
814 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
815 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
816 const char *Name, size_t NameLen,
817 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
818 uint32_t AlignInBits, LLVMRustDIFlags Flags,
819 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
820 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
821 const char *UniqueId, size_t UniqueIdLen) {
822 return wrap(Builder->createStructType(
823 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
824 unwrapDI<DIFile>(File), LineNumber,
825 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
826 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
827 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
830 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
831 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
832 const char *Name, size_t NameLen,
833 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
834 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
835 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
836 return wrap(Builder->createVariantPart(
837 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
838 unwrapDI<DIFile>(File), LineNumber,
839 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
840 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
843 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
844 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
845 const char *Name, size_t NameLen,
846 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
847 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
848 LLVMMetadataRef Ty) {
849 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
850 StringRef(Name, NameLen),
851 unwrapDI<DIFile>(File), LineNo,
852 SizeInBits, AlignInBits, OffsetInBits,
853 fromRust(Flags), unwrapDI<DIType>(Ty)));
856 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
857 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
858 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
859 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
860 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
861 llvm::ConstantInt* D = nullptr;
863 D = unwrap<llvm::ConstantInt>(Discriminant);
865 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
866 StringRef(Name, NameLen),
867 unwrapDI<DIFile>(File), LineNo,
868 SizeInBits, AlignInBits, OffsetInBits, D,
869 fromRust(Flags), unwrapDI<DIType>(Ty)));
872 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
873 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
874 LLVMMetadataRef File, unsigned Line, unsigned Col) {
875 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
876 unwrapDI<DIFile>(File), Line, Col));
879 extern "C" LLVMMetadataRef
880 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
881 LLVMMetadataRef Scope,
882 LLVMMetadataRef File) {
883 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
884 unwrapDI<DIFile>(File)));
887 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
888 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
889 const char *Name, size_t NameLen,
890 const char *LinkageName, size_t LinkageNameLen,
891 LLVMMetadataRef File, unsigned LineNo,
892 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
893 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
894 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
896 llvm::DIExpression *InitExpr = nullptr;
897 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
898 InitExpr = Builder->createConstantValueExpression(
899 IntVal->getValue().getSExtValue());
900 } else if (llvm::ConstantFP *FPVal =
901 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
902 InitExpr = Builder->createConstantValueExpression(
903 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
906 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
907 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
908 StringRef(LinkageName, LinkageNameLen),
909 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
910 /* isDefined */ true,
911 InitExpr, unwrapDIPtr<MDNode>(Decl),
912 /* templateParams */ nullptr,
915 InitVal->setMetadata("dbg", VarExpr);
917 return wrap(VarExpr);
920 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
921 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
922 const char *Name, size_t NameLen,
923 LLVMMetadataRef File, unsigned LineNo,
924 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
925 unsigned ArgNo, uint32_t AlignInBits) {
926 if (Tag == 0x100) { // DW_TAG_auto_variable
927 return wrap(Builder->createAutoVariable(
928 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
929 unwrapDI<DIFile>(File), LineNo,
930 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
932 return wrap(Builder->createParameterVariable(
933 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
934 unwrapDI<DIFile>(File), LineNo,
935 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
939 extern "C" LLVMMetadataRef
940 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
941 uint32_t AlignInBits, LLVMMetadataRef Ty,
942 LLVMMetadataRef Subscripts) {
944 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
945 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
948 extern "C" LLVMMetadataRef
949 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
951 return wrap(Builder->getOrCreateSubrange(Lo, Count));
954 extern "C" LLVMMetadataRef
955 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
956 LLVMMetadataRef *Ptr, unsigned Count) {
957 Metadata **DataValue = unwrap(Ptr);
959 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
962 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
963 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
964 int64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
965 LLVMBasicBlockRef InsertAtEnd) {
966 return wrap(Builder->insertDeclare(
967 unwrap(V), unwrap<DILocalVariable>(VarInfo),
968 Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
969 DebugLoc(cast<MDNode>(unwrap(DL))),
970 unwrap(InsertAtEnd)));
973 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
974 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
975 int64_t Value, bool IsUnsigned) {
976 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
979 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
980 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
981 const char *Name, size_t NameLen,
982 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
983 uint32_t AlignInBits, LLVMMetadataRef Elements,
984 LLVMMetadataRef ClassTy, bool IsScoped) {
985 return wrap(Builder->createEnumerationType(
986 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
987 unwrapDI<DIFile>(File), LineNumber,
988 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
989 unwrapDI<DIType>(ClassTy), "", IsScoped));
992 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
993 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
994 const char *Name, size_t NameLen,
995 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
996 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
997 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
998 return wrap(Builder->createUnionType(
999 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1000 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1001 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1002 StringRef(UniqueId, UniqueIdLen)));
1005 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1006 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1007 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1008 #if LLVM_VERSION_GE(11, 0)
1009 bool IsDefault = false; // FIXME: should we ever set this true?
1010 return wrap(Builder->createTemplateTypeParameter(
1011 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1013 return wrap(Builder->createTemplateTypeParameter(
1014 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty)));
1018 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1019 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1020 const char *Name, size_t NameLen, bool ExportSymbols) {
1021 return wrap(Builder->createNameSpace(
1022 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1027 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1028 LLVMMetadataRef CompositeTy,
1029 LLVMMetadataRef Elements,
1030 LLVMMetadataRef Params) {
1031 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1032 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1033 DINodeArray(unwrap<MDTuple>(Params)));
1036 extern "C" LLVMMetadataRef
1037 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1038 LLVMMetadataRef ScopeRef,
1039 LLVMMetadataRef InlinedAt) {
1040 #if LLVM_VERSION_GE(12, 0)
1041 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1042 DILocation *Loc = DILocation::get(
1043 Scope->getContext(), Line, Column, Scope,
1044 unwrapDIPtr<MDNode>(InlinedAt));
1047 DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(ScopeRef),
1048 unwrapDIPtr<MDNode>(InlinedAt));
1049 return wrap(debug_loc.getAsMDNode());
1053 extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {
1054 return dwarf::DW_OP_deref;
1057 extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1058 return dwarf::DW_OP_plus_uconst;
1061 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1062 RawRustStringOstream OS(Str);
1063 unwrap<llvm::Type>(Ty)->print(OS);
1066 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1067 RustStringRef Str) {
1068 RawRustStringOstream OS(Str);
1073 unwrap<llvm::Value>(V)->getType()->print(OS);
1075 unwrap<llvm::Value>(V)->print(OS);
1080 // Note that the two following functions look quite similar to the
1081 // LLVMGetSectionName function. Sadly, it appears that this function only
1082 // returns a char* pointer, which isn't guaranteed to be null-terminated. The
1083 // function provided by LLVM doesn't return the length, so we've created our own
1084 // function which returns the length as well as the data pointer.
1086 // For an example of this not returning a null terminated string, see
1087 // lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the
1088 // branches explicitly creates a StringRef without a null terminator, and then
1091 inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
1092 return reinterpret_cast<section_iterator *>(SI);
1095 extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI,
1097 auto NameOrErr = (*unwrap(SI))->getName();
1099 report_fatal_error(NameOrErr.takeError());
1100 *Ptr = NameOrErr->data();
1101 return NameOrErr->size();
1104 // LLVMArrayType function does not support 64-bit ElementCount
1105 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1106 uint64_t ElementCount) {
1107 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1110 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1112 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1113 RawRustStringOstream OS(Str);
1114 unwrap(T)->print(OS);
1117 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1118 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1119 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1120 RustStringRef FilenameOut, RustStringRef MessageOut) {
1121 // Undefined to call this not on an optimization diagnostic!
1122 llvm::DiagnosticInfoOptimizationBase *Opt =
1123 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1125 RawRustStringOstream PassNameOS(PassNameOut);
1126 PassNameOS << Opt->getPassName();
1127 *FunctionOut = wrap(&Opt->getFunction());
1129 RawRustStringOstream FilenameOS(FilenameOut);
1130 DiagnosticLocation loc = Opt->getLocation();
1131 if (loc.isValid()) {
1132 *Line = loc.getLine();
1133 *Column = loc.getColumn();
1134 FilenameOS << loc.getAbsolutePath();
1137 RawRustStringOstream MessageOS(MessageOut);
1138 MessageOS << Opt->getMsg();
1141 enum class LLVMRustDiagnosticLevel {
1149 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1150 LLVMRustDiagnosticLevel *LevelOut,
1151 unsigned *CookieOut,
1152 LLVMTwineRef *MessageOut,
1153 LLVMValueRef *InstructionOut) {
1154 // Undefined to call this not on an inline assembly diagnostic!
1155 llvm::DiagnosticInfoInlineAsm *IA =
1156 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1158 *CookieOut = IA->getLocCookie();
1159 *MessageOut = wrap(&IA->getMsgStr());
1160 *InstructionOut = wrap(IA->getInstruction());
1162 switch (IA->getSeverity()) {
1164 *LevelOut = LLVMRustDiagnosticLevel::Error;
1167 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1170 *LevelOut = LLVMRustDiagnosticLevel::Note;
1173 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1176 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1180 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1181 RustStringRef Str) {
1182 RawRustStringOstream OS(Str);
1183 DiagnosticPrinterRawOStream DP(OS);
1184 unwrap(DI)->print(DP);
1187 enum class LLVMRustDiagnosticKind {
1191 DebugMetadataVersion,
1194 OptimizationRemarkMissed,
1195 OptimizationRemarkAnalysis,
1196 OptimizationRemarkAnalysisFPCommute,
1197 OptimizationRemarkAnalysisAliasing,
1198 OptimizationRemarkOther,
1199 OptimizationFailure,
1205 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1208 return LLVMRustDiagnosticKind::InlineAsm;
1210 return LLVMRustDiagnosticKind::StackSize;
1211 case DK_DebugMetadataVersion:
1212 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1213 case DK_SampleProfile:
1214 return LLVMRustDiagnosticKind::SampleProfile;
1215 case DK_OptimizationRemark:
1216 return LLVMRustDiagnosticKind::OptimizationRemark;
1217 case DK_OptimizationRemarkMissed:
1218 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1219 case DK_OptimizationRemarkAnalysis:
1220 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1221 case DK_OptimizationRemarkAnalysisFPCommute:
1222 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1223 case DK_OptimizationRemarkAnalysisAliasing:
1224 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1226 return LLVMRustDiagnosticKind::PGOProfile;
1228 return LLVMRustDiagnosticKind::Linker;
1229 case DK_Unsupported:
1230 return LLVMRustDiagnosticKind::Unsupported;
1232 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1233 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1234 : LLVMRustDiagnosticKind::Other;
1238 extern "C" LLVMRustDiagnosticKind
1239 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1240 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1243 // This is kept distinct from LLVMGetTypeKind, because when
1244 // a new type kind is added, the Rust-side enum must be
1245 // updated or UB will result.
1246 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1247 switch (unwrap(Ty)->getTypeID()) {
1248 case Type::VoidTyID:
1249 return LLVMVoidTypeKind;
1250 case Type::HalfTyID:
1251 return LLVMHalfTypeKind;
1252 case Type::FloatTyID:
1253 return LLVMFloatTypeKind;
1254 case Type::DoubleTyID:
1255 return LLVMDoubleTypeKind;
1256 case Type::X86_FP80TyID:
1257 return LLVMX86_FP80TypeKind;
1258 case Type::FP128TyID:
1259 return LLVMFP128TypeKind;
1260 case Type::PPC_FP128TyID:
1261 return LLVMPPC_FP128TypeKind;
1262 case Type::LabelTyID:
1263 return LLVMLabelTypeKind;
1264 case Type::MetadataTyID:
1265 return LLVMMetadataTypeKind;
1266 case Type::IntegerTyID:
1267 return LLVMIntegerTypeKind;
1268 case Type::FunctionTyID:
1269 return LLVMFunctionTypeKind;
1270 case Type::StructTyID:
1271 return LLVMStructTypeKind;
1272 case Type::ArrayTyID:
1273 return LLVMArrayTypeKind;
1274 case Type::PointerTyID:
1275 return LLVMPointerTypeKind;
1276 #if LLVM_VERSION_GE(11, 0)
1277 case Type::FixedVectorTyID:
1278 return LLVMVectorTypeKind;
1280 case Type::VectorTyID:
1281 return LLVMVectorTypeKind;
1283 case Type::X86_MMXTyID:
1284 return LLVMX86_MMXTypeKind;
1285 case Type::TokenTyID:
1286 return LLVMTokenTypeKind;
1287 #if LLVM_VERSION_GE(11, 0)
1288 case Type::ScalableVectorTyID:
1289 return LLVMScalableVectorTypeKind;
1290 case Type::BFloatTyID:
1291 return LLVMBFloatTypeKind;
1293 #if LLVM_VERSION_GE(12, 0)
1294 case Type::X86_AMXTyID:
1295 return LLVMX86_AMXTypeKind;
1298 report_fatal_error("Unhandled TypeID.");
1301 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1303 #if LLVM_VERSION_LT(13, 0)
1304 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1306 using LLVMInlineAsmDiagHandlerTy = void*;
1309 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1310 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1311 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1312 // with LLVM 13 this function is gone.
1313 #if LLVM_VERSION_LT(13, 0)
1314 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1318 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1319 RustStringRef MessageOut,
1320 RustStringRef BufferOut,
1321 LLVMRustDiagnosticLevel* LevelOut,
1323 unsigned* RangesOut,
1324 size_t* NumRanges) {
1325 SMDiagnostic& D = *unwrap(DRef);
1326 RawRustStringOstream MessageOS(MessageOut);
1327 MessageOS << D.getMessage();
1329 switch (D.getKind()) {
1330 case SourceMgr::DK_Error:
1331 *LevelOut = LLVMRustDiagnosticLevel::Error;
1333 case SourceMgr::DK_Warning:
1334 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1336 case SourceMgr::DK_Note:
1337 *LevelOut = LLVMRustDiagnosticLevel::Note;
1339 case SourceMgr::DK_Remark:
1340 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1343 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1346 if (D.getLoc() == SMLoc())
1349 const SourceMgr &LSM = *D.getSourceMgr();
1350 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1351 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1353 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1355 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1356 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1357 for (size_t i = 0; i < *NumRanges; i++) {
1358 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1359 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1365 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1366 LLVMValueRef ParentPad,
1368 LLVMValueRef *LLArgs,
1370 Value **Args = unwrap(LLArgs);
1371 if (ParentPad == nullptr) {
1372 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1373 ParentPad = wrap(Constant::getNullValue(Ty));
1375 return wrap(unwrap(B)->CreateCleanupPad(
1376 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1379 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1380 LLVMValueRef CleanupPad,
1381 LLVMBasicBlockRef UnwindBB) {
1382 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1383 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1386 extern "C" LLVMValueRef
1387 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1388 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1389 Value **Args = unwrap(LLArgs);
1390 return wrap(unwrap(B)->CreateCatchPad(
1391 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1394 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1396 LLVMBasicBlockRef BB) {
1397 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1401 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1402 LLVMValueRef ParentPad,
1403 LLVMBasicBlockRef BB,
1404 unsigned NumHandlers,
1406 if (ParentPad == nullptr) {
1407 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1408 ParentPad = wrap(Constant::getNullValue(Ty));
1410 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1411 NumHandlers, Name));
1414 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1415 LLVMBasicBlockRef Handler) {
1416 Value *CatchSwitch = unwrap(CatchSwitchRef);
1417 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1420 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1421 LLVMValueRef *Inputs,
1422 unsigned NumInputs) {
1423 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1426 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1430 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
1431 LLVMValueRef *Args, unsigned NumArgs,
1432 OperandBundleDef *Bundle) {
1433 Value *Callee = unwrap(Fn);
1434 FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType());
1435 unsigned Len = Bundle ? 1 : 0;
1436 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1437 return wrap(unwrap(B)->CreateCall(
1438 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1441 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1442 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1443 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1446 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1447 LLVMValueRef Dst, unsigned DstAlign,
1448 LLVMValueRef Src, unsigned SrcAlign,
1449 LLVMValueRef Size, bool IsVolatile) {
1450 return wrap(unwrap(B)->CreateMemCpy(
1451 unwrap(Dst), MaybeAlign(DstAlign),
1452 unwrap(Src), MaybeAlign(SrcAlign),
1453 unwrap(Size), IsVolatile));
1456 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1457 LLVMValueRef Dst, unsigned DstAlign,
1458 LLVMValueRef Src, unsigned SrcAlign,
1459 LLVMValueRef Size, bool IsVolatile) {
1460 return wrap(unwrap(B)->CreateMemMove(
1461 unwrap(Dst), MaybeAlign(DstAlign),
1462 unwrap(Src), MaybeAlign(SrcAlign),
1463 unwrap(Size), IsVolatile));
1466 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1467 LLVMValueRef Dst, unsigned DstAlign,
1469 LLVMValueRef Size, bool IsVolatile) {
1470 return wrap(unwrap(B)->CreateMemSet(
1471 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1474 extern "C" LLVMValueRef
1475 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
1476 unsigned NumArgs, LLVMBasicBlockRef Then,
1477 LLVMBasicBlockRef Catch, OperandBundleDef *Bundle,
1479 Value *Callee = unwrap(Fn);
1480 FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType());
1481 unsigned Len = Bundle ? 1 : 0;
1482 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1483 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1484 makeArrayRef(unwrap(Args), NumArgs),
1488 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1489 LLVMBasicBlockRef BB) {
1490 auto Point = unwrap(BB)->getFirstInsertionPt();
1491 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1494 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1495 const char *Name, size_t NameLen) {
1496 Triple TargetTriple(unwrap(M)->getTargetTriple());
1497 GlobalObject *GV = unwrap<GlobalObject>(V);
1498 if (TargetTriple.supportsCOMDAT()) {
1499 StringRef NameRef(Name, NameLen);
1500 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1504 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1505 GlobalObject *GV = unwrap<GlobalObject>(V);
1506 GV->setComdat(nullptr);
1509 enum class LLVMRustLinkage {
1510 ExternalLinkage = 0,
1511 AvailableExternallyLinkage = 1,
1512 LinkOnceAnyLinkage = 2,
1513 LinkOnceODRLinkage = 3,
1516 AppendingLinkage = 6,
1517 InternalLinkage = 7,
1519 ExternalWeakLinkage = 9,
1523 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1525 case LLVMExternalLinkage:
1526 return LLVMRustLinkage::ExternalLinkage;
1527 case LLVMAvailableExternallyLinkage:
1528 return LLVMRustLinkage::AvailableExternallyLinkage;
1529 case LLVMLinkOnceAnyLinkage:
1530 return LLVMRustLinkage::LinkOnceAnyLinkage;
1531 case LLVMLinkOnceODRLinkage:
1532 return LLVMRustLinkage::LinkOnceODRLinkage;
1533 case LLVMWeakAnyLinkage:
1534 return LLVMRustLinkage::WeakAnyLinkage;
1535 case LLVMWeakODRLinkage:
1536 return LLVMRustLinkage::WeakODRLinkage;
1537 case LLVMAppendingLinkage:
1538 return LLVMRustLinkage::AppendingLinkage;
1539 case LLVMInternalLinkage:
1540 return LLVMRustLinkage::InternalLinkage;
1541 case LLVMPrivateLinkage:
1542 return LLVMRustLinkage::PrivateLinkage;
1543 case LLVMExternalWeakLinkage:
1544 return LLVMRustLinkage::ExternalWeakLinkage;
1545 case LLVMCommonLinkage:
1546 return LLVMRustLinkage::CommonLinkage;
1548 report_fatal_error("Invalid LLVMRustLinkage value!");
1552 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1554 case LLVMRustLinkage::ExternalLinkage:
1555 return LLVMExternalLinkage;
1556 case LLVMRustLinkage::AvailableExternallyLinkage:
1557 return LLVMAvailableExternallyLinkage;
1558 case LLVMRustLinkage::LinkOnceAnyLinkage:
1559 return LLVMLinkOnceAnyLinkage;
1560 case LLVMRustLinkage::LinkOnceODRLinkage:
1561 return LLVMLinkOnceODRLinkage;
1562 case LLVMRustLinkage::WeakAnyLinkage:
1563 return LLVMWeakAnyLinkage;
1564 case LLVMRustLinkage::WeakODRLinkage:
1565 return LLVMWeakODRLinkage;
1566 case LLVMRustLinkage::AppendingLinkage:
1567 return LLVMAppendingLinkage;
1568 case LLVMRustLinkage::InternalLinkage:
1569 return LLVMInternalLinkage;
1570 case LLVMRustLinkage::PrivateLinkage:
1571 return LLVMPrivateLinkage;
1572 case LLVMRustLinkage::ExternalWeakLinkage:
1573 return LLVMExternalWeakLinkage;
1574 case LLVMRustLinkage::CommonLinkage:
1575 return LLVMCommonLinkage;
1577 report_fatal_error("Invalid LLVMRustLinkage value!");
1580 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1581 return toRust(LLVMGetLinkage(V));
1584 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1585 LLVMRustLinkage RustLinkage) {
1586 LLVMSetLinkage(V, fromRust(RustLinkage));
1589 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1590 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1591 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1593 auto C = unwrap<llvm::ConstantInt>(CV);
1594 if (C->getBitWidth() > 128) { return false; }
1597 AP = C->getValue().sextOrSelf(128);
1599 AP = C->getValue().zextOrSelf(128);
1601 *low = AP.getLoBits(64).getZExtValue();
1602 *high = AP.getHiBits(64).getZExtValue();
1606 enum class LLVMRustVisibility {
1612 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1614 case LLVMDefaultVisibility:
1615 return LLVMRustVisibility::Default;
1616 case LLVMHiddenVisibility:
1617 return LLVMRustVisibility::Hidden;
1618 case LLVMProtectedVisibility:
1619 return LLVMRustVisibility::Protected;
1621 report_fatal_error("Invalid LLVMRustVisibility value!");
1624 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1626 case LLVMRustVisibility::Default:
1627 return LLVMDefaultVisibility;
1628 case LLVMRustVisibility::Hidden:
1629 return LLVMHiddenVisibility;
1630 case LLVMRustVisibility::Protected:
1631 return LLVMProtectedVisibility;
1633 report_fatal_error("Invalid LLVMRustVisibility value!");
1636 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1637 return toRust(LLVMGetVisibility(V));
1640 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1641 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1642 LLVMTypeRef DestTy, bool isSigned) {
1643 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1646 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1647 LLVMRustVisibility RustVisibility) {
1648 LLVMSetVisibility(V, fromRust(RustVisibility));
1651 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1652 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1655 struct LLVMRustModuleBuffer {
1659 extern "C" LLVMRustModuleBuffer*
1660 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1661 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1663 raw_string_ostream OS(Ret->data);
1665 legacy::PassManager PM;
1666 PM.add(createBitcodeWriterPass(OS));
1670 return Ret.release();
1674 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1678 extern "C" const void*
1679 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1680 return Buffer->data.data();
1684 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1685 return Buffer->data.length();
1689 LLVMRustModuleCost(LLVMModuleRef M) {
1690 auto f = unwrap(M)->functions();
1691 return std::distance(std::begin(f), std::end(f));
1694 // Vector reductions:
1695 extern "C" LLVMValueRef
1696 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1697 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1699 extern "C" LLVMValueRef
1700 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1701 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1703 extern "C" LLVMValueRef
1704 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1705 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1707 extern "C" LLVMValueRef
1708 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1709 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1711 extern "C" LLVMValueRef
1712 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1713 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1715 extern "C" LLVMValueRef
1716 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1717 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1719 extern "C" LLVMValueRef
1720 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1721 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1723 extern "C" LLVMValueRef
1724 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1725 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1727 extern "C" LLVMValueRef
1728 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1729 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1731 extern "C" LLVMValueRef
1732 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1733 #if LLVM_VERSION_GE(12, 0)
1734 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1735 I->setHasNoNaNs(NoNaN);
1738 return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN));
1741 extern "C" LLVMValueRef
1742 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1743 #if LLVM_VERSION_GE(12, 0)
1744 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1745 I->setHasNoNaNs(NoNaN);
1748 return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN));
1752 extern "C" LLVMValueRef
1753 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1754 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1756 extern "C" LLVMValueRef
1757 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1758 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));