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" bool LLVMRustIsRustLLVM() {
727 extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
729 unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
732 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
733 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
736 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
737 return new DIBuilder(*unwrap(M));
740 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
744 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
748 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
749 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
750 const char *Producer, size_t ProducerLen, bool isOptimized,
751 const char *Flags, unsigned RuntimeVer,
752 const char *SplitName, size_t SplitNameLen,
753 LLVMRustDebugEmissionKind Kind,
754 uint64_t DWOId, bool SplitDebugInlining) {
755 auto *File = unwrapDI<DIFile>(FileRef);
757 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
758 isOptimized, Flags, RuntimeVer,
759 StringRef(SplitName, SplitNameLen),
760 fromRust(Kind), DWOId, SplitDebugInlining));
763 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
764 LLVMRustDIBuilderRef Builder,
765 const char *Filename, size_t FilenameLen,
766 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
767 const char *Checksum, size_t ChecksumLen) {
768 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
769 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
771 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
772 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
773 StringRef(Directory, DirectoryLen),
777 extern "C" LLVMMetadataRef
778 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
779 LLVMMetadataRef ParameterTypes) {
780 return wrap(Builder->createSubroutineType(
781 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
784 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
785 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
786 const char *Name, size_t NameLen,
787 const char *LinkageName, size_t LinkageNameLen,
788 LLVMMetadataRef File, unsigned LineNo,
789 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
790 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
791 LLVMMetadataRef Decl) {
792 DITemplateParameterArray TParams =
793 DITemplateParameterArray(unwrap<MDTuple>(TParam));
794 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
795 DINode::DIFlags llvmFlags = fromRust(Flags);
796 DISubprogram *Sub = Builder->createFunction(
797 unwrapDI<DIScope>(Scope),
798 StringRef(Name, NameLen),
799 StringRef(LinkageName, LinkageNameLen),
800 unwrapDI<DIFile>(File), LineNo,
801 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
802 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
804 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
808 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
809 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
810 uint64_t SizeInBits, unsigned Encoding) {
811 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
814 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
815 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
816 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
817 return wrap(Builder->createTypedef(
818 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
819 LineNo, unwrapDIPtr<DIScope>(Scope)));
822 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
823 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
824 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
825 const char *Name, size_t NameLen) {
826 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
827 SizeInBits, AlignInBits,
829 StringRef(Name, NameLen)));
832 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
833 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
834 const char *Name, size_t NameLen,
835 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
836 uint32_t AlignInBits, LLVMRustDIFlags Flags,
837 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
838 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
839 const char *UniqueId, size_t UniqueIdLen) {
840 return wrap(Builder->createStructType(
841 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
842 unwrapDI<DIFile>(File), LineNumber,
843 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
844 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
845 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
848 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
849 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
850 const char *Name, size_t NameLen,
851 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
852 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
853 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
854 return wrap(Builder->createVariantPart(
855 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
856 unwrapDI<DIFile>(File), LineNumber,
857 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
858 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
861 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
862 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
863 const char *Name, size_t NameLen,
864 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
865 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
866 LLVMMetadataRef Ty) {
867 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
868 StringRef(Name, NameLen),
869 unwrapDI<DIFile>(File), LineNo,
870 SizeInBits, AlignInBits, OffsetInBits,
871 fromRust(Flags), unwrapDI<DIType>(Ty)));
874 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
875 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
876 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
877 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
878 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
879 llvm::ConstantInt* D = nullptr;
881 D = unwrap<llvm::ConstantInt>(Discriminant);
883 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
884 StringRef(Name, NameLen),
885 unwrapDI<DIFile>(File), LineNo,
886 SizeInBits, AlignInBits, OffsetInBits, D,
887 fromRust(Flags), unwrapDI<DIType>(Ty)));
890 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
891 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
892 LLVMMetadataRef File, unsigned Line, unsigned Col) {
893 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
894 unwrapDI<DIFile>(File), Line, Col));
897 extern "C" LLVMMetadataRef
898 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
899 LLVMMetadataRef Scope,
900 LLVMMetadataRef File) {
901 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
902 unwrapDI<DIFile>(File)));
905 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
906 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
907 const char *Name, size_t NameLen,
908 const char *LinkageName, size_t LinkageNameLen,
909 LLVMMetadataRef File, unsigned LineNo,
910 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
911 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
912 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
914 llvm::DIExpression *InitExpr = nullptr;
915 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
916 InitExpr = Builder->createConstantValueExpression(
917 IntVal->getValue().getSExtValue());
918 } else if (llvm::ConstantFP *FPVal =
919 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
920 InitExpr = Builder->createConstantValueExpression(
921 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
924 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
925 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
926 StringRef(LinkageName, LinkageNameLen),
927 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
928 /* isDefined */ true,
929 InitExpr, unwrapDIPtr<MDNode>(Decl),
930 /* templateParams */ nullptr,
933 InitVal->setMetadata("dbg", VarExpr);
935 return wrap(VarExpr);
938 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
939 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
940 const char *Name, size_t NameLen,
941 LLVMMetadataRef File, unsigned LineNo,
942 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
943 unsigned ArgNo, uint32_t AlignInBits) {
944 if (Tag == 0x100) { // DW_TAG_auto_variable
945 return wrap(Builder->createAutoVariable(
946 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
947 unwrapDI<DIFile>(File), LineNo,
948 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
950 return wrap(Builder->createParameterVariable(
951 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
952 unwrapDI<DIFile>(File), LineNo,
953 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
957 extern "C" LLVMMetadataRef
958 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
959 uint32_t AlignInBits, LLVMMetadataRef Ty,
960 LLVMMetadataRef Subscripts) {
962 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
963 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
966 extern "C" LLVMMetadataRef
967 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
969 return wrap(Builder->getOrCreateSubrange(Lo, Count));
972 extern "C" LLVMMetadataRef
973 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
974 LLVMMetadataRef *Ptr, unsigned Count) {
975 Metadata **DataValue = unwrap(Ptr);
977 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
980 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
981 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
982 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
983 LLVMBasicBlockRef InsertAtEnd) {
984 return wrap(Builder->insertDeclare(
985 unwrap(V), unwrap<DILocalVariable>(VarInfo),
986 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
987 DebugLoc(cast<MDNode>(unwrap(DL))),
988 unwrap(InsertAtEnd)));
991 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
992 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
993 int64_t Value, bool IsUnsigned) {
994 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
997 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
998 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
999 const char *Name, size_t NameLen,
1000 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1001 uint32_t AlignInBits, LLVMMetadataRef Elements,
1002 LLVMMetadataRef ClassTy, bool IsScoped) {
1003 return wrap(Builder->createEnumerationType(
1004 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
1005 unwrapDI<DIFile>(File), LineNumber,
1006 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
1007 unwrapDI<DIType>(ClassTy), "", IsScoped));
1010 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
1011 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1012 const char *Name, size_t NameLen,
1013 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1014 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
1015 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
1016 return wrap(Builder->createUnionType(
1017 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1018 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1019 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1020 StringRef(UniqueId, UniqueIdLen)));
1023 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1024 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1025 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1026 bool IsDefault = false; // FIXME: should we ever set this true?
1027 return wrap(Builder->createTemplateTypeParameter(
1028 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1031 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1032 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1033 const char *Name, size_t NameLen, bool ExportSymbols) {
1034 return wrap(Builder->createNameSpace(
1035 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1040 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1041 LLVMMetadataRef CompositeTy,
1042 LLVMMetadataRef Elements,
1043 LLVMMetadataRef Params) {
1044 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1045 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1046 DINodeArray(unwrap<MDTuple>(Params)));
1049 extern "C" LLVMMetadataRef
1050 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1051 LLVMMetadataRef ScopeRef,
1052 LLVMMetadataRef InlinedAt) {
1053 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1054 DILocation *Loc = DILocation::get(
1055 Scope->getContext(), Line, Column, Scope,
1056 unwrapDIPtr<MDNode>(InlinedAt));
1060 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1061 return dwarf::DW_OP_deref;
1064 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1065 return dwarf::DW_OP_plus_uconst;
1068 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1069 RawRustStringOstream OS(Str);
1070 unwrap<llvm::Type>(Ty)->print(OS);
1073 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1074 RustStringRef Str) {
1075 RawRustStringOstream OS(Str);
1080 unwrap<llvm::Value>(V)->getType()->print(OS);
1082 unwrap<llvm::Value>(V)->print(OS);
1087 // LLVMArrayType function does not support 64-bit ElementCount
1088 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1089 uint64_t ElementCount) {
1090 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1093 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1095 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1096 RawRustStringOstream OS(Str);
1097 unwrap(T)->print(OS);
1100 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1101 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1102 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1103 RustStringRef FilenameOut, RustStringRef MessageOut) {
1104 // Undefined to call this not on an optimization diagnostic!
1105 llvm::DiagnosticInfoOptimizationBase *Opt =
1106 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1108 RawRustStringOstream PassNameOS(PassNameOut);
1109 PassNameOS << Opt->getPassName();
1110 *FunctionOut = wrap(&Opt->getFunction());
1112 RawRustStringOstream FilenameOS(FilenameOut);
1113 DiagnosticLocation loc = Opt->getLocation();
1114 if (loc.isValid()) {
1115 *Line = loc.getLine();
1116 *Column = loc.getColumn();
1117 FilenameOS << loc.getAbsolutePath();
1120 RawRustStringOstream MessageOS(MessageOut);
1121 MessageOS << Opt->getMsg();
1124 enum class LLVMRustDiagnosticLevel {
1132 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1133 LLVMRustDiagnosticLevel *LevelOut,
1134 unsigned *CookieOut,
1135 LLVMTwineRef *MessageOut) {
1136 // Undefined to call this not on an inline assembly diagnostic!
1137 llvm::DiagnosticInfoInlineAsm *IA =
1138 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1140 *CookieOut = IA->getLocCookie();
1141 *MessageOut = wrap(&IA->getMsgStr());
1143 switch (IA->getSeverity()) {
1145 *LevelOut = LLVMRustDiagnosticLevel::Error;
1148 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1151 *LevelOut = LLVMRustDiagnosticLevel::Note;
1154 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1157 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1161 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1162 RustStringRef Str) {
1163 RawRustStringOstream OS(Str);
1164 DiagnosticPrinterRawOStream DP(OS);
1165 unwrap(DI)->print(DP);
1168 enum class LLVMRustDiagnosticKind {
1172 DebugMetadataVersion,
1175 OptimizationRemarkMissed,
1176 OptimizationRemarkAnalysis,
1177 OptimizationRemarkAnalysisFPCommute,
1178 OptimizationRemarkAnalysisAliasing,
1179 OptimizationRemarkOther,
1180 OptimizationFailure,
1187 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1190 return LLVMRustDiagnosticKind::InlineAsm;
1192 return LLVMRustDiagnosticKind::StackSize;
1193 case DK_DebugMetadataVersion:
1194 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1195 case DK_SampleProfile:
1196 return LLVMRustDiagnosticKind::SampleProfile;
1197 case DK_OptimizationRemark:
1198 case DK_MachineOptimizationRemark:
1199 return LLVMRustDiagnosticKind::OptimizationRemark;
1200 case DK_OptimizationRemarkMissed:
1201 case DK_MachineOptimizationRemarkMissed:
1202 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1203 case DK_OptimizationRemarkAnalysis:
1204 case DK_MachineOptimizationRemarkAnalysis:
1205 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1206 case DK_OptimizationRemarkAnalysisFPCommute:
1207 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1208 case DK_OptimizationRemarkAnalysisAliasing:
1209 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1211 return LLVMRustDiagnosticKind::PGOProfile;
1213 return LLVMRustDiagnosticKind::Linker;
1214 case DK_Unsupported:
1215 return LLVMRustDiagnosticKind::Unsupported;
1216 #if LLVM_VERSION_GE(13, 0)
1218 return LLVMRustDiagnosticKind::SrcMgr;
1221 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1222 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1223 : LLVMRustDiagnosticKind::Other;
1227 extern "C" LLVMRustDiagnosticKind
1228 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1229 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1232 // This is kept distinct from LLVMGetTypeKind, because when
1233 // a new type kind is added, the Rust-side enum must be
1234 // updated or UB will result.
1235 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1236 switch (unwrap(Ty)->getTypeID()) {
1237 case Type::VoidTyID:
1238 return LLVMVoidTypeKind;
1239 case Type::HalfTyID:
1240 return LLVMHalfTypeKind;
1241 case Type::FloatTyID:
1242 return LLVMFloatTypeKind;
1243 case Type::DoubleTyID:
1244 return LLVMDoubleTypeKind;
1245 case Type::X86_FP80TyID:
1246 return LLVMX86_FP80TypeKind;
1247 case Type::FP128TyID:
1248 return LLVMFP128TypeKind;
1249 case Type::PPC_FP128TyID:
1250 return LLVMPPC_FP128TypeKind;
1251 case Type::LabelTyID:
1252 return LLVMLabelTypeKind;
1253 case Type::MetadataTyID:
1254 return LLVMMetadataTypeKind;
1255 case Type::IntegerTyID:
1256 return LLVMIntegerTypeKind;
1257 case Type::FunctionTyID:
1258 return LLVMFunctionTypeKind;
1259 case Type::StructTyID:
1260 return LLVMStructTypeKind;
1261 case Type::ArrayTyID:
1262 return LLVMArrayTypeKind;
1263 case Type::PointerTyID:
1264 return LLVMPointerTypeKind;
1265 case Type::FixedVectorTyID:
1266 return LLVMVectorTypeKind;
1267 case Type::X86_MMXTyID:
1268 return LLVMX86_MMXTypeKind;
1269 case Type::TokenTyID:
1270 return LLVMTokenTypeKind;
1271 case Type::ScalableVectorTyID:
1272 return LLVMScalableVectorTypeKind;
1273 case Type::BFloatTyID:
1274 return LLVMBFloatTypeKind;
1275 case Type::X86_AMXTyID:
1276 return LLVMX86_AMXTypeKind;
1278 report_fatal_error("Unhandled TypeID.");
1281 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1283 #if LLVM_VERSION_LT(13, 0)
1284 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1286 using LLVMInlineAsmDiagHandlerTy = void*;
1289 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1290 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1291 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1292 // with LLVM 13 this function is gone.
1293 #if LLVM_VERSION_LT(13, 0)
1294 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1298 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1299 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1300 #if LLVM_VERSION_GE(13, 0)
1301 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1302 *Cookie = SM->getLocCookie();
1303 return wrap(&SM->getSMDiag());
1305 report_fatal_error("Shouldn't get called on older versions");
1309 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1310 RustStringRef MessageOut,
1311 RustStringRef BufferOut,
1312 LLVMRustDiagnosticLevel* LevelOut,
1314 unsigned* RangesOut,
1315 size_t* NumRanges) {
1316 SMDiagnostic& D = *unwrap(DRef);
1317 RawRustStringOstream MessageOS(MessageOut);
1318 MessageOS << D.getMessage();
1320 switch (D.getKind()) {
1321 case SourceMgr::DK_Error:
1322 *LevelOut = LLVMRustDiagnosticLevel::Error;
1324 case SourceMgr::DK_Warning:
1325 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1327 case SourceMgr::DK_Note:
1328 *LevelOut = LLVMRustDiagnosticLevel::Note;
1330 case SourceMgr::DK_Remark:
1331 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1334 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1337 if (D.getLoc() == SMLoc())
1340 const SourceMgr &LSM = *D.getSourceMgr();
1341 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1342 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1344 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1346 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1347 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1348 for (size_t i = 0; i < *NumRanges; i++) {
1349 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1350 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1356 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1357 LLVMValueRef ParentPad,
1359 LLVMValueRef *LLArgs,
1361 Value **Args = unwrap(LLArgs);
1362 if (ParentPad == nullptr) {
1363 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1364 ParentPad = wrap(Constant::getNullValue(Ty));
1366 return wrap(unwrap(B)->CreateCleanupPad(
1367 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1370 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1371 LLVMValueRef CleanupPad,
1372 LLVMBasicBlockRef UnwindBB) {
1373 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1374 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1377 extern "C" LLVMValueRef
1378 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1379 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1380 Value **Args = unwrap(LLArgs);
1381 return wrap(unwrap(B)->CreateCatchPad(
1382 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1385 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1387 LLVMBasicBlockRef BB) {
1388 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1392 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1393 LLVMValueRef ParentPad,
1394 LLVMBasicBlockRef BB,
1395 unsigned NumHandlers,
1397 if (ParentPad == nullptr) {
1398 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1399 ParentPad = wrap(Constant::getNullValue(Ty));
1401 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1402 NumHandlers, Name));
1405 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1406 LLVMBasicBlockRef Handler) {
1407 Value *CatchSwitch = unwrap(CatchSwitchRef);
1408 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1411 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1412 LLVMValueRef *Inputs,
1413 unsigned NumInputs) {
1414 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1417 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1421 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1422 LLVMValueRef *Args, unsigned NumArgs,
1423 OperandBundleDef *Bundle) {
1424 Value *Callee = unwrap(Fn);
1425 FunctionType *FTy = unwrap<FunctionType>(Ty);
1426 unsigned Len = Bundle ? 1 : 0;
1427 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1428 return wrap(unwrap(B)->CreateCall(
1429 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1432 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1433 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1434 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1437 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1438 LLVMValueRef Dst, unsigned DstAlign,
1439 LLVMValueRef Src, unsigned SrcAlign,
1440 LLVMValueRef Size, bool IsVolatile) {
1441 return wrap(unwrap(B)->CreateMemCpy(
1442 unwrap(Dst), MaybeAlign(DstAlign),
1443 unwrap(Src), MaybeAlign(SrcAlign),
1444 unwrap(Size), IsVolatile));
1447 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1448 LLVMValueRef Dst, unsigned DstAlign,
1449 LLVMValueRef Src, unsigned SrcAlign,
1450 LLVMValueRef Size, bool IsVolatile) {
1451 return wrap(unwrap(B)->CreateMemMove(
1452 unwrap(Dst), MaybeAlign(DstAlign),
1453 unwrap(Src), MaybeAlign(SrcAlign),
1454 unwrap(Size), IsVolatile));
1457 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1458 LLVMValueRef Dst, unsigned DstAlign,
1460 LLVMValueRef Size, bool IsVolatile) {
1461 return wrap(unwrap(B)->CreateMemSet(
1462 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1465 extern "C" LLVMValueRef
1466 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1467 LLVMValueRef *Args, unsigned NumArgs,
1468 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1469 OperandBundleDef *Bundle, const char *Name) {
1470 Value *Callee = unwrap(Fn);
1471 FunctionType *FTy = unwrap<FunctionType>(Ty);
1472 unsigned Len = Bundle ? 1 : 0;
1473 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1474 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1475 makeArrayRef(unwrap(Args), NumArgs),
1479 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1480 LLVMBasicBlockRef BB) {
1481 auto Point = unwrap(BB)->getFirstInsertionPt();
1482 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1485 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1486 const char *Name, size_t NameLen) {
1487 Triple TargetTriple(unwrap(M)->getTargetTriple());
1488 GlobalObject *GV = unwrap<GlobalObject>(V);
1489 if (TargetTriple.supportsCOMDAT()) {
1490 StringRef NameRef(Name, NameLen);
1491 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1495 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1496 GlobalObject *GV = unwrap<GlobalObject>(V);
1497 GV->setComdat(nullptr);
1500 enum class LLVMRustLinkage {
1501 ExternalLinkage = 0,
1502 AvailableExternallyLinkage = 1,
1503 LinkOnceAnyLinkage = 2,
1504 LinkOnceODRLinkage = 3,
1507 AppendingLinkage = 6,
1508 InternalLinkage = 7,
1510 ExternalWeakLinkage = 9,
1514 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1516 case LLVMExternalLinkage:
1517 return LLVMRustLinkage::ExternalLinkage;
1518 case LLVMAvailableExternallyLinkage:
1519 return LLVMRustLinkage::AvailableExternallyLinkage;
1520 case LLVMLinkOnceAnyLinkage:
1521 return LLVMRustLinkage::LinkOnceAnyLinkage;
1522 case LLVMLinkOnceODRLinkage:
1523 return LLVMRustLinkage::LinkOnceODRLinkage;
1524 case LLVMWeakAnyLinkage:
1525 return LLVMRustLinkage::WeakAnyLinkage;
1526 case LLVMWeakODRLinkage:
1527 return LLVMRustLinkage::WeakODRLinkage;
1528 case LLVMAppendingLinkage:
1529 return LLVMRustLinkage::AppendingLinkage;
1530 case LLVMInternalLinkage:
1531 return LLVMRustLinkage::InternalLinkage;
1532 case LLVMPrivateLinkage:
1533 return LLVMRustLinkage::PrivateLinkage;
1534 case LLVMExternalWeakLinkage:
1535 return LLVMRustLinkage::ExternalWeakLinkage;
1536 case LLVMCommonLinkage:
1537 return LLVMRustLinkage::CommonLinkage;
1539 report_fatal_error("Invalid LLVMRustLinkage value!");
1543 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1545 case LLVMRustLinkage::ExternalLinkage:
1546 return LLVMExternalLinkage;
1547 case LLVMRustLinkage::AvailableExternallyLinkage:
1548 return LLVMAvailableExternallyLinkage;
1549 case LLVMRustLinkage::LinkOnceAnyLinkage:
1550 return LLVMLinkOnceAnyLinkage;
1551 case LLVMRustLinkage::LinkOnceODRLinkage:
1552 return LLVMLinkOnceODRLinkage;
1553 case LLVMRustLinkage::WeakAnyLinkage:
1554 return LLVMWeakAnyLinkage;
1555 case LLVMRustLinkage::WeakODRLinkage:
1556 return LLVMWeakODRLinkage;
1557 case LLVMRustLinkage::AppendingLinkage:
1558 return LLVMAppendingLinkage;
1559 case LLVMRustLinkage::InternalLinkage:
1560 return LLVMInternalLinkage;
1561 case LLVMRustLinkage::PrivateLinkage:
1562 return LLVMPrivateLinkage;
1563 case LLVMRustLinkage::ExternalWeakLinkage:
1564 return LLVMExternalWeakLinkage;
1565 case LLVMRustLinkage::CommonLinkage:
1566 return LLVMCommonLinkage;
1568 report_fatal_error("Invalid LLVMRustLinkage value!");
1571 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1572 return toRust(LLVMGetLinkage(V));
1575 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1576 LLVMRustLinkage RustLinkage) {
1577 LLVMSetLinkage(V, fromRust(RustLinkage));
1580 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1581 LLVMValueRef ConstantVal,
1582 LLVMValueRef *ConstantIndices,
1583 unsigned NumIndices) {
1584 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1586 Constant *Val = unwrap<Constant>(ConstantVal);
1587 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1590 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1591 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1592 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1594 auto C = unwrap<llvm::ConstantInt>(CV);
1595 if (C->getBitWidth() > 128) { return false; }
1598 AP = C->getValue().sextOrSelf(128);
1600 AP = C->getValue().zextOrSelf(128);
1602 *low = AP.getLoBits(64).getZExtValue();
1603 *high = AP.getHiBits(64).getZExtValue();
1607 enum class LLVMRustVisibility {
1613 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1615 case LLVMDefaultVisibility:
1616 return LLVMRustVisibility::Default;
1617 case LLVMHiddenVisibility:
1618 return LLVMRustVisibility::Hidden;
1619 case LLVMProtectedVisibility:
1620 return LLVMRustVisibility::Protected;
1622 report_fatal_error("Invalid LLVMRustVisibility value!");
1625 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1627 case LLVMRustVisibility::Default:
1628 return LLVMDefaultVisibility;
1629 case LLVMRustVisibility::Hidden:
1630 return LLVMHiddenVisibility;
1631 case LLVMRustVisibility::Protected:
1632 return LLVMProtectedVisibility;
1634 report_fatal_error("Invalid LLVMRustVisibility value!");
1637 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1638 return toRust(LLVMGetVisibility(V));
1641 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1642 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1643 LLVMTypeRef DestTy, bool isSigned) {
1644 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1647 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1648 LLVMRustVisibility RustVisibility) {
1649 LLVMSetVisibility(V, fromRust(RustVisibility));
1652 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1653 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1656 struct LLVMRustModuleBuffer {
1660 extern "C" LLVMRustModuleBuffer*
1661 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1662 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1664 raw_string_ostream OS(Ret->data);
1666 legacy::PassManager PM;
1667 PM.add(createBitcodeWriterPass(OS));
1671 return Ret.release();
1675 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1679 extern "C" const void*
1680 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1681 return Buffer->data.data();
1685 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1686 return Buffer->data.length();
1690 LLVMRustModuleCost(LLVMModuleRef M) {
1691 auto f = unwrap(M)->functions();
1692 return std::distance(std::begin(f), std::end(f));
1695 // Vector reductions:
1696 extern "C" LLVMValueRef
1697 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1698 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1700 extern "C" LLVMValueRef
1701 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1702 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1704 extern "C" LLVMValueRef
1705 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1706 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1708 extern "C" LLVMValueRef
1709 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1710 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1712 extern "C" LLVMValueRef
1713 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1714 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1716 extern "C" LLVMValueRef
1717 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1718 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1720 extern "C" LLVMValueRef
1721 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1722 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1724 extern "C" LLVMValueRef
1725 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1726 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1728 extern "C" LLVMValueRef
1729 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1730 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1732 extern "C" LLVMValueRef
1733 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1734 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1735 I->setHasNoNaNs(NoNaN);
1738 extern "C" LLVMValueRef
1739 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1740 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1741 I->setHasNoNaNs(NoNaN);
1745 extern "C" LLVMValueRef
1746 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1747 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1749 extern "C" LLVMValueRef
1750 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1751 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1754 // This struct contains all necessary info about a symbol exported from a DLL.
1755 struct LLVMRustCOFFShortExport {
1757 bool ordinal_present;
1758 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1762 // Machine must be a COFF machine type, as defined in PE specs.
1763 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1764 const char* ImportName,
1766 const LLVMRustCOFFShortExport* Exports,
1771 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1772 ConvertedExports.reserve(NumExports);
1774 for (size_t i = 0; i < NumExports; ++i) {
1775 bool ordinal_present = Exports[i].ordinal_present;
1776 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1777 ConvertedExports.push_back(llvm::object::COFFShortExport{
1778 Exports[i].name, // Name
1779 std::string{}, // ExtName
1780 std::string{}, // SymbolName
1781 std::string{}, // AliasTarget
1783 ordinal_present, // Noname
1790 auto Error = llvm::object::writeImportLibrary(
1794 static_cast<llvm::COFF::MachineTypes>(Machine),
1797 std::string errorString;
1798 llvm::raw_string_ostream stream(errorString);
1801 LLVMRustSetLastError(errorString.c_str());
1802 return LLVMRustResult::Failure;
1804 return LLVMRustResult::Success;
1808 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1809 extern "C" DiagnosticHandler *
1810 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1811 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1812 return DH.release();
1815 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1816 // handling. Ownership of the handler is moved to the LLVMContext.
1817 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1818 DiagnosticHandler *DH) {
1819 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1822 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1824 // Configures a diagnostic handler that invokes provided callback when a
1825 // backend needs to emit a diagnostic.
1827 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1828 // the RemarkPasses array specifies individual passes for which remarks will be
1830 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1831 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1832 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1833 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1835 class RustDiagnosticHandler final : public DiagnosticHandler {
1837 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1838 void *DiagnosticHandlerContext,
1839 bool RemarkAllPasses,
1840 std::vector<std::string> RemarkPasses)
1841 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1842 DiagnosticHandlerContext(DiagnosticHandlerContext),
1843 RemarkAllPasses(RemarkAllPasses),
1844 RemarkPasses(RemarkPasses) {}
1846 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1847 if (DiagnosticHandlerCallback) {
1848 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1854 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1855 return isRemarkEnabled(PassName);
1858 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1859 return isRemarkEnabled(PassName);
1862 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1863 return isRemarkEnabled(PassName);
1866 bool isAnyRemarkEnabled() const override {
1867 return RemarkAllPasses || !RemarkPasses.empty();
1871 bool isRemarkEnabled(StringRef PassName) const {
1872 if (RemarkAllPasses)
1875 for (auto &Pass : RemarkPasses)
1876 if (Pass == PassName)
1882 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1883 void *DiagnosticHandlerContext = nullptr;
1885 bool RemarkAllPasses = false;
1886 std::vector<std::string> RemarkPasses;
1889 std::vector<std::string> Passes;
1890 for (size_t I = 0; I != RemarkPassesLen; ++I)
1891 Passes.push_back(RemarkPasses[I]);
1893 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1894 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));