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 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
386 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
387 fromRust(FailureOrder));
392 enum class LLVMRustSynchronizationScope {
397 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
399 case LLVMRustSynchronizationScope::SingleThread:
400 return SyncScope::SingleThread;
401 case LLVMRustSynchronizationScope::CrossThread:
402 return SyncScope::System;
404 report_fatal_error("bad SynchronizationScope.");
408 extern "C" LLVMValueRef
409 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
410 LLVMRustSynchronizationScope Scope) {
411 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
414 enum class LLVMRustAsmDialect {
419 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
421 case LLVMRustAsmDialect::Att:
422 return InlineAsm::AD_ATT;
423 case LLVMRustAsmDialect::Intel:
424 return InlineAsm::AD_Intel;
426 report_fatal_error("bad AsmDialect.");
430 extern "C" LLVMValueRef
431 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
432 char *Constraints, size_t ConstraintsLen,
433 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
434 LLVMRustAsmDialect Dialect) {
435 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
436 StringRef(AsmString, AsmStringLen),
437 StringRef(Constraints, ConstraintsLen),
438 HasSideEffects, IsAlignStack, fromRust(Dialect)));
441 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
442 size_t ConstraintsLen) {
443 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
444 StringRef(Constraints, ConstraintsLen));
447 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
449 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
452 typedef DIBuilder *LLVMRustDIBuilderRef;
454 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
455 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
458 #define DIDescriptor DIScope
459 #define DIArray DINodeArray
460 #define unwrapDI unwrapDIPtr
462 // These values **must** match debuginfo::DIFlags! They also *happen*
463 // to match LLVM, but that isn't required as we do giant sets of
464 // matching below. The value shouldn't be directly passed to LLVM.
465 enum class LLVMRustDIFlags : uint32_t {
470 FlagFwdDecl = (1 << 2),
471 FlagAppleBlock = (1 << 3),
472 FlagBlockByrefStruct = (1 << 4),
473 FlagVirtual = (1 << 5),
474 FlagArtificial = (1 << 6),
475 FlagExplicit = (1 << 7),
476 FlagPrototyped = (1 << 8),
477 FlagObjcClassComplete = (1 << 9),
478 FlagObjectPointer = (1 << 10),
479 FlagVector = (1 << 11),
480 FlagStaticMember = (1 << 12),
481 FlagLValueReference = (1 << 13),
482 FlagRValueReference = (1 << 14),
483 FlagExternalTypeRef = (1 << 15),
484 FlagIntroducedVirtual = (1 << 18),
485 FlagBitField = (1 << 19),
486 FlagNoReturn = (1 << 20),
487 // Do not add values that are not supported by the minimum LLVM
488 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
491 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
492 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
493 static_cast<uint32_t>(B));
496 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
497 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
498 static_cast<uint32_t>(B));
501 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
505 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
507 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
508 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
511 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
512 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
514 switch (visibility(Flags)) {
515 case LLVMRustDIFlags::FlagPrivate:
516 Result |= DINode::DIFlags::FlagPrivate;
518 case LLVMRustDIFlags::FlagProtected:
519 Result |= DINode::DIFlags::FlagProtected;
521 case LLVMRustDIFlags::FlagPublic:
522 Result |= DINode::DIFlags::FlagPublic;
525 // The rest are handled below
529 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
530 Result |= DINode::DIFlags::FlagFwdDecl;
532 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
533 Result |= DINode::DIFlags::FlagAppleBlock;
535 #if LLVM_VERSION_LT(10, 0)
536 if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) {
537 Result |= DINode::DIFlags::FlagBlockByrefStruct;
540 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
541 Result |= DINode::DIFlags::FlagVirtual;
543 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
544 Result |= DINode::DIFlags::FlagArtificial;
546 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
547 Result |= DINode::DIFlags::FlagExplicit;
549 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
550 Result |= DINode::DIFlags::FlagPrototyped;
552 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
553 Result |= DINode::DIFlags::FlagObjcClassComplete;
555 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
556 Result |= DINode::DIFlags::FlagObjectPointer;
558 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
559 Result |= DINode::DIFlags::FlagVector;
561 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
562 Result |= DINode::DIFlags::FlagStaticMember;
564 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
565 Result |= DINode::DIFlags::FlagLValueReference;
567 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
568 Result |= DINode::DIFlags::FlagRValueReference;
570 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
571 Result |= DINode::DIFlags::FlagIntroducedVirtual;
573 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
574 Result |= DINode::DIFlags::FlagBitField;
576 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
577 Result |= DINode::DIFlags::FlagNoReturn;
583 // These values **must** match debuginfo::DISPFlags! They also *happen*
584 // to match LLVM, but that isn't required as we do giant sets of
585 // matching below. The value shouldn't be directly passed to LLVM.
586 enum class LLVMRustDISPFlags : uint32_t {
589 SPFlagPureVirtual = 2,
590 SPFlagLocalToUnit = (1 << 2),
591 SPFlagDefinition = (1 << 3),
592 SPFlagOptimized = (1 << 4),
593 SPFlagMainSubprogram = (1 << 5),
594 // Do not add values that are not supported by the minimum LLVM
595 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
596 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
599 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
600 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
601 static_cast<uint32_t>(B));
604 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
605 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
606 static_cast<uint32_t>(B));
609 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
613 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
615 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
616 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
619 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
620 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
622 switch (virtuality(SPFlags)) {
623 case LLVMRustDISPFlags::SPFlagVirtual:
624 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
626 case LLVMRustDISPFlags::SPFlagPureVirtual:
627 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
630 // The rest are handled below
634 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
635 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
637 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
638 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
640 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
641 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
643 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
644 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
650 enum class LLVMRustDebugEmissionKind {
656 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
658 case LLVMRustDebugEmissionKind::NoDebug:
659 return DICompileUnit::DebugEmissionKind::NoDebug;
660 case LLVMRustDebugEmissionKind::FullDebug:
661 return DICompileUnit::DebugEmissionKind::FullDebug;
662 case LLVMRustDebugEmissionKind::LineTablesOnly:
663 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
665 report_fatal_error("bad DebugEmissionKind.");
669 enum class LLVMRustChecksumKind {
676 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
678 case LLVMRustChecksumKind::None:
680 case LLVMRustChecksumKind::MD5:
681 return DIFile::ChecksumKind::CSK_MD5;
682 case LLVMRustChecksumKind::SHA1:
683 return DIFile::ChecksumKind::CSK_SHA1;
684 #if (LLVM_VERSION_MAJOR >= 11)
685 case LLVMRustChecksumKind::SHA256:
686 return DIFile::ChecksumKind::CSK_SHA256;
689 report_fatal_error("bad ChecksumKind.");
693 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
694 return DEBUG_METADATA_VERSION;
697 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
699 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
701 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
703 extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
705 unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
708 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
709 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
712 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
713 return new DIBuilder(*unwrap(M));
716 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
720 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
724 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
725 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
726 const char *Producer, size_t ProducerLen, bool isOptimized,
727 const char *Flags, unsigned RuntimeVer,
728 const char *SplitName, size_t SplitNameLen,
729 LLVMRustDebugEmissionKind Kind,
730 uint64_t DWOId, bool SplitDebugInlining) {
731 auto *File = unwrapDI<DIFile>(FileRef);
733 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
734 isOptimized, Flags, RuntimeVer,
735 StringRef(SplitName, SplitNameLen),
736 fromRust(Kind), DWOId, SplitDebugInlining));
739 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
740 LLVMRustDIBuilderRef Builder,
741 const char *Filename, size_t FilenameLen,
742 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
743 const char *Checksum, size_t ChecksumLen) {
744 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
745 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
747 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
748 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
749 StringRef(Directory, DirectoryLen),
753 extern "C" LLVMMetadataRef
754 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
755 LLVMMetadataRef ParameterTypes) {
756 return wrap(Builder->createSubroutineType(
757 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
760 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
761 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
762 const char *Name, size_t NameLen,
763 const char *LinkageName, size_t LinkageNameLen,
764 LLVMMetadataRef File, unsigned LineNo,
765 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
766 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
767 LLVMMetadataRef Decl) {
768 DITemplateParameterArray TParams =
769 DITemplateParameterArray(unwrap<MDTuple>(TParam));
770 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
771 DINode::DIFlags llvmFlags = fromRust(Flags);
772 DISubprogram *Sub = Builder->createFunction(
773 unwrapDI<DIScope>(Scope),
774 StringRef(Name, NameLen),
775 StringRef(LinkageName, LinkageNameLen),
776 unwrapDI<DIFile>(File), LineNo,
777 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
778 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
780 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
784 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
785 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
786 uint64_t SizeInBits, unsigned Encoding) {
787 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
790 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
791 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
792 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
793 return wrap(Builder->createTypedef(
794 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
795 LineNo, unwrapDIPtr<DIScope>(Scope)));
798 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
799 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
800 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
801 const char *Name, size_t NameLen) {
802 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
803 SizeInBits, AlignInBits,
805 StringRef(Name, NameLen)));
808 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
809 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
810 const char *Name, size_t NameLen,
811 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
812 uint32_t AlignInBits, LLVMRustDIFlags Flags,
813 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
814 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
815 const char *UniqueId, size_t UniqueIdLen) {
816 return wrap(Builder->createStructType(
817 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
818 unwrapDI<DIFile>(File), LineNumber,
819 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
820 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
821 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
824 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
825 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
826 const char *Name, size_t NameLen,
827 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
828 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
829 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
830 return wrap(Builder->createVariantPart(
831 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
832 unwrapDI<DIFile>(File), LineNumber,
833 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
834 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
837 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
838 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
839 const char *Name, size_t NameLen,
840 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
841 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
842 LLVMMetadataRef Ty) {
843 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
844 StringRef(Name, NameLen),
845 unwrapDI<DIFile>(File), LineNo,
846 SizeInBits, AlignInBits, OffsetInBits,
847 fromRust(Flags), unwrapDI<DIType>(Ty)));
850 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
851 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
852 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
853 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
854 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
855 llvm::ConstantInt* D = nullptr;
857 D = unwrap<llvm::ConstantInt>(Discriminant);
859 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
860 StringRef(Name, NameLen),
861 unwrapDI<DIFile>(File), LineNo,
862 SizeInBits, AlignInBits, OffsetInBits, D,
863 fromRust(Flags), unwrapDI<DIType>(Ty)));
866 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
867 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
868 LLVMMetadataRef File, unsigned Line, unsigned Col) {
869 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
870 unwrapDI<DIFile>(File), Line, Col));
873 extern "C" LLVMMetadataRef
874 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
875 LLVMMetadataRef Scope,
876 LLVMMetadataRef File) {
877 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
878 unwrapDI<DIFile>(File)));
881 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
882 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
883 const char *Name, size_t NameLen,
884 const char *LinkageName, size_t LinkageNameLen,
885 LLVMMetadataRef File, unsigned LineNo,
886 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
887 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
888 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
890 llvm::DIExpression *InitExpr = nullptr;
891 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
892 InitExpr = Builder->createConstantValueExpression(
893 IntVal->getValue().getSExtValue());
894 } else if (llvm::ConstantFP *FPVal =
895 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
896 InitExpr = Builder->createConstantValueExpression(
897 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
900 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
901 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
902 StringRef(LinkageName, LinkageNameLen),
903 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
904 #if LLVM_VERSION_GE(10, 0)
905 /* isDefined */ true,
907 InitExpr, unwrapDIPtr<MDNode>(Decl),
908 /* templateParams */ nullptr,
911 InitVal->setMetadata("dbg", VarExpr);
913 return wrap(VarExpr);
916 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
917 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
918 const char *Name, size_t NameLen,
919 LLVMMetadataRef File, unsigned LineNo,
920 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
921 unsigned ArgNo, uint32_t AlignInBits) {
922 if (Tag == 0x100) { // DW_TAG_auto_variable
923 return wrap(Builder->createAutoVariable(
924 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
925 unwrapDI<DIFile>(File), LineNo,
926 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
928 return wrap(Builder->createParameterVariable(
929 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
930 unwrapDI<DIFile>(File), LineNo,
931 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
935 extern "C" LLVMMetadataRef
936 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
937 uint32_t AlignInBits, LLVMMetadataRef Ty,
938 LLVMMetadataRef Subscripts) {
940 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
941 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
944 extern "C" LLVMMetadataRef
945 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
947 return wrap(Builder->getOrCreateSubrange(Lo, Count));
950 extern "C" LLVMMetadataRef
951 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
952 LLVMMetadataRef *Ptr, unsigned Count) {
953 Metadata **DataValue = unwrap(Ptr);
955 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
958 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
959 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
960 int64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
961 LLVMBasicBlockRef InsertAtEnd) {
962 return wrap(Builder->insertDeclare(
963 unwrap(V), unwrap<DILocalVariable>(VarInfo),
964 Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
965 DebugLoc(cast<MDNode>(unwrap(DL))),
966 unwrap(InsertAtEnd)));
969 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
970 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
971 int64_t Value, bool IsUnsigned) {
972 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
975 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
976 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
977 const char *Name, size_t NameLen,
978 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
979 uint32_t AlignInBits, LLVMMetadataRef Elements,
980 LLVMMetadataRef ClassTy, bool IsScoped) {
981 return wrap(Builder->createEnumerationType(
982 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
983 unwrapDI<DIFile>(File), LineNumber,
984 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
985 unwrapDI<DIType>(ClassTy), "", IsScoped));
988 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
989 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
990 const char *Name, size_t NameLen,
991 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
992 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
993 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
994 return wrap(Builder->createUnionType(
995 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
996 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
997 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
998 StringRef(UniqueId, UniqueIdLen)));
1001 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1002 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1003 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1004 #if LLVM_VERSION_GE(11, 0)
1005 bool IsDefault = false; // FIXME: should we ever set this true?
1006 return wrap(Builder->createTemplateTypeParameter(
1007 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1009 return wrap(Builder->createTemplateTypeParameter(
1010 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty)));
1014 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1015 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1016 const char *Name, size_t NameLen, bool ExportSymbols) {
1017 return wrap(Builder->createNameSpace(
1018 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1023 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1024 LLVMMetadataRef CompositeTy,
1025 LLVMMetadataRef Elements,
1026 LLVMMetadataRef Params) {
1027 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1028 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1029 DINodeArray(unwrap<MDTuple>(Params)));
1032 extern "C" LLVMMetadataRef
1033 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1034 LLVMMetadataRef ScopeRef,
1035 LLVMMetadataRef InlinedAt) {
1036 #if LLVM_VERSION_GE(12, 0)
1037 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1038 DILocation *Loc = DILocation::get(
1039 Scope->getContext(), Line, Column, Scope,
1040 unwrapDIPtr<MDNode>(InlinedAt));
1043 DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(ScopeRef),
1044 unwrapDIPtr<MDNode>(InlinedAt));
1045 return wrap(debug_loc.getAsMDNode());
1049 extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {
1050 return dwarf::DW_OP_deref;
1053 extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1054 return dwarf::DW_OP_plus_uconst;
1057 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1058 RawRustStringOstream OS(Str);
1059 unwrap<llvm::Type>(Ty)->print(OS);
1062 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1063 RustStringRef Str) {
1064 RawRustStringOstream OS(Str);
1069 unwrap<llvm::Value>(V)->getType()->print(OS);
1071 unwrap<llvm::Value>(V)->print(OS);
1076 // Note that the two following functions look quite similar to the
1077 // LLVMGetSectionName function. Sadly, it appears that this function only
1078 // returns a char* pointer, which isn't guaranteed to be null-terminated. The
1079 // function provided by LLVM doesn't return the length, so we've created our own
1080 // function which returns the length as well as the data pointer.
1082 // For an example of this not returning a null terminated string, see
1083 // lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the
1084 // branches explicitly creates a StringRef without a null terminator, and then
1087 inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
1088 return reinterpret_cast<section_iterator *>(SI);
1091 extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI,
1093 #if LLVM_VERSION_GE(10, 0)
1094 auto NameOrErr = (*unwrap(SI))->getName();
1096 report_fatal_error(NameOrErr.takeError());
1097 *Ptr = NameOrErr->data();
1098 return NameOrErr->size();
1101 if (std::error_code EC = (*unwrap(SI))->getName(Ret))
1102 report_fatal_error(EC.message());
1108 // LLVMArrayType function does not support 64-bit ElementCount
1109 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1110 uint64_t ElementCount) {
1111 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1114 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1116 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1117 RawRustStringOstream OS(Str);
1118 unwrap(T)->print(OS);
1121 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1122 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1123 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1124 RustStringRef FilenameOut, RustStringRef MessageOut) {
1125 // Undefined to call this not on an optimization diagnostic!
1126 llvm::DiagnosticInfoOptimizationBase *Opt =
1127 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1129 RawRustStringOstream PassNameOS(PassNameOut);
1130 PassNameOS << Opt->getPassName();
1131 *FunctionOut = wrap(&Opt->getFunction());
1133 RawRustStringOstream FilenameOS(FilenameOut);
1134 DiagnosticLocation loc = Opt->getLocation();
1135 if (loc.isValid()) {
1136 *Line = loc.getLine();
1137 *Column = loc.getColumn();
1138 FilenameOS << loc.getAbsolutePath();
1141 RawRustStringOstream MessageOS(MessageOut);
1142 MessageOS << Opt->getMsg();
1145 enum class LLVMRustDiagnosticLevel {
1153 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1154 LLVMRustDiagnosticLevel *LevelOut,
1155 unsigned *CookieOut,
1156 LLVMTwineRef *MessageOut,
1157 LLVMValueRef *InstructionOut) {
1158 // Undefined to call this not on an inline assembly diagnostic!
1159 llvm::DiagnosticInfoInlineAsm *IA =
1160 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1162 *CookieOut = IA->getLocCookie();
1163 *MessageOut = wrap(&IA->getMsgStr());
1164 *InstructionOut = wrap(IA->getInstruction());
1166 switch (IA->getSeverity()) {
1168 *LevelOut = LLVMRustDiagnosticLevel::Error;
1171 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1174 *LevelOut = LLVMRustDiagnosticLevel::Note;
1177 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1180 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1184 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1185 RustStringRef Str) {
1186 RawRustStringOstream OS(Str);
1187 DiagnosticPrinterRawOStream DP(OS);
1188 unwrap(DI)->print(DP);
1191 enum class LLVMRustDiagnosticKind {
1195 DebugMetadataVersion,
1198 OptimizationRemarkMissed,
1199 OptimizationRemarkAnalysis,
1200 OptimizationRemarkAnalysisFPCommute,
1201 OptimizationRemarkAnalysisAliasing,
1202 OptimizationRemarkOther,
1203 OptimizationFailure,
1209 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1212 return LLVMRustDiagnosticKind::InlineAsm;
1214 return LLVMRustDiagnosticKind::StackSize;
1215 case DK_DebugMetadataVersion:
1216 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1217 case DK_SampleProfile:
1218 return LLVMRustDiagnosticKind::SampleProfile;
1219 case DK_OptimizationRemark:
1220 return LLVMRustDiagnosticKind::OptimizationRemark;
1221 case DK_OptimizationRemarkMissed:
1222 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1223 case DK_OptimizationRemarkAnalysis:
1224 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1225 case DK_OptimizationRemarkAnalysisFPCommute:
1226 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1227 case DK_OptimizationRemarkAnalysisAliasing:
1228 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1230 return LLVMRustDiagnosticKind::PGOProfile;
1232 return LLVMRustDiagnosticKind::Linker;
1233 case DK_Unsupported:
1234 return LLVMRustDiagnosticKind::Unsupported;
1236 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1237 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1238 : LLVMRustDiagnosticKind::Other;
1242 extern "C" LLVMRustDiagnosticKind
1243 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1244 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1247 // This is kept distinct from LLVMGetTypeKind, because when
1248 // a new type kind is added, the Rust-side enum must be
1249 // updated or UB will result.
1250 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1251 switch (unwrap(Ty)->getTypeID()) {
1252 case Type::VoidTyID:
1253 return LLVMVoidTypeKind;
1254 case Type::HalfTyID:
1255 return LLVMHalfTypeKind;
1256 case Type::FloatTyID:
1257 return LLVMFloatTypeKind;
1258 case Type::DoubleTyID:
1259 return LLVMDoubleTypeKind;
1260 case Type::X86_FP80TyID:
1261 return LLVMX86_FP80TypeKind;
1262 case Type::FP128TyID:
1263 return LLVMFP128TypeKind;
1264 case Type::PPC_FP128TyID:
1265 return LLVMPPC_FP128TypeKind;
1266 case Type::LabelTyID:
1267 return LLVMLabelTypeKind;
1268 case Type::MetadataTyID:
1269 return LLVMMetadataTypeKind;
1270 case Type::IntegerTyID:
1271 return LLVMIntegerTypeKind;
1272 case Type::FunctionTyID:
1273 return LLVMFunctionTypeKind;
1274 case Type::StructTyID:
1275 return LLVMStructTypeKind;
1276 case Type::ArrayTyID:
1277 return LLVMArrayTypeKind;
1278 case Type::PointerTyID:
1279 return LLVMPointerTypeKind;
1280 #if LLVM_VERSION_GE(11, 0)
1281 case Type::FixedVectorTyID:
1282 return LLVMVectorTypeKind;
1284 case Type::VectorTyID:
1285 return LLVMVectorTypeKind;
1287 case Type::X86_MMXTyID:
1288 return LLVMX86_MMXTypeKind;
1289 case Type::TokenTyID:
1290 return LLVMTokenTypeKind;
1291 #if LLVM_VERSION_GE(11, 0)
1292 case Type::ScalableVectorTyID:
1293 return LLVMScalableVectorTypeKind;
1294 case Type::BFloatTyID:
1295 return LLVMBFloatTypeKind;
1297 #if LLVM_VERSION_GE(12, 0)
1298 case Type::X86_AMXTyID:
1299 return LLVMX86_AMXTypeKind;
1302 report_fatal_error("Unhandled TypeID.");
1305 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1307 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1308 LLVMContextRef C, LLVMContext::InlineAsmDiagHandlerTy H, void *CX) {
1309 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1312 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1313 RustStringRef MessageOut,
1314 RustStringRef BufferOut,
1315 LLVMRustDiagnosticLevel* LevelOut,
1317 unsigned* RangesOut,
1318 size_t* NumRanges) {
1319 SMDiagnostic& D = *unwrap(DRef);
1320 RawRustStringOstream MessageOS(MessageOut);
1321 MessageOS << D.getMessage();
1323 switch (D.getKind()) {
1324 case SourceMgr::DK_Error:
1325 *LevelOut = LLVMRustDiagnosticLevel::Error;
1327 case SourceMgr::DK_Warning:
1328 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1330 case SourceMgr::DK_Note:
1331 *LevelOut = LLVMRustDiagnosticLevel::Note;
1333 case SourceMgr::DK_Remark:
1334 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1337 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1340 if (D.getLoc() == SMLoc())
1343 const SourceMgr &LSM = *D.getSourceMgr();
1344 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1345 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1347 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1349 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1350 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1351 for (size_t i = 0; i < *NumRanges; i++) {
1352 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1353 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1359 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1360 LLVMValueRef ParentPad,
1362 LLVMValueRef *LLArgs,
1364 Value **Args = unwrap(LLArgs);
1365 if (ParentPad == nullptr) {
1366 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1367 ParentPad = wrap(Constant::getNullValue(Ty));
1369 return wrap(unwrap(B)->CreateCleanupPad(
1370 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1373 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1374 LLVMValueRef CleanupPad,
1375 LLVMBasicBlockRef UnwindBB) {
1376 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1377 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1380 extern "C" LLVMValueRef
1381 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1382 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1383 Value **Args = unwrap(LLArgs);
1384 return wrap(unwrap(B)->CreateCatchPad(
1385 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1388 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1390 LLVMBasicBlockRef BB) {
1391 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1395 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1396 LLVMValueRef ParentPad,
1397 LLVMBasicBlockRef BB,
1398 unsigned NumHandlers,
1400 if (ParentPad == nullptr) {
1401 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1402 ParentPad = wrap(Constant::getNullValue(Ty));
1404 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1405 NumHandlers, Name));
1408 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1409 LLVMBasicBlockRef Handler) {
1410 Value *CatchSwitch = unwrap(CatchSwitchRef);
1411 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1414 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1415 LLVMValueRef *Inputs,
1416 unsigned NumInputs) {
1417 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1420 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1424 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
1425 LLVMValueRef *Args, unsigned NumArgs,
1426 OperandBundleDef *Bundle) {
1427 Value *Callee = unwrap(Fn);
1428 FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType());
1429 unsigned Len = Bundle ? 1 : 0;
1430 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1431 return wrap(unwrap(B)->CreateCall(
1432 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1435 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1436 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1437 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1440 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1441 LLVMValueRef Dst, unsigned DstAlign,
1442 LLVMValueRef Src, unsigned SrcAlign,
1443 LLVMValueRef Size, bool IsVolatile) {
1444 #if LLVM_VERSION_GE(10, 0)
1445 return wrap(unwrap(B)->CreateMemCpy(
1446 unwrap(Dst), MaybeAlign(DstAlign),
1447 unwrap(Src), MaybeAlign(SrcAlign),
1448 unwrap(Size), IsVolatile));
1450 return wrap(unwrap(B)->CreateMemCpy(
1451 unwrap(Dst), DstAlign,
1452 unwrap(Src), SrcAlign,
1453 unwrap(Size), IsVolatile));
1457 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1458 LLVMValueRef Dst, unsigned DstAlign,
1459 LLVMValueRef Src, unsigned SrcAlign,
1460 LLVMValueRef Size, bool IsVolatile) {
1461 #if LLVM_VERSION_GE(10, 0)
1462 return wrap(unwrap(B)->CreateMemMove(
1463 unwrap(Dst), MaybeAlign(DstAlign),
1464 unwrap(Src), MaybeAlign(SrcAlign),
1465 unwrap(Size), IsVolatile));
1467 return wrap(unwrap(B)->CreateMemMove(
1468 unwrap(Dst), DstAlign,
1469 unwrap(Src), SrcAlign,
1470 unwrap(Size), IsVolatile));
1474 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1475 LLVMValueRef Dst, unsigned DstAlign,
1477 LLVMValueRef Size, bool IsVolatile) {
1478 #if LLVM_VERSION_GE(10, 0)
1479 return wrap(unwrap(B)->CreateMemSet(
1480 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1482 return wrap(unwrap(B)->CreateMemSet(
1483 unwrap(Dst), unwrap(Val), unwrap(Size), DstAlign, IsVolatile));
1487 extern "C" LLVMValueRef
1488 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
1489 unsigned NumArgs, LLVMBasicBlockRef Then,
1490 LLVMBasicBlockRef Catch, OperandBundleDef *Bundle,
1492 Value *Callee = unwrap(Fn);
1493 FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType());
1494 unsigned Len = Bundle ? 1 : 0;
1495 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1496 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1497 makeArrayRef(unwrap(Args), NumArgs),
1501 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1502 LLVMBasicBlockRef BB) {
1503 auto Point = unwrap(BB)->getFirstInsertionPt();
1504 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1507 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1508 const char *Name, size_t NameLen) {
1509 Triple TargetTriple(unwrap(M)->getTargetTriple());
1510 GlobalObject *GV = unwrap<GlobalObject>(V);
1511 if (TargetTriple.supportsCOMDAT()) {
1512 StringRef NameRef(Name, NameLen);
1513 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1517 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1518 GlobalObject *GV = unwrap<GlobalObject>(V);
1519 GV->setComdat(nullptr);
1522 enum class LLVMRustLinkage {
1523 ExternalLinkage = 0,
1524 AvailableExternallyLinkage = 1,
1525 LinkOnceAnyLinkage = 2,
1526 LinkOnceODRLinkage = 3,
1529 AppendingLinkage = 6,
1530 InternalLinkage = 7,
1532 ExternalWeakLinkage = 9,
1536 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1538 case LLVMExternalLinkage:
1539 return LLVMRustLinkage::ExternalLinkage;
1540 case LLVMAvailableExternallyLinkage:
1541 return LLVMRustLinkage::AvailableExternallyLinkage;
1542 case LLVMLinkOnceAnyLinkage:
1543 return LLVMRustLinkage::LinkOnceAnyLinkage;
1544 case LLVMLinkOnceODRLinkage:
1545 return LLVMRustLinkage::LinkOnceODRLinkage;
1546 case LLVMWeakAnyLinkage:
1547 return LLVMRustLinkage::WeakAnyLinkage;
1548 case LLVMWeakODRLinkage:
1549 return LLVMRustLinkage::WeakODRLinkage;
1550 case LLVMAppendingLinkage:
1551 return LLVMRustLinkage::AppendingLinkage;
1552 case LLVMInternalLinkage:
1553 return LLVMRustLinkage::InternalLinkage;
1554 case LLVMPrivateLinkage:
1555 return LLVMRustLinkage::PrivateLinkage;
1556 case LLVMExternalWeakLinkage:
1557 return LLVMRustLinkage::ExternalWeakLinkage;
1558 case LLVMCommonLinkage:
1559 return LLVMRustLinkage::CommonLinkage;
1561 report_fatal_error("Invalid LLVMRustLinkage value!");
1565 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1567 case LLVMRustLinkage::ExternalLinkage:
1568 return LLVMExternalLinkage;
1569 case LLVMRustLinkage::AvailableExternallyLinkage:
1570 return LLVMAvailableExternallyLinkage;
1571 case LLVMRustLinkage::LinkOnceAnyLinkage:
1572 return LLVMLinkOnceAnyLinkage;
1573 case LLVMRustLinkage::LinkOnceODRLinkage:
1574 return LLVMLinkOnceODRLinkage;
1575 case LLVMRustLinkage::WeakAnyLinkage:
1576 return LLVMWeakAnyLinkage;
1577 case LLVMRustLinkage::WeakODRLinkage:
1578 return LLVMWeakODRLinkage;
1579 case LLVMRustLinkage::AppendingLinkage:
1580 return LLVMAppendingLinkage;
1581 case LLVMRustLinkage::InternalLinkage:
1582 return LLVMInternalLinkage;
1583 case LLVMRustLinkage::PrivateLinkage:
1584 return LLVMPrivateLinkage;
1585 case LLVMRustLinkage::ExternalWeakLinkage:
1586 return LLVMExternalWeakLinkage;
1587 case LLVMRustLinkage::CommonLinkage:
1588 return LLVMCommonLinkage;
1590 report_fatal_error("Invalid LLVMRustLinkage value!");
1593 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1594 return toRust(LLVMGetLinkage(V));
1597 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1598 LLVMRustLinkage RustLinkage) {
1599 LLVMSetLinkage(V, fromRust(RustLinkage));
1602 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1603 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1604 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1606 auto C = unwrap<llvm::ConstantInt>(CV);
1607 if (C->getBitWidth() > 128) { return false; }
1610 AP = C->getValue().sextOrSelf(128);
1612 AP = C->getValue().zextOrSelf(128);
1614 *low = AP.getLoBits(64).getZExtValue();
1615 *high = AP.getHiBits(64).getZExtValue();
1619 enum class LLVMRustVisibility {
1625 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1627 case LLVMDefaultVisibility:
1628 return LLVMRustVisibility::Default;
1629 case LLVMHiddenVisibility:
1630 return LLVMRustVisibility::Hidden;
1631 case LLVMProtectedVisibility:
1632 return LLVMRustVisibility::Protected;
1634 report_fatal_error("Invalid LLVMRustVisibility value!");
1637 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1639 case LLVMRustVisibility::Default:
1640 return LLVMDefaultVisibility;
1641 case LLVMRustVisibility::Hidden:
1642 return LLVMHiddenVisibility;
1643 case LLVMRustVisibility::Protected:
1644 return LLVMProtectedVisibility;
1646 report_fatal_error("Invalid LLVMRustVisibility value!");
1649 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1650 return toRust(LLVMGetVisibility(V));
1653 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1654 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1655 LLVMTypeRef DestTy, bool isSigned) {
1656 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1659 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1660 LLVMRustVisibility RustVisibility) {
1661 LLVMSetVisibility(V, fromRust(RustVisibility));
1664 struct LLVMRustModuleBuffer {
1668 extern "C" LLVMRustModuleBuffer*
1669 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1670 #if LLVM_VERSION_GE(10, 0)
1671 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1673 auto Ret = llvm::make_unique<LLVMRustModuleBuffer>();
1676 raw_string_ostream OS(Ret->data);
1678 legacy::PassManager PM;
1679 PM.add(createBitcodeWriterPass(OS));
1683 return Ret.release();
1687 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1691 extern "C" const void*
1692 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1693 return Buffer->data.data();
1697 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1698 return Buffer->data.length();
1702 LLVMRustModuleCost(LLVMModuleRef M) {
1703 auto f = unwrap(M)->functions();
1704 return std::distance(std::begin(f), std::end(f));
1707 // Vector reductions:
1708 extern "C" LLVMValueRef
1709 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1710 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1712 extern "C" LLVMValueRef
1713 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1714 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1716 extern "C" LLVMValueRef
1717 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1718 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1720 extern "C" LLVMValueRef
1721 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1722 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1724 extern "C" LLVMValueRef
1725 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1726 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1728 extern "C" LLVMValueRef
1729 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1730 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1732 extern "C" LLVMValueRef
1733 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1734 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1736 extern "C" LLVMValueRef
1737 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1738 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1740 extern "C" LLVMValueRef
1741 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1742 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1744 extern "C" LLVMValueRef
1745 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1746 #if LLVM_VERSION_GE(12, 0)
1747 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1748 I->setHasNoNaNs(NoNaN);
1751 return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN));
1754 extern "C" LLVMValueRef
1755 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1756 #if LLVM_VERSION_GE(12, 0)
1757 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1758 I->setHasNoNaNs(NoNaN);
1761 return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN));
1765 extern "C" LLVMValueRef
1766 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1767 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1769 extern "C" LLVMValueRef
1770 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1771 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));