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 AttributeList PAL = F->getAttributes();
345 AttributeList PALNew;
346 #if LLVM_VERSION_LT(14, 0)
347 PALNew = PAL.removeAttribute(F->getContext(), Index, fromRust(RustAttr));
349 PALNew = PAL.removeAttributeAtIndex(F->getContext(), Index, fromRust(RustAttr));
351 F->setAttributes(PALNew);
354 // Enable a fast-math flag
356 // https://llvm.org/docs/LangRef.html#fast-math-flags
357 extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
358 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
363 extern "C" LLVMValueRef
364 LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
365 const char *Name, LLVMAtomicOrdering Order) {
366 Value *Ptr = unwrap(Source);
367 LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
368 LI->setAtomic(fromRust(Order));
372 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
375 LLVMAtomicOrdering Order) {
376 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
377 SI->setAtomic(fromRust(Order));
381 // FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
382 // once we raise our minimum support to LLVM 10.
383 extern "C" LLVMValueRef
384 LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
385 LLVMValueRef Old, LLVMValueRef Source,
386 LLVMAtomicOrdering Order,
387 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
388 #if LLVM_VERSION_GE(13,0)
389 // Rust probably knows the alignment of the target value and should be able to
390 // specify something more precise than MaybeAlign here. See also
391 // https://reviews.llvm.org/D97224 which may be a useful reference.
392 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
393 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
394 fromRust(FailureOrder));
396 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
397 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
398 fromRust(FailureOrder));
404 enum class LLVMRustSynchronizationScope {
409 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
411 case LLVMRustSynchronizationScope::SingleThread:
412 return SyncScope::SingleThread;
413 case LLVMRustSynchronizationScope::CrossThread:
414 return SyncScope::System;
416 report_fatal_error("bad SynchronizationScope.");
420 extern "C" LLVMValueRef
421 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
422 LLVMRustSynchronizationScope Scope) {
423 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
426 enum class LLVMRustAsmDialect {
431 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
433 case LLVMRustAsmDialect::Att:
434 return InlineAsm::AD_ATT;
435 case LLVMRustAsmDialect::Intel:
436 return InlineAsm::AD_Intel;
438 report_fatal_error("bad AsmDialect.");
442 extern "C" LLVMValueRef
443 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
444 char *Constraints, size_t ConstraintsLen,
445 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
446 LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
447 #if LLVM_VERSION_GE(13, 0)
448 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
449 StringRef(AsmString, AsmStringLen),
450 StringRef(Constraints, ConstraintsLen),
451 HasSideEffects, IsAlignStack,
452 fromRust(Dialect), CanThrow));
454 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
455 StringRef(AsmString, AsmStringLen),
456 StringRef(Constraints, ConstraintsLen),
457 HasSideEffects, IsAlignStack,
462 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
463 size_t ConstraintsLen) {
464 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
465 StringRef(Constraints, ConstraintsLen));
468 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
470 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
473 typedef DIBuilder *LLVMRustDIBuilderRef;
475 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
476 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
479 #define DIDescriptor DIScope
480 #define DIArray DINodeArray
481 #define unwrapDI unwrapDIPtr
483 // These values **must** match debuginfo::DIFlags! They also *happen*
484 // to match LLVM, but that isn't required as we do giant sets of
485 // matching below. The value shouldn't be directly passed to LLVM.
486 enum class LLVMRustDIFlags : uint32_t {
491 FlagFwdDecl = (1 << 2),
492 FlagAppleBlock = (1 << 3),
493 FlagBlockByrefStruct = (1 << 4),
494 FlagVirtual = (1 << 5),
495 FlagArtificial = (1 << 6),
496 FlagExplicit = (1 << 7),
497 FlagPrototyped = (1 << 8),
498 FlagObjcClassComplete = (1 << 9),
499 FlagObjectPointer = (1 << 10),
500 FlagVector = (1 << 11),
501 FlagStaticMember = (1 << 12),
502 FlagLValueReference = (1 << 13),
503 FlagRValueReference = (1 << 14),
504 FlagExternalTypeRef = (1 << 15),
505 FlagIntroducedVirtual = (1 << 18),
506 FlagBitField = (1 << 19),
507 FlagNoReturn = (1 << 20),
508 // Do not add values that are not supported by the minimum LLVM
509 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
512 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
513 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
514 static_cast<uint32_t>(B));
517 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
518 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
519 static_cast<uint32_t>(B));
522 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
526 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
528 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
529 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
532 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
533 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
535 switch (visibility(Flags)) {
536 case LLVMRustDIFlags::FlagPrivate:
537 Result |= DINode::DIFlags::FlagPrivate;
539 case LLVMRustDIFlags::FlagProtected:
540 Result |= DINode::DIFlags::FlagProtected;
542 case LLVMRustDIFlags::FlagPublic:
543 Result |= DINode::DIFlags::FlagPublic;
546 // The rest are handled below
550 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
551 Result |= DINode::DIFlags::FlagFwdDecl;
553 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
554 Result |= DINode::DIFlags::FlagAppleBlock;
556 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
557 Result |= DINode::DIFlags::FlagVirtual;
559 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
560 Result |= DINode::DIFlags::FlagArtificial;
562 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
563 Result |= DINode::DIFlags::FlagExplicit;
565 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
566 Result |= DINode::DIFlags::FlagPrototyped;
568 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
569 Result |= DINode::DIFlags::FlagObjcClassComplete;
571 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
572 Result |= DINode::DIFlags::FlagObjectPointer;
574 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
575 Result |= DINode::DIFlags::FlagVector;
577 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
578 Result |= DINode::DIFlags::FlagStaticMember;
580 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
581 Result |= DINode::DIFlags::FlagLValueReference;
583 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
584 Result |= DINode::DIFlags::FlagRValueReference;
586 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
587 Result |= DINode::DIFlags::FlagIntroducedVirtual;
589 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
590 Result |= DINode::DIFlags::FlagBitField;
592 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
593 Result |= DINode::DIFlags::FlagNoReturn;
599 // These values **must** match debuginfo::DISPFlags! They also *happen*
600 // to match LLVM, but that isn't required as we do giant sets of
601 // matching below. The value shouldn't be directly passed to LLVM.
602 enum class LLVMRustDISPFlags : uint32_t {
605 SPFlagPureVirtual = 2,
606 SPFlagLocalToUnit = (1 << 2),
607 SPFlagDefinition = (1 << 3),
608 SPFlagOptimized = (1 << 4),
609 SPFlagMainSubprogram = (1 << 5),
610 // Do not add values that are not supported by the minimum LLVM
611 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
612 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
615 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
616 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
617 static_cast<uint32_t>(B));
620 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
621 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
622 static_cast<uint32_t>(B));
625 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
629 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
631 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
632 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
635 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
636 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
638 switch (virtuality(SPFlags)) {
639 case LLVMRustDISPFlags::SPFlagVirtual:
640 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
642 case LLVMRustDISPFlags::SPFlagPureVirtual:
643 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
646 // The rest are handled below
650 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
651 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
653 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
654 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
656 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
657 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
659 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
660 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
666 enum class LLVMRustDebugEmissionKind {
672 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
674 case LLVMRustDebugEmissionKind::NoDebug:
675 return DICompileUnit::DebugEmissionKind::NoDebug;
676 case LLVMRustDebugEmissionKind::FullDebug:
677 return DICompileUnit::DebugEmissionKind::FullDebug;
678 case LLVMRustDebugEmissionKind::LineTablesOnly:
679 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
681 report_fatal_error("bad DebugEmissionKind.");
685 enum class LLVMRustChecksumKind {
692 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
694 case LLVMRustChecksumKind::None:
696 case LLVMRustChecksumKind::MD5:
697 return DIFile::ChecksumKind::CSK_MD5;
698 case LLVMRustChecksumKind::SHA1:
699 return DIFile::ChecksumKind::CSK_SHA1;
700 case LLVMRustChecksumKind::SHA256:
701 return DIFile::ChecksumKind::CSK_SHA256;
703 report_fatal_error("bad ChecksumKind.");
707 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
708 return DEBUG_METADATA_VERSION;
711 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
713 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
715 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
717 extern "C" bool LLVMRustIsRustLLVM() {
725 extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
727 unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
730 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
731 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
734 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
735 return new DIBuilder(*unwrap(M));
738 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
742 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
746 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
747 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
748 const char *Producer, size_t ProducerLen, bool isOptimized,
749 const char *Flags, unsigned RuntimeVer,
750 const char *SplitName, size_t SplitNameLen,
751 LLVMRustDebugEmissionKind Kind,
752 uint64_t DWOId, bool SplitDebugInlining) {
753 auto *File = unwrapDI<DIFile>(FileRef);
755 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
756 isOptimized, Flags, RuntimeVer,
757 StringRef(SplitName, SplitNameLen),
758 fromRust(Kind), DWOId, SplitDebugInlining));
761 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
762 LLVMRustDIBuilderRef Builder,
763 const char *Filename, size_t FilenameLen,
764 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
765 const char *Checksum, size_t ChecksumLen) {
766 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
767 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
769 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
770 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
771 StringRef(Directory, DirectoryLen),
775 extern "C" LLVMMetadataRef
776 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
777 LLVMMetadataRef ParameterTypes) {
778 return wrap(Builder->createSubroutineType(
779 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
782 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
783 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
784 const char *Name, size_t NameLen,
785 const char *LinkageName, size_t LinkageNameLen,
786 LLVMMetadataRef File, unsigned LineNo,
787 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
788 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
789 LLVMMetadataRef Decl) {
790 DITemplateParameterArray TParams =
791 DITemplateParameterArray(unwrap<MDTuple>(TParam));
792 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
793 DINode::DIFlags llvmFlags = fromRust(Flags);
794 DISubprogram *Sub = Builder->createFunction(
795 unwrapDI<DIScope>(Scope),
796 StringRef(Name, NameLen),
797 StringRef(LinkageName, LinkageNameLen),
798 unwrapDI<DIFile>(File), LineNo,
799 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
800 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
802 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
806 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
807 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
808 uint64_t SizeInBits, unsigned Encoding) {
809 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
812 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
813 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
814 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
815 return wrap(Builder->createTypedef(
816 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
817 LineNo, unwrapDIPtr<DIScope>(Scope)));
820 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
821 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
822 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
823 const char *Name, size_t NameLen) {
824 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
825 SizeInBits, AlignInBits,
827 StringRef(Name, NameLen)));
830 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
831 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
832 const char *Name, size_t NameLen,
833 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
834 uint32_t AlignInBits, LLVMRustDIFlags Flags,
835 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
836 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
837 const char *UniqueId, size_t UniqueIdLen) {
838 return wrap(Builder->createStructType(
839 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
840 unwrapDI<DIFile>(File), LineNumber,
841 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
842 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
843 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
846 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
847 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
848 const char *Name, size_t NameLen,
849 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
850 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
851 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
852 return wrap(Builder->createVariantPart(
853 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
854 unwrapDI<DIFile>(File), LineNumber,
855 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
856 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
859 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
860 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
861 const char *Name, size_t NameLen,
862 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
863 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
864 LLVMMetadataRef Ty) {
865 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
866 StringRef(Name, NameLen),
867 unwrapDI<DIFile>(File), LineNo,
868 SizeInBits, AlignInBits, OffsetInBits,
869 fromRust(Flags), unwrapDI<DIType>(Ty)));
872 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
873 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
874 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
875 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
876 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
877 llvm::ConstantInt* D = nullptr;
879 D = unwrap<llvm::ConstantInt>(Discriminant);
881 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
882 StringRef(Name, NameLen),
883 unwrapDI<DIFile>(File), LineNo,
884 SizeInBits, AlignInBits, OffsetInBits, D,
885 fromRust(Flags), unwrapDI<DIType>(Ty)));
888 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
889 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
890 LLVMMetadataRef File, unsigned Line, unsigned Col) {
891 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
892 unwrapDI<DIFile>(File), Line, Col));
895 extern "C" LLVMMetadataRef
896 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
897 LLVMMetadataRef Scope,
898 LLVMMetadataRef File) {
899 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
900 unwrapDI<DIFile>(File)));
903 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
904 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
905 const char *Name, size_t NameLen,
906 const char *LinkageName, size_t LinkageNameLen,
907 LLVMMetadataRef File, unsigned LineNo,
908 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
909 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
910 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
912 llvm::DIExpression *InitExpr = nullptr;
913 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
914 InitExpr = Builder->createConstantValueExpression(
915 IntVal->getValue().getSExtValue());
916 } else if (llvm::ConstantFP *FPVal =
917 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
918 InitExpr = Builder->createConstantValueExpression(
919 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
922 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
923 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
924 StringRef(LinkageName, LinkageNameLen),
925 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
926 /* isDefined */ true,
927 InitExpr, unwrapDIPtr<MDNode>(Decl),
928 /* templateParams */ nullptr,
931 InitVal->setMetadata("dbg", VarExpr);
933 return wrap(VarExpr);
936 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
937 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
938 const char *Name, size_t NameLen,
939 LLVMMetadataRef File, unsigned LineNo,
940 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
941 unsigned ArgNo, uint32_t AlignInBits) {
942 if (Tag == 0x100) { // DW_TAG_auto_variable
943 return wrap(Builder->createAutoVariable(
944 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
945 unwrapDI<DIFile>(File), LineNo,
946 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
948 return wrap(Builder->createParameterVariable(
949 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
950 unwrapDI<DIFile>(File), LineNo,
951 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
955 extern "C" LLVMMetadataRef
956 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
957 uint32_t AlignInBits, LLVMMetadataRef Ty,
958 LLVMMetadataRef Subscripts) {
960 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
961 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
964 extern "C" LLVMMetadataRef
965 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
967 return wrap(Builder->getOrCreateSubrange(Lo, Count));
970 extern "C" LLVMMetadataRef
971 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
972 LLVMMetadataRef *Ptr, unsigned Count) {
973 Metadata **DataValue = unwrap(Ptr);
975 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
978 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
979 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
980 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
981 LLVMBasicBlockRef InsertAtEnd) {
982 return wrap(Builder->insertDeclare(
983 unwrap(V), unwrap<DILocalVariable>(VarInfo),
984 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
985 DebugLoc(cast<MDNode>(unwrap(DL))),
986 unwrap(InsertAtEnd)));
989 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
990 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
991 int64_t Value, bool IsUnsigned) {
992 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
995 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
996 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
997 const char *Name, size_t NameLen,
998 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
999 uint32_t AlignInBits, LLVMMetadataRef Elements,
1000 LLVMMetadataRef ClassTy, bool IsScoped) {
1001 return wrap(Builder->createEnumerationType(
1002 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
1003 unwrapDI<DIFile>(File), LineNumber,
1004 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
1005 unwrapDI<DIType>(ClassTy), "", IsScoped));
1008 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
1009 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1010 const char *Name, size_t NameLen,
1011 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1012 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
1013 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
1014 return wrap(Builder->createUnionType(
1015 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1016 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1017 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1018 StringRef(UniqueId, UniqueIdLen)));
1021 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1022 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1023 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1024 bool IsDefault = false; // FIXME: should we ever set this true?
1025 return wrap(Builder->createTemplateTypeParameter(
1026 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1029 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1030 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1031 const char *Name, size_t NameLen, bool ExportSymbols) {
1032 return wrap(Builder->createNameSpace(
1033 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1038 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1039 LLVMMetadataRef CompositeTy,
1040 LLVMMetadataRef Elements,
1041 LLVMMetadataRef Params) {
1042 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1043 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1044 DINodeArray(unwrap<MDTuple>(Params)));
1047 extern "C" LLVMMetadataRef
1048 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1049 LLVMMetadataRef ScopeRef,
1050 LLVMMetadataRef InlinedAt) {
1051 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1052 DILocation *Loc = DILocation::get(
1053 Scope->getContext(), Line, Column, Scope,
1054 unwrapDIPtr<MDNode>(InlinedAt));
1058 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1059 return dwarf::DW_OP_deref;
1062 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1063 return dwarf::DW_OP_plus_uconst;
1066 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1067 RawRustStringOstream OS(Str);
1068 unwrap<llvm::Type>(Ty)->print(OS);
1071 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1072 RustStringRef Str) {
1073 RawRustStringOstream OS(Str);
1078 unwrap<llvm::Value>(V)->getType()->print(OS);
1080 unwrap<llvm::Value>(V)->print(OS);
1085 // LLVMArrayType function does not support 64-bit ElementCount
1086 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1087 uint64_t ElementCount) {
1088 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1091 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1093 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1094 RawRustStringOstream OS(Str);
1095 unwrap(T)->print(OS);
1098 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1099 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1100 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1101 RustStringRef FilenameOut, RustStringRef MessageOut) {
1102 // Undefined to call this not on an optimization diagnostic!
1103 llvm::DiagnosticInfoOptimizationBase *Opt =
1104 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1106 RawRustStringOstream PassNameOS(PassNameOut);
1107 PassNameOS << Opt->getPassName();
1108 *FunctionOut = wrap(&Opt->getFunction());
1110 RawRustStringOstream FilenameOS(FilenameOut);
1111 DiagnosticLocation loc = Opt->getLocation();
1112 if (loc.isValid()) {
1113 *Line = loc.getLine();
1114 *Column = loc.getColumn();
1115 FilenameOS << loc.getAbsolutePath();
1118 RawRustStringOstream MessageOS(MessageOut);
1119 MessageOS << Opt->getMsg();
1122 enum class LLVMRustDiagnosticLevel {
1130 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1131 LLVMRustDiagnosticLevel *LevelOut,
1132 unsigned *CookieOut,
1133 LLVMTwineRef *MessageOut) {
1134 // Undefined to call this not on an inline assembly diagnostic!
1135 llvm::DiagnosticInfoInlineAsm *IA =
1136 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1138 *CookieOut = IA->getLocCookie();
1139 *MessageOut = wrap(&IA->getMsgStr());
1141 switch (IA->getSeverity()) {
1143 *LevelOut = LLVMRustDiagnosticLevel::Error;
1146 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1149 *LevelOut = LLVMRustDiagnosticLevel::Note;
1152 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1155 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1159 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1160 RustStringRef Str) {
1161 RawRustStringOstream OS(Str);
1162 DiagnosticPrinterRawOStream DP(OS);
1163 unwrap(DI)->print(DP);
1166 enum class LLVMRustDiagnosticKind {
1170 DebugMetadataVersion,
1173 OptimizationRemarkMissed,
1174 OptimizationRemarkAnalysis,
1175 OptimizationRemarkAnalysisFPCommute,
1176 OptimizationRemarkAnalysisAliasing,
1177 OptimizationRemarkOther,
1178 OptimizationFailure,
1185 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1188 return LLVMRustDiagnosticKind::InlineAsm;
1190 return LLVMRustDiagnosticKind::StackSize;
1191 case DK_DebugMetadataVersion:
1192 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1193 case DK_SampleProfile:
1194 return LLVMRustDiagnosticKind::SampleProfile;
1195 case DK_OptimizationRemark:
1196 case DK_MachineOptimizationRemark:
1197 return LLVMRustDiagnosticKind::OptimizationRemark;
1198 case DK_OptimizationRemarkMissed:
1199 case DK_MachineOptimizationRemarkMissed:
1200 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1201 case DK_OptimizationRemarkAnalysis:
1202 case DK_MachineOptimizationRemarkAnalysis:
1203 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1204 case DK_OptimizationRemarkAnalysisFPCommute:
1205 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1206 case DK_OptimizationRemarkAnalysisAliasing:
1207 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1209 return LLVMRustDiagnosticKind::PGOProfile;
1211 return LLVMRustDiagnosticKind::Linker;
1212 case DK_Unsupported:
1213 return LLVMRustDiagnosticKind::Unsupported;
1214 #if LLVM_VERSION_GE(13, 0)
1216 return LLVMRustDiagnosticKind::SrcMgr;
1219 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1220 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1221 : LLVMRustDiagnosticKind::Other;
1225 extern "C" LLVMRustDiagnosticKind
1226 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1227 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1230 // This is kept distinct from LLVMGetTypeKind, because when
1231 // a new type kind is added, the Rust-side enum must be
1232 // updated or UB will result.
1233 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1234 switch (unwrap(Ty)->getTypeID()) {
1235 case Type::VoidTyID:
1236 return LLVMVoidTypeKind;
1237 case Type::HalfTyID:
1238 return LLVMHalfTypeKind;
1239 case Type::FloatTyID:
1240 return LLVMFloatTypeKind;
1241 case Type::DoubleTyID:
1242 return LLVMDoubleTypeKind;
1243 case Type::X86_FP80TyID:
1244 return LLVMX86_FP80TypeKind;
1245 case Type::FP128TyID:
1246 return LLVMFP128TypeKind;
1247 case Type::PPC_FP128TyID:
1248 return LLVMPPC_FP128TypeKind;
1249 case Type::LabelTyID:
1250 return LLVMLabelTypeKind;
1251 case Type::MetadataTyID:
1252 return LLVMMetadataTypeKind;
1253 case Type::IntegerTyID:
1254 return LLVMIntegerTypeKind;
1255 case Type::FunctionTyID:
1256 return LLVMFunctionTypeKind;
1257 case Type::StructTyID:
1258 return LLVMStructTypeKind;
1259 case Type::ArrayTyID:
1260 return LLVMArrayTypeKind;
1261 case Type::PointerTyID:
1262 return LLVMPointerTypeKind;
1263 case Type::FixedVectorTyID:
1264 return LLVMVectorTypeKind;
1265 case Type::X86_MMXTyID:
1266 return LLVMX86_MMXTypeKind;
1267 case Type::TokenTyID:
1268 return LLVMTokenTypeKind;
1269 case Type::ScalableVectorTyID:
1270 return LLVMScalableVectorTypeKind;
1271 case Type::BFloatTyID:
1272 return LLVMBFloatTypeKind;
1273 case Type::X86_AMXTyID:
1274 return LLVMX86_AMXTypeKind;
1276 report_fatal_error("Unhandled TypeID.");
1279 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1281 #if LLVM_VERSION_LT(13, 0)
1282 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1284 using LLVMInlineAsmDiagHandlerTy = void*;
1287 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1288 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1289 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1290 // with LLVM 13 this function is gone.
1291 #if LLVM_VERSION_LT(13, 0)
1292 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1296 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1297 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1298 #if LLVM_VERSION_GE(13, 0)
1299 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1300 *Cookie = SM->getLocCookie();
1301 return wrap(&SM->getSMDiag());
1303 report_fatal_error("Shouldn't get called on older versions");
1307 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1308 RustStringRef MessageOut,
1309 RustStringRef BufferOut,
1310 LLVMRustDiagnosticLevel* LevelOut,
1312 unsigned* RangesOut,
1313 size_t* NumRanges) {
1314 SMDiagnostic& D = *unwrap(DRef);
1315 RawRustStringOstream MessageOS(MessageOut);
1316 MessageOS << D.getMessage();
1318 switch (D.getKind()) {
1319 case SourceMgr::DK_Error:
1320 *LevelOut = LLVMRustDiagnosticLevel::Error;
1322 case SourceMgr::DK_Warning:
1323 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1325 case SourceMgr::DK_Note:
1326 *LevelOut = LLVMRustDiagnosticLevel::Note;
1328 case SourceMgr::DK_Remark:
1329 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1332 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1335 if (D.getLoc() == SMLoc())
1338 const SourceMgr &LSM = *D.getSourceMgr();
1339 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1340 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1342 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1344 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1345 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1346 for (size_t i = 0; i < *NumRanges; i++) {
1347 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1348 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1354 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1355 LLVMValueRef ParentPad,
1357 LLVMValueRef *LLArgs,
1359 Value **Args = unwrap(LLArgs);
1360 if (ParentPad == nullptr) {
1361 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1362 ParentPad = wrap(Constant::getNullValue(Ty));
1364 return wrap(unwrap(B)->CreateCleanupPad(
1365 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1368 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1369 LLVMValueRef CleanupPad,
1370 LLVMBasicBlockRef UnwindBB) {
1371 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1372 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1375 extern "C" LLVMValueRef
1376 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1377 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1378 Value **Args = unwrap(LLArgs);
1379 return wrap(unwrap(B)->CreateCatchPad(
1380 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1383 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1385 LLVMBasicBlockRef BB) {
1386 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1390 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1391 LLVMValueRef ParentPad,
1392 LLVMBasicBlockRef BB,
1393 unsigned NumHandlers,
1395 if (ParentPad == nullptr) {
1396 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1397 ParentPad = wrap(Constant::getNullValue(Ty));
1399 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1400 NumHandlers, Name));
1403 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1404 LLVMBasicBlockRef Handler) {
1405 Value *CatchSwitch = unwrap(CatchSwitchRef);
1406 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1409 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1410 LLVMValueRef *Inputs,
1411 unsigned NumInputs) {
1412 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1415 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1419 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1420 LLVMValueRef *Args, unsigned NumArgs,
1421 OperandBundleDef *Bundle) {
1422 Value *Callee = unwrap(Fn);
1423 FunctionType *FTy = unwrap<FunctionType>(Ty);
1424 unsigned Len = Bundle ? 1 : 0;
1425 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1426 return wrap(unwrap(B)->CreateCall(
1427 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1430 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1431 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1432 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1435 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1436 LLVMValueRef Dst, unsigned DstAlign,
1437 LLVMValueRef Src, unsigned SrcAlign,
1438 LLVMValueRef Size, bool IsVolatile) {
1439 return wrap(unwrap(B)->CreateMemCpy(
1440 unwrap(Dst), MaybeAlign(DstAlign),
1441 unwrap(Src), MaybeAlign(SrcAlign),
1442 unwrap(Size), IsVolatile));
1445 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1446 LLVMValueRef Dst, unsigned DstAlign,
1447 LLVMValueRef Src, unsigned SrcAlign,
1448 LLVMValueRef Size, bool IsVolatile) {
1449 return wrap(unwrap(B)->CreateMemMove(
1450 unwrap(Dst), MaybeAlign(DstAlign),
1451 unwrap(Src), MaybeAlign(SrcAlign),
1452 unwrap(Size), IsVolatile));
1455 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1456 LLVMValueRef Dst, unsigned DstAlign,
1458 LLVMValueRef Size, bool IsVolatile) {
1459 return wrap(unwrap(B)->CreateMemSet(
1460 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1463 extern "C" LLVMValueRef
1464 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1465 LLVMValueRef *Args, unsigned NumArgs,
1466 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1467 OperandBundleDef *Bundle, const char *Name) {
1468 Value *Callee = unwrap(Fn);
1469 FunctionType *FTy = unwrap<FunctionType>(Ty);
1470 unsigned Len = Bundle ? 1 : 0;
1471 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1472 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1473 makeArrayRef(unwrap(Args), NumArgs),
1477 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1478 LLVMBasicBlockRef BB) {
1479 auto Point = unwrap(BB)->getFirstInsertionPt();
1480 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1483 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1484 const char *Name, size_t NameLen) {
1485 Triple TargetTriple(unwrap(M)->getTargetTriple());
1486 GlobalObject *GV = unwrap<GlobalObject>(V);
1487 if (TargetTriple.supportsCOMDAT()) {
1488 StringRef NameRef(Name, NameLen);
1489 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1493 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1494 GlobalObject *GV = unwrap<GlobalObject>(V);
1495 GV->setComdat(nullptr);
1498 enum class LLVMRustLinkage {
1499 ExternalLinkage = 0,
1500 AvailableExternallyLinkage = 1,
1501 LinkOnceAnyLinkage = 2,
1502 LinkOnceODRLinkage = 3,
1505 AppendingLinkage = 6,
1506 InternalLinkage = 7,
1508 ExternalWeakLinkage = 9,
1512 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1514 case LLVMExternalLinkage:
1515 return LLVMRustLinkage::ExternalLinkage;
1516 case LLVMAvailableExternallyLinkage:
1517 return LLVMRustLinkage::AvailableExternallyLinkage;
1518 case LLVMLinkOnceAnyLinkage:
1519 return LLVMRustLinkage::LinkOnceAnyLinkage;
1520 case LLVMLinkOnceODRLinkage:
1521 return LLVMRustLinkage::LinkOnceODRLinkage;
1522 case LLVMWeakAnyLinkage:
1523 return LLVMRustLinkage::WeakAnyLinkage;
1524 case LLVMWeakODRLinkage:
1525 return LLVMRustLinkage::WeakODRLinkage;
1526 case LLVMAppendingLinkage:
1527 return LLVMRustLinkage::AppendingLinkage;
1528 case LLVMInternalLinkage:
1529 return LLVMRustLinkage::InternalLinkage;
1530 case LLVMPrivateLinkage:
1531 return LLVMRustLinkage::PrivateLinkage;
1532 case LLVMExternalWeakLinkage:
1533 return LLVMRustLinkage::ExternalWeakLinkage;
1534 case LLVMCommonLinkage:
1535 return LLVMRustLinkage::CommonLinkage;
1537 report_fatal_error("Invalid LLVMRustLinkage value!");
1541 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1543 case LLVMRustLinkage::ExternalLinkage:
1544 return LLVMExternalLinkage;
1545 case LLVMRustLinkage::AvailableExternallyLinkage:
1546 return LLVMAvailableExternallyLinkage;
1547 case LLVMRustLinkage::LinkOnceAnyLinkage:
1548 return LLVMLinkOnceAnyLinkage;
1549 case LLVMRustLinkage::LinkOnceODRLinkage:
1550 return LLVMLinkOnceODRLinkage;
1551 case LLVMRustLinkage::WeakAnyLinkage:
1552 return LLVMWeakAnyLinkage;
1553 case LLVMRustLinkage::WeakODRLinkage:
1554 return LLVMWeakODRLinkage;
1555 case LLVMRustLinkage::AppendingLinkage:
1556 return LLVMAppendingLinkage;
1557 case LLVMRustLinkage::InternalLinkage:
1558 return LLVMInternalLinkage;
1559 case LLVMRustLinkage::PrivateLinkage:
1560 return LLVMPrivateLinkage;
1561 case LLVMRustLinkage::ExternalWeakLinkage:
1562 return LLVMExternalWeakLinkage;
1563 case LLVMRustLinkage::CommonLinkage:
1564 return LLVMCommonLinkage;
1566 report_fatal_error("Invalid LLVMRustLinkage value!");
1569 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1570 return toRust(LLVMGetLinkage(V));
1573 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1574 LLVMRustLinkage RustLinkage) {
1575 LLVMSetLinkage(V, fromRust(RustLinkage));
1578 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1579 LLVMValueRef ConstantVal,
1580 LLVMValueRef *ConstantIndices,
1581 unsigned NumIndices) {
1582 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1584 Constant *Val = unwrap<Constant>(ConstantVal);
1585 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1588 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1589 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1590 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1592 auto C = unwrap<llvm::ConstantInt>(CV);
1593 if (C->getBitWidth() > 128) { return false; }
1596 AP = C->getValue().sextOrSelf(128);
1598 AP = C->getValue().zextOrSelf(128);
1600 *low = AP.getLoBits(64).getZExtValue();
1601 *high = AP.getHiBits(64).getZExtValue();
1605 enum class LLVMRustVisibility {
1611 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1613 case LLVMDefaultVisibility:
1614 return LLVMRustVisibility::Default;
1615 case LLVMHiddenVisibility:
1616 return LLVMRustVisibility::Hidden;
1617 case LLVMProtectedVisibility:
1618 return LLVMRustVisibility::Protected;
1620 report_fatal_error("Invalid LLVMRustVisibility value!");
1623 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1625 case LLVMRustVisibility::Default:
1626 return LLVMDefaultVisibility;
1627 case LLVMRustVisibility::Hidden:
1628 return LLVMHiddenVisibility;
1629 case LLVMRustVisibility::Protected:
1630 return LLVMProtectedVisibility;
1632 report_fatal_error("Invalid LLVMRustVisibility value!");
1635 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1636 return toRust(LLVMGetVisibility(V));
1639 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1640 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1641 LLVMTypeRef DestTy, bool isSigned) {
1642 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1645 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1646 LLVMRustVisibility RustVisibility) {
1647 LLVMSetVisibility(V, fromRust(RustVisibility));
1650 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1651 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1654 struct LLVMRustModuleBuffer {
1658 extern "C" LLVMRustModuleBuffer*
1659 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1660 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1662 raw_string_ostream OS(Ret->data);
1664 legacy::PassManager PM;
1665 PM.add(createBitcodeWriterPass(OS));
1669 return Ret.release();
1673 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1677 extern "C" const void*
1678 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1679 return Buffer->data.data();
1683 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1684 return Buffer->data.length();
1688 LLVMRustModuleCost(LLVMModuleRef M) {
1689 auto f = unwrap(M)->functions();
1690 return std::distance(std::begin(f), std::end(f));
1693 // Vector reductions:
1694 extern "C" LLVMValueRef
1695 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1696 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1698 extern "C" LLVMValueRef
1699 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1700 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1702 extern "C" LLVMValueRef
1703 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1704 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1706 extern "C" LLVMValueRef
1707 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1708 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1710 extern "C" LLVMValueRef
1711 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1712 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1714 extern "C" LLVMValueRef
1715 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1716 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1718 extern "C" LLVMValueRef
1719 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1720 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1722 extern "C" LLVMValueRef
1723 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1724 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1726 extern "C" LLVMValueRef
1727 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1728 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1730 extern "C" LLVMValueRef
1731 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1732 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1733 I->setHasNoNaNs(NoNaN);
1736 extern "C" LLVMValueRef
1737 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1738 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1739 I->setHasNoNaNs(NoNaN);
1743 extern "C" LLVMValueRef
1744 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1745 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1747 extern "C" LLVMValueRef
1748 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1749 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1752 // This struct contains all necessary info about a symbol exported from a DLL.
1753 struct LLVMRustCOFFShortExport {
1755 bool ordinal_present;
1756 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1760 // Machine must be a COFF machine type, as defined in PE specs.
1761 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1762 const char* ImportName,
1764 const LLVMRustCOFFShortExport* Exports,
1769 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1770 ConvertedExports.reserve(NumExports);
1772 for (size_t i = 0; i < NumExports; ++i) {
1773 bool ordinal_present = Exports[i].ordinal_present;
1774 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1775 ConvertedExports.push_back(llvm::object::COFFShortExport{
1776 Exports[i].name, // Name
1777 std::string{}, // ExtName
1778 std::string{}, // SymbolName
1779 std::string{}, // AliasTarget
1781 ordinal_present, // Noname
1788 auto Error = llvm::object::writeImportLibrary(
1792 static_cast<llvm::COFF::MachineTypes>(Machine),
1795 std::string errorString;
1796 llvm::raw_string_ostream stream(errorString);
1799 LLVMRustSetLastError(errorString.c_str());
1800 return LLVMRustResult::Failure;
1802 return LLVMRustResult::Success;
1806 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1807 extern "C" DiagnosticHandler *
1808 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1809 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1810 return DH.release();
1813 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1814 // handling. Ownership of the handler is moved to the LLVMContext.
1815 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1816 DiagnosticHandler *DH) {
1817 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1820 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1822 // Configures a diagnostic handler that invokes provided callback when a
1823 // backend needs to emit a diagnostic.
1825 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1826 // the RemarkPasses array specifies individual passes for which remarks will be
1828 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1829 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1830 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1831 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1833 class RustDiagnosticHandler final : public DiagnosticHandler {
1835 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1836 void *DiagnosticHandlerContext,
1837 bool RemarkAllPasses,
1838 std::vector<std::string> RemarkPasses)
1839 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1840 DiagnosticHandlerContext(DiagnosticHandlerContext),
1841 RemarkAllPasses(RemarkAllPasses),
1842 RemarkPasses(RemarkPasses) {}
1844 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1845 if (DiagnosticHandlerCallback) {
1846 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1852 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1853 return isRemarkEnabled(PassName);
1856 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1857 return isRemarkEnabled(PassName);
1860 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1861 return isRemarkEnabled(PassName);
1864 bool isAnyRemarkEnabled() const override {
1865 return RemarkAllPasses || !RemarkPasses.empty();
1869 bool isRemarkEnabled(StringRef PassName) const {
1870 if (RemarkAllPasses)
1873 for (auto &Pass : RemarkPasses)
1874 if (Pass == PassName)
1880 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1881 void *DiagnosticHandlerContext = nullptr;
1883 bool RemarkAllPasses = false;
1884 std::vector<std::string> RemarkPasses;
1887 std::vector<std::string> Passes;
1888 for (size_t I = 0; I != RemarkPassesLen; ++I)
1889 Passes.push_back(RemarkPasses[I]);
1891 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1892 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));