1 #include "LLVMWrapper.h"
2 #include "llvm/IR/DebugInfoMetadata.h"
3 #include "llvm/IR/DiagnosticHandler.h"
4 #include "llvm/IR/DiagnosticInfo.h"
5 #include "llvm/IR/DiagnosticPrinter.h"
6 #include "llvm/IR/GlobalVariable.h"
7 #include "llvm/IR/Instructions.h"
8 #include "llvm/IR/Intrinsics.h"
9 #include "llvm/Object/Archive.h"
10 #include "llvm/Object/COFFImportFile.h"
11 #include "llvm/Object/ObjectFile.h"
12 #include "llvm/Bitcode/BitcodeWriterPass.h"
13 #include "llvm/Support/Signals.h"
14 #include "llvm/ADT/Optional.h"
18 //===----------------------------------------------------------------------===
20 // This file defines alternate interfaces to core functions that are more
21 // readily callable by Rust's FFI.
23 //===----------------------------------------------------------------------===
26 using namespace llvm::sys;
27 using namespace llvm::object;
29 // LLVMAtomicOrdering is already an enum - don't create another
31 static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
33 case LLVMAtomicOrderingNotAtomic:
34 return AtomicOrdering::NotAtomic;
35 case LLVMAtomicOrderingUnordered:
36 return AtomicOrdering::Unordered;
37 case LLVMAtomicOrderingMonotonic:
38 return AtomicOrdering::Monotonic;
39 case LLVMAtomicOrderingAcquire:
40 return AtomicOrdering::Acquire;
41 case LLVMAtomicOrderingRelease:
42 return AtomicOrdering::Release;
43 case LLVMAtomicOrderingAcquireRelease:
44 return AtomicOrdering::AcquireRelease;
45 case LLVMAtomicOrderingSequentiallyConsistent:
46 return AtomicOrdering::SequentiallyConsistent;
49 report_fatal_error("Invalid LLVMAtomicOrdering value!");
52 static LLVM_THREAD_LOCAL char *LastError;
54 // Custom error handler for fatal LLVM errors.
56 // Notably it exits the process with code 101, unlike LLVM's default of 1.
57 static void FatalErrorHandler(void *UserData,
58 #if LLVM_VERSION_LT(14, 0)
59 const std::string& Reason,
64 // Do the same thing that the default error handler does.
65 std::cerr << "LLVM ERROR: " << Reason << std::endl;
67 // Since this error handler exits the process, we have to run any cleanup that
68 // LLVM would run after handling the error. This might change with an LLVM
70 sys::RunInterruptHandlers();
75 extern "C" void LLVMRustInstallFatalErrorHandler() {
76 install_fatal_error_handler(FatalErrorHandler);
79 extern "C" char *LLVMRustGetLastError(void) {
80 char *Ret = LastError;
85 extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) {
86 return unwrap(M)->getInstructionCount();
89 extern "C" void LLVMRustSetLastError(const char *Err) {
90 free((void *)LastError);
91 LastError = strdup(Err);
94 extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
95 auto ctx = new LLVMContext();
96 ctx->setDiscardValueNames(shouldDiscardNames);
100 extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
101 const char *Triple) {
102 unwrap(M)->setTargetTriple(Triple::normalize(Triple));
105 extern "C" void LLVMRustPrintPassTimings() {
106 raw_fd_ostream OS(2, false); // stderr.
107 TimerGroup::printAll(OS);
110 extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
112 return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
115 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
118 LLVMTypeRef FunctionTy) {
119 return wrap(unwrap(M)
120 ->getOrInsertFunction(StringRef(Name, NameLen),
121 unwrap<FunctionType>(FunctionTy))
126 extern "C" LLVMValueRef
127 LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
128 Module *Mod = unwrap(M);
129 StringRef NameRef(Name, NameLen);
131 // We don't use Module::getOrInsertGlobal because that returns a Constant*,
132 // which may either be the real GlobalVariable*, or a constant bitcast of it
133 // if our type doesn't match the original declaration. We always want the
134 // GlobalVariable* so we can access linkage, visibility, etc.
135 GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true);
137 GV = new GlobalVariable(*Mod, unwrap(Ty), false,
138 GlobalValue::ExternalLinkage, nullptr, NameRef);
142 extern "C" LLVMValueRef
143 LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
144 return wrap(new GlobalVariable(*unwrap(M),
147 GlobalValue::PrivateLinkage,
151 extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
152 return wrap(Type::getMetadataTy(*unwrap(C)));
155 static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
158 return Attribute::AlwaysInline;
160 return Attribute::ByVal;
162 return Attribute::Cold;
164 return Attribute::InlineHint;
166 return Attribute::MinSize;
168 return Attribute::Naked;
170 return Attribute::NoAlias;
172 return Attribute::NoCapture;
174 return Attribute::NoInline;
176 return Attribute::NonNull;
178 return Attribute::NoRedZone;
180 return Attribute::NoReturn;
182 return Attribute::NoUnwind;
183 case OptimizeForSize:
184 return Attribute::OptimizeForSize;
186 return Attribute::ReadOnly;
188 return Attribute::SExt;
190 return Attribute::StructRet;
192 return Attribute::UWTable;
194 return Attribute::ZExt;
196 return Attribute::InReg;
198 return Attribute::SanitizeThread;
199 case SanitizeAddress:
200 return Attribute::SanitizeAddress;
202 return Attribute::SanitizeMemory;
204 return Attribute::NonLazyBind;
206 return Attribute::OptimizeNone;
208 return Attribute::ReturnsTwice;
210 return Attribute::ReadNone;
211 case InaccessibleMemOnly:
212 return Attribute::InaccessibleMemOnly;
213 case SanitizeHWAddress:
214 return Attribute::SanitizeHWAddress;
216 return Attribute::WillReturn;
217 case StackProtectReq:
218 return Attribute::StackProtectReq;
219 case StackProtectStrong:
220 return Attribute::StackProtectStrong;
222 return Attribute::StackProtect;
224 report_fatal_error("bad AttributeKind");
227 template<typename T> static inline void AddAttribute(T *t, unsigned Index, Attribute Attr) {
228 #if LLVM_VERSION_LT(14, 0)
229 t->addAttribute(Index, Attr);
231 t->addAttributeAtIndex(Index, Attr);
235 extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
236 LLVMRustAttribute RustAttr) {
237 CallBase *Call = unwrap<CallBase>(Instr);
238 Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
239 AddAttribute(Call, Index, Attr);
242 extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index,
244 CallBase *Call = unwrap<CallBase>(Instr);
245 Attribute Attr = Attribute::get(Call->getContext(), Name);
246 AddAttribute(Call, Index, Attr);
249 extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
252 CallBase *Call = unwrap<CallBase>(Instr);
253 Attribute Attr = Attribute::getWithAlignment(Call->getContext(), Align(Bytes));
254 AddAttribute(Call, Index, Attr);
257 extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
260 CallBase *Call = unwrap<CallBase>(Instr);
261 Attribute Attr = Attribute::getWithDereferenceableBytes(Call->getContext(), Bytes);
262 AddAttribute(Call, Index, Attr);
265 extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
268 CallBase *Call = unwrap<CallBase>(Instr);
269 Attribute Attr = Attribute::getWithDereferenceableOrNullBytes(Call->getContext(), Bytes);
270 AddAttribute(Call, Index, Attr);
273 extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
275 CallBase *Call = unwrap<CallBase>(Instr);
276 Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
277 AddAttribute(Call, Index, Attr);
280 extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index,
282 CallBase *Call = unwrap<CallBase>(Instr);
283 Attribute Attr = Attribute::getWithStructRetType(Call->getContext(), unwrap(Ty));
284 AddAttribute(Call, Index, Attr);
287 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
288 LLVMRustAttribute RustAttr) {
289 Function *A = unwrap<Function>(Fn);
290 Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
291 AddAttribute(A, Index, Attr);
294 extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
297 Function *A = unwrap<Function>(Fn);
298 AddAttribute(A, Index, Attribute::getWithAlignment(
299 A->getContext(), llvm::Align(Bytes)));
302 extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
304 Function *A = unwrap<Function>(Fn);
305 AddAttribute(A, Index, Attribute::getWithDereferenceableBytes(A->getContext(),
309 extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
312 Function *A = unwrap<Function>(Fn);
313 AddAttribute(A, Index, Attribute::getWithDereferenceableOrNullBytes(
314 A->getContext(), Bytes));
317 extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
319 Function *F = unwrap<Function>(Fn);
320 Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
321 AddAttribute(F, Index, Attr);
324 extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index,
326 Function *F = unwrap<Function>(Fn);
327 Attribute Attr = Attribute::getWithStructRetType(F->getContext(), unwrap(Ty));
328 AddAttribute(F, Index, Attr);
331 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
335 Function *F = unwrap<Function>(Fn);
336 AddAttribute(F, Index, Attribute::get(
337 F->getContext(), StringRef(Name), StringRef(Value)));
340 extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
342 LLVMRustAttribute RustAttr) {
343 Function *F = unwrap<Function>(Fn);
344 Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr));
346 auto PAL = F->getAttributes();
347 AttributeList PALNew;
348 #if LLVM_VERSION_LT(14, 0)
349 PALNew = PAL.removeAttributes(F->getContext(), Index, B);
351 PALNew = PAL.removeAttributesAtIndex(F->getContext(), Index, B);
353 F->setAttributes(PALNew);
356 // Enable a fast-math flag
358 // https://llvm.org/docs/LangRef.html#fast-math-flags
359 extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
360 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
365 extern "C" LLVMValueRef
366 LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
367 const char *Name, LLVMAtomicOrdering Order) {
368 Value *Ptr = unwrap(Source);
369 LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
370 LI->setAtomic(fromRust(Order));
374 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
377 LLVMAtomicOrdering Order) {
378 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
379 SI->setAtomic(fromRust(Order));
383 // FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
384 // once we raise our minimum support to LLVM 10.
385 extern "C" LLVMValueRef
386 LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
387 LLVMValueRef Old, LLVMValueRef Source,
388 LLVMAtomicOrdering Order,
389 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
390 #if LLVM_VERSION_GE(13,0)
391 // Rust probably knows the alignment of the target value and should be able to
392 // specify something more precise than MaybeAlign here. See also
393 // https://reviews.llvm.org/D97224 which may be a useful reference.
394 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
395 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
396 fromRust(FailureOrder));
398 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
399 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
400 fromRust(FailureOrder));
406 enum class LLVMRustSynchronizationScope {
411 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
413 case LLVMRustSynchronizationScope::SingleThread:
414 return SyncScope::SingleThread;
415 case LLVMRustSynchronizationScope::CrossThread:
416 return SyncScope::System;
418 report_fatal_error("bad SynchronizationScope.");
422 extern "C" LLVMValueRef
423 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
424 LLVMRustSynchronizationScope Scope) {
425 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
428 enum class LLVMRustAsmDialect {
433 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
435 case LLVMRustAsmDialect::Att:
436 return InlineAsm::AD_ATT;
437 case LLVMRustAsmDialect::Intel:
438 return InlineAsm::AD_Intel;
440 report_fatal_error("bad AsmDialect.");
444 extern "C" LLVMValueRef
445 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
446 char *Constraints, size_t ConstraintsLen,
447 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
448 LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
449 #if LLVM_VERSION_GE(13, 0)
450 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
451 StringRef(AsmString, AsmStringLen),
452 StringRef(Constraints, ConstraintsLen),
453 HasSideEffects, IsAlignStack,
454 fromRust(Dialect), CanThrow));
456 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
457 StringRef(AsmString, AsmStringLen),
458 StringRef(Constraints, ConstraintsLen),
459 HasSideEffects, IsAlignStack,
464 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
465 size_t ConstraintsLen) {
466 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
467 StringRef(Constraints, ConstraintsLen));
470 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
472 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
475 typedef DIBuilder *LLVMRustDIBuilderRef;
477 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
478 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
481 #define DIDescriptor DIScope
482 #define DIArray DINodeArray
483 #define unwrapDI unwrapDIPtr
485 // These values **must** match debuginfo::DIFlags! They also *happen*
486 // to match LLVM, but that isn't required as we do giant sets of
487 // matching below. The value shouldn't be directly passed to LLVM.
488 enum class LLVMRustDIFlags : uint32_t {
493 FlagFwdDecl = (1 << 2),
494 FlagAppleBlock = (1 << 3),
495 FlagBlockByrefStruct = (1 << 4),
496 FlagVirtual = (1 << 5),
497 FlagArtificial = (1 << 6),
498 FlagExplicit = (1 << 7),
499 FlagPrototyped = (1 << 8),
500 FlagObjcClassComplete = (1 << 9),
501 FlagObjectPointer = (1 << 10),
502 FlagVector = (1 << 11),
503 FlagStaticMember = (1 << 12),
504 FlagLValueReference = (1 << 13),
505 FlagRValueReference = (1 << 14),
506 FlagExternalTypeRef = (1 << 15),
507 FlagIntroducedVirtual = (1 << 18),
508 FlagBitField = (1 << 19),
509 FlagNoReturn = (1 << 20),
510 // Do not add values that are not supported by the minimum LLVM
511 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
514 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
515 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
516 static_cast<uint32_t>(B));
519 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
520 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
521 static_cast<uint32_t>(B));
524 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
528 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
530 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
531 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
534 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
535 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
537 switch (visibility(Flags)) {
538 case LLVMRustDIFlags::FlagPrivate:
539 Result |= DINode::DIFlags::FlagPrivate;
541 case LLVMRustDIFlags::FlagProtected:
542 Result |= DINode::DIFlags::FlagProtected;
544 case LLVMRustDIFlags::FlagPublic:
545 Result |= DINode::DIFlags::FlagPublic;
548 // The rest are handled below
552 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
553 Result |= DINode::DIFlags::FlagFwdDecl;
555 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
556 Result |= DINode::DIFlags::FlagAppleBlock;
558 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
559 Result |= DINode::DIFlags::FlagVirtual;
561 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
562 Result |= DINode::DIFlags::FlagArtificial;
564 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
565 Result |= DINode::DIFlags::FlagExplicit;
567 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
568 Result |= DINode::DIFlags::FlagPrototyped;
570 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
571 Result |= DINode::DIFlags::FlagObjcClassComplete;
573 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
574 Result |= DINode::DIFlags::FlagObjectPointer;
576 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
577 Result |= DINode::DIFlags::FlagVector;
579 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
580 Result |= DINode::DIFlags::FlagStaticMember;
582 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
583 Result |= DINode::DIFlags::FlagLValueReference;
585 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
586 Result |= DINode::DIFlags::FlagRValueReference;
588 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
589 Result |= DINode::DIFlags::FlagIntroducedVirtual;
591 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
592 Result |= DINode::DIFlags::FlagBitField;
594 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
595 Result |= DINode::DIFlags::FlagNoReturn;
601 // These values **must** match debuginfo::DISPFlags! They also *happen*
602 // to match LLVM, but that isn't required as we do giant sets of
603 // matching below. The value shouldn't be directly passed to LLVM.
604 enum class LLVMRustDISPFlags : uint32_t {
607 SPFlagPureVirtual = 2,
608 SPFlagLocalToUnit = (1 << 2),
609 SPFlagDefinition = (1 << 3),
610 SPFlagOptimized = (1 << 4),
611 SPFlagMainSubprogram = (1 << 5),
612 // Do not add values that are not supported by the minimum LLVM
613 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
614 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
617 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
618 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
619 static_cast<uint32_t>(B));
622 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
623 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
624 static_cast<uint32_t>(B));
627 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
631 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
633 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
634 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
637 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
638 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
640 switch (virtuality(SPFlags)) {
641 case LLVMRustDISPFlags::SPFlagVirtual:
642 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
644 case LLVMRustDISPFlags::SPFlagPureVirtual:
645 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
648 // The rest are handled below
652 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
653 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
655 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
656 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
658 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
659 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
661 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
662 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
668 enum class LLVMRustDebugEmissionKind {
674 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
676 case LLVMRustDebugEmissionKind::NoDebug:
677 return DICompileUnit::DebugEmissionKind::NoDebug;
678 case LLVMRustDebugEmissionKind::FullDebug:
679 return DICompileUnit::DebugEmissionKind::FullDebug;
680 case LLVMRustDebugEmissionKind::LineTablesOnly:
681 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
683 report_fatal_error("bad DebugEmissionKind.");
687 enum class LLVMRustChecksumKind {
694 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
696 case LLVMRustChecksumKind::None:
698 case LLVMRustChecksumKind::MD5:
699 return DIFile::ChecksumKind::CSK_MD5;
700 case LLVMRustChecksumKind::SHA1:
701 return DIFile::ChecksumKind::CSK_SHA1;
702 case LLVMRustChecksumKind::SHA256:
703 return DIFile::ChecksumKind::CSK_SHA256;
705 report_fatal_error("bad ChecksumKind.");
709 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
710 return DEBUG_METADATA_VERSION;
713 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
715 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
717 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
719 extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
721 unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
724 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
725 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
728 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
729 return new DIBuilder(*unwrap(M));
732 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
736 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
740 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
741 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
742 const char *Producer, size_t ProducerLen, bool isOptimized,
743 const char *Flags, unsigned RuntimeVer,
744 const char *SplitName, size_t SplitNameLen,
745 LLVMRustDebugEmissionKind Kind,
746 uint64_t DWOId, bool SplitDebugInlining) {
747 auto *File = unwrapDI<DIFile>(FileRef);
749 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
750 isOptimized, Flags, RuntimeVer,
751 StringRef(SplitName, SplitNameLen),
752 fromRust(Kind), DWOId, SplitDebugInlining));
755 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
756 LLVMRustDIBuilderRef Builder,
757 const char *Filename, size_t FilenameLen,
758 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
759 const char *Checksum, size_t ChecksumLen) {
760 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
761 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
763 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
764 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
765 StringRef(Directory, DirectoryLen),
769 extern "C" LLVMMetadataRef
770 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
771 LLVMMetadataRef ParameterTypes) {
772 return wrap(Builder->createSubroutineType(
773 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
776 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
777 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
778 const char *Name, size_t NameLen,
779 const char *LinkageName, size_t LinkageNameLen,
780 LLVMMetadataRef File, unsigned LineNo,
781 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
782 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
783 LLVMMetadataRef Decl) {
784 DITemplateParameterArray TParams =
785 DITemplateParameterArray(unwrap<MDTuple>(TParam));
786 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
787 DINode::DIFlags llvmFlags = fromRust(Flags);
788 DISubprogram *Sub = Builder->createFunction(
789 unwrapDI<DIScope>(Scope),
790 StringRef(Name, NameLen),
791 StringRef(LinkageName, LinkageNameLen),
792 unwrapDI<DIFile>(File), LineNo,
793 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
794 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
796 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
800 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
801 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
802 uint64_t SizeInBits, unsigned Encoding) {
803 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
806 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
807 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
808 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
809 return wrap(Builder->createTypedef(
810 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
811 LineNo, unwrapDIPtr<DIScope>(Scope)));
814 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
815 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
816 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
817 const char *Name, size_t NameLen) {
818 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
819 SizeInBits, AlignInBits,
821 StringRef(Name, NameLen)));
824 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
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,
829 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
830 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
831 const char *UniqueId, size_t UniqueIdLen) {
832 return wrap(Builder->createStructType(
833 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
834 unwrapDI<DIFile>(File), LineNumber,
835 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
836 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
837 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
840 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
841 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
842 const char *Name, size_t NameLen,
843 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
844 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
845 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
846 return wrap(Builder->createVariantPart(
847 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
848 unwrapDI<DIFile>(File), LineNumber,
849 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
850 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
853 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
854 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
855 const char *Name, size_t NameLen,
856 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
857 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
858 LLVMMetadataRef Ty) {
859 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
860 StringRef(Name, NameLen),
861 unwrapDI<DIFile>(File), LineNo,
862 SizeInBits, AlignInBits, OffsetInBits,
863 fromRust(Flags), unwrapDI<DIType>(Ty)));
866 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
867 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
868 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
869 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
870 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
871 llvm::ConstantInt* D = nullptr;
873 D = unwrap<llvm::ConstantInt>(Discriminant);
875 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
876 StringRef(Name, NameLen),
877 unwrapDI<DIFile>(File), LineNo,
878 SizeInBits, AlignInBits, OffsetInBits, D,
879 fromRust(Flags), unwrapDI<DIType>(Ty)));
882 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
883 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
884 LLVMMetadataRef File, unsigned Line, unsigned Col) {
885 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
886 unwrapDI<DIFile>(File), Line, Col));
889 extern "C" LLVMMetadataRef
890 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
891 LLVMMetadataRef Scope,
892 LLVMMetadataRef File) {
893 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
894 unwrapDI<DIFile>(File)));
897 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
898 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
899 const char *Name, size_t NameLen,
900 const char *LinkageName, size_t LinkageNameLen,
901 LLVMMetadataRef File, unsigned LineNo,
902 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
903 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
904 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
906 llvm::DIExpression *InitExpr = nullptr;
907 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
908 InitExpr = Builder->createConstantValueExpression(
909 IntVal->getValue().getSExtValue());
910 } else if (llvm::ConstantFP *FPVal =
911 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
912 InitExpr = Builder->createConstantValueExpression(
913 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
916 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
917 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
918 StringRef(LinkageName, LinkageNameLen),
919 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
920 /* isDefined */ true,
921 InitExpr, unwrapDIPtr<MDNode>(Decl),
922 /* templateParams */ nullptr,
925 InitVal->setMetadata("dbg", VarExpr);
927 return wrap(VarExpr);
930 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
931 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
932 const char *Name, size_t NameLen,
933 LLVMMetadataRef File, unsigned LineNo,
934 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
935 unsigned ArgNo, uint32_t AlignInBits) {
936 if (Tag == 0x100) { // DW_TAG_auto_variable
937 return wrap(Builder->createAutoVariable(
938 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
939 unwrapDI<DIFile>(File), LineNo,
940 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
942 return wrap(Builder->createParameterVariable(
943 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
944 unwrapDI<DIFile>(File), LineNo,
945 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
949 extern "C" LLVMMetadataRef
950 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
951 uint32_t AlignInBits, LLVMMetadataRef Ty,
952 LLVMMetadataRef Subscripts) {
954 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
955 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
958 extern "C" LLVMMetadataRef
959 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
961 return wrap(Builder->getOrCreateSubrange(Lo, Count));
964 extern "C" LLVMMetadataRef
965 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
966 LLVMMetadataRef *Ptr, unsigned Count) {
967 Metadata **DataValue = unwrap(Ptr);
969 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
972 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
973 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
974 int64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
975 LLVMBasicBlockRef InsertAtEnd) {
976 return wrap(Builder->insertDeclare(
977 unwrap(V), unwrap<DILocalVariable>(VarInfo),
978 Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
979 DebugLoc(cast<MDNode>(unwrap(DL))),
980 unwrap(InsertAtEnd)));
983 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
984 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
985 int64_t Value, bool IsUnsigned) {
986 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
989 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
990 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
991 const char *Name, size_t NameLen,
992 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
993 uint32_t AlignInBits, LLVMMetadataRef Elements,
994 LLVMMetadataRef ClassTy, bool IsScoped) {
995 return wrap(Builder->createEnumerationType(
996 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
997 unwrapDI<DIFile>(File), LineNumber,
998 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
999 unwrapDI<DIType>(ClassTy), "", IsScoped));
1002 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
1003 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1004 const char *Name, size_t NameLen,
1005 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1006 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
1007 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
1008 return wrap(Builder->createUnionType(
1009 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1010 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1011 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1012 StringRef(UniqueId, UniqueIdLen)));
1015 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1016 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1017 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1018 bool IsDefault = false; // FIXME: should we ever set this true?
1019 return wrap(Builder->createTemplateTypeParameter(
1020 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1023 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1024 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1025 const char *Name, size_t NameLen, bool ExportSymbols) {
1026 return wrap(Builder->createNameSpace(
1027 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1032 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1033 LLVMMetadataRef CompositeTy,
1034 LLVMMetadataRef Elements,
1035 LLVMMetadataRef Params) {
1036 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1037 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1038 DINodeArray(unwrap<MDTuple>(Params)));
1041 extern "C" LLVMMetadataRef
1042 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1043 LLVMMetadataRef ScopeRef,
1044 LLVMMetadataRef InlinedAt) {
1045 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1046 DILocation *Loc = DILocation::get(
1047 Scope->getContext(), Line, Column, Scope,
1048 unwrapDIPtr<MDNode>(InlinedAt));
1052 extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {
1053 return dwarf::DW_OP_deref;
1056 extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1057 return dwarf::DW_OP_plus_uconst;
1060 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1061 RawRustStringOstream OS(Str);
1062 unwrap<llvm::Type>(Ty)->print(OS);
1065 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1066 RustStringRef Str) {
1067 RawRustStringOstream OS(Str);
1072 unwrap<llvm::Value>(V)->getType()->print(OS);
1074 unwrap<llvm::Value>(V)->print(OS);
1079 // LLVMArrayType function does not support 64-bit ElementCount
1080 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1081 uint64_t ElementCount) {
1082 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1085 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1087 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1088 RawRustStringOstream OS(Str);
1089 unwrap(T)->print(OS);
1092 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1093 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1094 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1095 RustStringRef FilenameOut, RustStringRef MessageOut) {
1096 // Undefined to call this not on an optimization diagnostic!
1097 llvm::DiagnosticInfoOptimizationBase *Opt =
1098 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1100 RawRustStringOstream PassNameOS(PassNameOut);
1101 PassNameOS << Opt->getPassName();
1102 *FunctionOut = wrap(&Opt->getFunction());
1104 RawRustStringOstream FilenameOS(FilenameOut);
1105 DiagnosticLocation loc = Opt->getLocation();
1106 if (loc.isValid()) {
1107 *Line = loc.getLine();
1108 *Column = loc.getColumn();
1109 FilenameOS << loc.getAbsolutePath();
1112 RawRustStringOstream MessageOS(MessageOut);
1113 MessageOS << Opt->getMsg();
1116 enum class LLVMRustDiagnosticLevel {
1124 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1125 LLVMRustDiagnosticLevel *LevelOut,
1126 unsigned *CookieOut,
1127 LLVMTwineRef *MessageOut) {
1128 // Undefined to call this not on an inline assembly diagnostic!
1129 llvm::DiagnosticInfoInlineAsm *IA =
1130 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1132 *CookieOut = IA->getLocCookie();
1133 *MessageOut = wrap(&IA->getMsgStr());
1135 switch (IA->getSeverity()) {
1137 *LevelOut = LLVMRustDiagnosticLevel::Error;
1140 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1143 *LevelOut = LLVMRustDiagnosticLevel::Note;
1146 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1149 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1153 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1154 RustStringRef Str) {
1155 RawRustStringOstream OS(Str);
1156 DiagnosticPrinterRawOStream DP(OS);
1157 unwrap(DI)->print(DP);
1160 enum class LLVMRustDiagnosticKind {
1164 DebugMetadataVersion,
1167 OptimizationRemarkMissed,
1168 OptimizationRemarkAnalysis,
1169 OptimizationRemarkAnalysisFPCommute,
1170 OptimizationRemarkAnalysisAliasing,
1171 OptimizationRemarkOther,
1172 OptimizationFailure,
1179 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1182 return LLVMRustDiagnosticKind::InlineAsm;
1184 return LLVMRustDiagnosticKind::StackSize;
1185 case DK_DebugMetadataVersion:
1186 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1187 case DK_SampleProfile:
1188 return LLVMRustDiagnosticKind::SampleProfile;
1189 case DK_OptimizationRemark:
1190 case DK_MachineOptimizationRemark:
1191 return LLVMRustDiagnosticKind::OptimizationRemark;
1192 case DK_OptimizationRemarkMissed:
1193 case DK_MachineOptimizationRemarkMissed:
1194 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1195 case DK_OptimizationRemarkAnalysis:
1196 case DK_MachineOptimizationRemarkAnalysis:
1197 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1198 case DK_OptimizationRemarkAnalysisFPCommute:
1199 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1200 case DK_OptimizationRemarkAnalysisAliasing:
1201 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1203 return LLVMRustDiagnosticKind::PGOProfile;
1205 return LLVMRustDiagnosticKind::Linker;
1206 case DK_Unsupported:
1207 return LLVMRustDiagnosticKind::Unsupported;
1208 #if LLVM_VERSION_GE(13, 0)
1210 return LLVMRustDiagnosticKind::SrcMgr;
1213 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1214 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1215 : LLVMRustDiagnosticKind::Other;
1219 extern "C" LLVMRustDiagnosticKind
1220 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1221 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1224 // This is kept distinct from LLVMGetTypeKind, because when
1225 // a new type kind is added, the Rust-side enum must be
1226 // updated or UB will result.
1227 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1228 switch (unwrap(Ty)->getTypeID()) {
1229 case Type::VoidTyID:
1230 return LLVMVoidTypeKind;
1231 case Type::HalfTyID:
1232 return LLVMHalfTypeKind;
1233 case Type::FloatTyID:
1234 return LLVMFloatTypeKind;
1235 case Type::DoubleTyID:
1236 return LLVMDoubleTypeKind;
1237 case Type::X86_FP80TyID:
1238 return LLVMX86_FP80TypeKind;
1239 case Type::FP128TyID:
1240 return LLVMFP128TypeKind;
1241 case Type::PPC_FP128TyID:
1242 return LLVMPPC_FP128TypeKind;
1243 case Type::LabelTyID:
1244 return LLVMLabelTypeKind;
1245 case Type::MetadataTyID:
1246 return LLVMMetadataTypeKind;
1247 case Type::IntegerTyID:
1248 return LLVMIntegerTypeKind;
1249 case Type::FunctionTyID:
1250 return LLVMFunctionTypeKind;
1251 case Type::StructTyID:
1252 return LLVMStructTypeKind;
1253 case Type::ArrayTyID:
1254 return LLVMArrayTypeKind;
1255 case Type::PointerTyID:
1256 return LLVMPointerTypeKind;
1257 case Type::FixedVectorTyID:
1258 return LLVMVectorTypeKind;
1259 case Type::X86_MMXTyID:
1260 return LLVMX86_MMXTypeKind;
1261 case Type::TokenTyID:
1262 return LLVMTokenTypeKind;
1263 case Type::ScalableVectorTyID:
1264 return LLVMScalableVectorTypeKind;
1265 case Type::BFloatTyID:
1266 return LLVMBFloatTypeKind;
1267 case Type::X86_AMXTyID:
1268 return LLVMX86_AMXTypeKind;
1270 report_fatal_error("Unhandled TypeID.");
1273 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1275 #if LLVM_VERSION_LT(13, 0)
1276 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1278 using LLVMInlineAsmDiagHandlerTy = void*;
1281 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1282 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1283 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1284 // with LLVM 13 this function is gone.
1285 #if LLVM_VERSION_LT(13, 0)
1286 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1290 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1291 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1292 #if LLVM_VERSION_GE(13, 0)
1293 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1294 *Cookie = SM->getLocCookie();
1295 return wrap(&SM->getSMDiag());
1297 report_fatal_error("Shouldn't get called on older versions");
1301 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1302 RustStringRef MessageOut,
1303 RustStringRef BufferOut,
1304 LLVMRustDiagnosticLevel* LevelOut,
1306 unsigned* RangesOut,
1307 size_t* NumRanges) {
1308 SMDiagnostic& D = *unwrap(DRef);
1309 RawRustStringOstream MessageOS(MessageOut);
1310 MessageOS << D.getMessage();
1312 switch (D.getKind()) {
1313 case SourceMgr::DK_Error:
1314 *LevelOut = LLVMRustDiagnosticLevel::Error;
1316 case SourceMgr::DK_Warning:
1317 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1319 case SourceMgr::DK_Note:
1320 *LevelOut = LLVMRustDiagnosticLevel::Note;
1322 case SourceMgr::DK_Remark:
1323 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1326 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1329 if (D.getLoc() == SMLoc())
1332 const SourceMgr &LSM = *D.getSourceMgr();
1333 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1334 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1336 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1338 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1339 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1340 for (size_t i = 0; i < *NumRanges; i++) {
1341 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1342 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1348 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1349 LLVMValueRef ParentPad,
1351 LLVMValueRef *LLArgs,
1353 Value **Args = unwrap(LLArgs);
1354 if (ParentPad == nullptr) {
1355 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1356 ParentPad = wrap(Constant::getNullValue(Ty));
1358 return wrap(unwrap(B)->CreateCleanupPad(
1359 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1362 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1363 LLVMValueRef CleanupPad,
1364 LLVMBasicBlockRef UnwindBB) {
1365 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1366 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1369 extern "C" LLVMValueRef
1370 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1371 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1372 Value **Args = unwrap(LLArgs);
1373 return wrap(unwrap(B)->CreateCatchPad(
1374 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1377 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1379 LLVMBasicBlockRef BB) {
1380 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1384 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1385 LLVMValueRef ParentPad,
1386 LLVMBasicBlockRef BB,
1387 unsigned NumHandlers,
1389 if (ParentPad == nullptr) {
1390 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1391 ParentPad = wrap(Constant::getNullValue(Ty));
1393 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1394 NumHandlers, Name));
1397 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1398 LLVMBasicBlockRef Handler) {
1399 Value *CatchSwitch = unwrap(CatchSwitchRef);
1400 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1403 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1404 LLVMValueRef *Inputs,
1405 unsigned NumInputs) {
1406 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1409 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1413 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1414 LLVMValueRef *Args, unsigned NumArgs,
1415 OperandBundleDef *Bundle) {
1416 Value *Callee = unwrap(Fn);
1417 FunctionType *FTy = unwrap<FunctionType>(Ty);
1418 unsigned Len = Bundle ? 1 : 0;
1419 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1420 return wrap(unwrap(B)->CreateCall(
1421 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1424 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1425 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1426 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1429 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1430 LLVMValueRef Dst, unsigned DstAlign,
1431 LLVMValueRef Src, unsigned SrcAlign,
1432 LLVMValueRef Size, bool IsVolatile) {
1433 return wrap(unwrap(B)->CreateMemCpy(
1434 unwrap(Dst), MaybeAlign(DstAlign),
1435 unwrap(Src), MaybeAlign(SrcAlign),
1436 unwrap(Size), IsVolatile));
1439 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1440 LLVMValueRef Dst, unsigned DstAlign,
1441 LLVMValueRef Src, unsigned SrcAlign,
1442 LLVMValueRef Size, bool IsVolatile) {
1443 return wrap(unwrap(B)->CreateMemMove(
1444 unwrap(Dst), MaybeAlign(DstAlign),
1445 unwrap(Src), MaybeAlign(SrcAlign),
1446 unwrap(Size), IsVolatile));
1449 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1450 LLVMValueRef Dst, unsigned DstAlign,
1452 LLVMValueRef Size, bool IsVolatile) {
1453 return wrap(unwrap(B)->CreateMemSet(
1454 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1457 extern "C" LLVMValueRef
1458 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1459 LLVMValueRef *Args, unsigned NumArgs,
1460 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1461 OperandBundleDef *Bundle, const char *Name) {
1462 Value *Callee = unwrap(Fn);
1463 FunctionType *FTy = unwrap<FunctionType>(Ty);
1464 unsigned Len = Bundle ? 1 : 0;
1465 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1466 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1467 makeArrayRef(unwrap(Args), NumArgs),
1471 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1472 LLVMBasicBlockRef BB) {
1473 auto Point = unwrap(BB)->getFirstInsertionPt();
1474 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1477 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1478 const char *Name, size_t NameLen) {
1479 Triple TargetTriple(unwrap(M)->getTargetTriple());
1480 GlobalObject *GV = unwrap<GlobalObject>(V);
1481 if (TargetTriple.supportsCOMDAT()) {
1482 StringRef NameRef(Name, NameLen);
1483 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1487 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1488 GlobalObject *GV = unwrap<GlobalObject>(V);
1489 GV->setComdat(nullptr);
1492 enum class LLVMRustLinkage {
1493 ExternalLinkage = 0,
1494 AvailableExternallyLinkage = 1,
1495 LinkOnceAnyLinkage = 2,
1496 LinkOnceODRLinkage = 3,
1499 AppendingLinkage = 6,
1500 InternalLinkage = 7,
1502 ExternalWeakLinkage = 9,
1506 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1508 case LLVMExternalLinkage:
1509 return LLVMRustLinkage::ExternalLinkage;
1510 case LLVMAvailableExternallyLinkage:
1511 return LLVMRustLinkage::AvailableExternallyLinkage;
1512 case LLVMLinkOnceAnyLinkage:
1513 return LLVMRustLinkage::LinkOnceAnyLinkage;
1514 case LLVMLinkOnceODRLinkage:
1515 return LLVMRustLinkage::LinkOnceODRLinkage;
1516 case LLVMWeakAnyLinkage:
1517 return LLVMRustLinkage::WeakAnyLinkage;
1518 case LLVMWeakODRLinkage:
1519 return LLVMRustLinkage::WeakODRLinkage;
1520 case LLVMAppendingLinkage:
1521 return LLVMRustLinkage::AppendingLinkage;
1522 case LLVMInternalLinkage:
1523 return LLVMRustLinkage::InternalLinkage;
1524 case LLVMPrivateLinkage:
1525 return LLVMRustLinkage::PrivateLinkage;
1526 case LLVMExternalWeakLinkage:
1527 return LLVMRustLinkage::ExternalWeakLinkage;
1528 case LLVMCommonLinkage:
1529 return LLVMRustLinkage::CommonLinkage;
1531 report_fatal_error("Invalid LLVMRustLinkage value!");
1535 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1537 case LLVMRustLinkage::ExternalLinkage:
1538 return LLVMExternalLinkage;
1539 case LLVMRustLinkage::AvailableExternallyLinkage:
1540 return LLVMAvailableExternallyLinkage;
1541 case LLVMRustLinkage::LinkOnceAnyLinkage:
1542 return LLVMLinkOnceAnyLinkage;
1543 case LLVMRustLinkage::LinkOnceODRLinkage:
1544 return LLVMLinkOnceODRLinkage;
1545 case LLVMRustLinkage::WeakAnyLinkage:
1546 return LLVMWeakAnyLinkage;
1547 case LLVMRustLinkage::WeakODRLinkage:
1548 return LLVMWeakODRLinkage;
1549 case LLVMRustLinkage::AppendingLinkage:
1550 return LLVMAppendingLinkage;
1551 case LLVMRustLinkage::InternalLinkage:
1552 return LLVMInternalLinkage;
1553 case LLVMRustLinkage::PrivateLinkage:
1554 return LLVMPrivateLinkage;
1555 case LLVMRustLinkage::ExternalWeakLinkage:
1556 return LLVMExternalWeakLinkage;
1557 case LLVMRustLinkage::CommonLinkage:
1558 return LLVMCommonLinkage;
1560 report_fatal_error("Invalid LLVMRustLinkage value!");
1563 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1564 return toRust(LLVMGetLinkage(V));
1567 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1568 LLVMRustLinkage RustLinkage) {
1569 LLVMSetLinkage(V, fromRust(RustLinkage));
1572 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1573 LLVMValueRef ConstantVal,
1574 LLVMValueRef *ConstantIndices,
1575 unsigned NumIndices) {
1576 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1578 Constant *Val = unwrap<Constant>(ConstantVal);
1579 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1582 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1583 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1584 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1586 auto C = unwrap<llvm::ConstantInt>(CV);
1587 if (C->getBitWidth() > 128) { return false; }
1590 AP = C->getValue().sextOrSelf(128);
1592 AP = C->getValue().zextOrSelf(128);
1594 *low = AP.getLoBits(64).getZExtValue();
1595 *high = AP.getHiBits(64).getZExtValue();
1599 enum class LLVMRustVisibility {
1605 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1607 case LLVMDefaultVisibility:
1608 return LLVMRustVisibility::Default;
1609 case LLVMHiddenVisibility:
1610 return LLVMRustVisibility::Hidden;
1611 case LLVMProtectedVisibility:
1612 return LLVMRustVisibility::Protected;
1614 report_fatal_error("Invalid LLVMRustVisibility value!");
1617 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1619 case LLVMRustVisibility::Default:
1620 return LLVMDefaultVisibility;
1621 case LLVMRustVisibility::Hidden:
1622 return LLVMHiddenVisibility;
1623 case LLVMRustVisibility::Protected:
1624 return LLVMProtectedVisibility;
1626 report_fatal_error("Invalid LLVMRustVisibility value!");
1629 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1630 return toRust(LLVMGetVisibility(V));
1633 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1634 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1635 LLVMTypeRef DestTy, bool isSigned) {
1636 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1639 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1640 LLVMRustVisibility RustVisibility) {
1641 LLVMSetVisibility(V, fromRust(RustVisibility));
1644 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1645 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1648 struct LLVMRustModuleBuffer {
1652 extern "C" LLVMRustModuleBuffer*
1653 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1654 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1656 raw_string_ostream OS(Ret->data);
1658 legacy::PassManager PM;
1659 PM.add(createBitcodeWriterPass(OS));
1663 return Ret.release();
1667 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1671 extern "C" const void*
1672 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1673 return Buffer->data.data();
1677 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1678 return Buffer->data.length();
1682 LLVMRustModuleCost(LLVMModuleRef M) {
1683 auto f = unwrap(M)->functions();
1684 return std::distance(std::begin(f), std::end(f));
1687 // Vector reductions:
1688 extern "C" LLVMValueRef
1689 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1690 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1692 extern "C" LLVMValueRef
1693 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1694 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1696 extern "C" LLVMValueRef
1697 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1698 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1700 extern "C" LLVMValueRef
1701 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1702 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1704 extern "C" LLVMValueRef
1705 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1706 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1708 extern "C" LLVMValueRef
1709 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1710 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1712 extern "C" LLVMValueRef
1713 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1714 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1716 extern "C" LLVMValueRef
1717 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1718 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1720 extern "C" LLVMValueRef
1721 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1722 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1724 extern "C" LLVMValueRef
1725 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1726 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1727 I->setHasNoNaNs(NoNaN);
1730 extern "C" LLVMValueRef
1731 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1732 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1733 I->setHasNoNaNs(NoNaN);
1737 extern "C" LLVMValueRef
1738 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1739 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1741 extern "C" LLVMValueRef
1742 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1743 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1746 // This struct contains all necessary info about a symbol exported from a DLL.
1747 struct LLVMRustCOFFShortExport {
1749 bool ordinal_present;
1750 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1754 // Machine must be a COFF machine type, as defined in PE specs.
1755 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1756 const char* ImportName,
1758 const LLVMRustCOFFShortExport* Exports,
1763 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1764 ConvertedExports.reserve(NumExports);
1766 for (size_t i = 0; i < NumExports; ++i) {
1767 bool ordinal_present = Exports[i].ordinal_present;
1768 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1769 ConvertedExports.push_back(llvm::object::COFFShortExport{
1770 Exports[i].name, // Name
1771 std::string{}, // ExtName
1772 std::string{}, // SymbolName
1773 std::string{}, // AliasTarget
1775 ordinal_present, // Noname
1782 auto Error = llvm::object::writeImportLibrary(
1786 static_cast<llvm::COFF::MachineTypes>(Machine),
1789 std::string errorString;
1790 llvm::raw_string_ostream stream(errorString);
1793 LLVMRustSetLastError(errorString.c_str());
1794 return LLVMRustResult::Failure;
1796 return LLVMRustResult::Success;
1800 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1801 extern "C" DiagnosticHandler *
1802 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1803 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1804 return DH.release();
1807 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1808 // handling. Ownership of the handler is moved to the LLVMContext.
1809 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1810 DiagnosticHandler *DH) {
1811 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1814 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1816 // Configures a diagnostic handler that invokes provided callback when a
1817 // backend needs to emit a diagnostic.
1819 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1820 // the RemarkPasses array specifies individual passes for which remarks will be
1822 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1823 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1824 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1825 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1827 class RustDiagnosticHandler final : public DiagnosticHandler {
1829 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1830 void *DiagnosticHandlerContext,
1831 bool RemarkAllPasses,
1832 std::vector<std::string> RemarkPasses)
1833 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1834 DiagnosticHandlerContext(DiagnosticHandlerContext),
1835 RemarkAllPasses(RemarkAllPasses),
1836 RemarkPasses(RemarkPasses) {}
1838 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1839 if (DiagnosticHandlerCallback) {
1840 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1846 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1847 return isRemarkEnabled(PassName);
1850 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1851 return isRemarkEnabled(PassName);
1854 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1855 return isRemarkEnabled(PassName);
1858 bool isAnyRemarkEnabled() const override {
1859 return RemarkAllPasses || !RemarkPasses.empty();
1863 bool isRemarkEnabled(StringRef PassName) const {
1864 if (RemarkAllPasses)
1867 for (auto &Pass : RemarkPasses)
1868 if (Pass == PassName)
1874 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1875 void *DiagnosticHandlerContext = nullptr;
1877 bool RemarkAllPasses = false;
1878 std::vector<std::string> RemarkPasses;
1881 std::vector<std::string> Passes;
1882 for (size_t I = 0; I != RemarkPassesLen; ++I)
1883 Passes.push_back(RemarkPasses[I]);
1885 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1886 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));