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" void LLVMRustDisableSystemDialogsOnCrash() {
80 sys::DisableSystemDialogsOnCrash();
83 extern "C" char *LLVMRustGetLastError(void) {
84 char *Ret = LastError;
89 extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) {
90 return unwrap(M)->getInstructionCount();
93 extern "C" void LLVMRustSetLastError(const char *Err) {
94 free((void *)LastError);
95 LastError = strdup(Err);
98 extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
99 auto ctx = new LLVMContext();
100 ctx->setDiscardValueNames(shouldDiscardNames);
104 extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
105 const char *Triple) {
106 unwrap(M)->setTargetTriple(Triple::normalize(Triple));
109 extern "C" void LLVMRustPrintPassTimings() {
110 raw_fd_ostream OS(2, false); // stderr.
111 TimerGroup::printAll(OS);
114 extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
116 return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
119 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
122 LLVMTypeRef FunctionTy) {
123 return wrap(unwrap(M)
124 ->getOrInsertFunction(StringRef(Name, NameLen),
125 unwrap<FunctionType>(FunctionTy))
130 extern "C" LLVMValueRef
131 LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
132 Module *Mod = unwrap(M);
133 StringRef NameRef(Name, NameLen);
135 // We don't use Module::getOrInsertGlobal because that returns a Constant*,
136 // which may either be the real GlobalVariable*, or a constant bitcast of it
137 // if our type doesn't match the original declaration. We always want the
138 // GlobalVariable* so we can access linkage, visibility, etc.
139 GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true);
141 GV = new GlobalVariable(*Mod, unwrap(Ty), false,
142 GlobalValue::ExternalLinkage, nullptr, NameRef);
146 extern "C" LLVMValueRef
147 LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
148 return wrap(new GlobalVariable(*unwrap(M),
151 GlobalValue::PrivateLinkage,
155 extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
156 return wrap(Type::getMetadataTy(*unwrap(C)));
159 static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
162 return Attribute::AlwaysInline;
164 return Attribute::ByVal;
166 return Attribute::Cold;
168 return Attribute::InlineHint;
170 return Attribute::MinSize;
172 return Attribute::Naked;
174 return Attribute::NoAlias;
176 return Attribute::NoCapture;
178 return Attribute::NoInline;
180 return Attribute::NonNull;
182 return Attribute::NoRedZone;
184 return Attribute::NoReturn;
186 return Attribute::NoUnwind;
187 case OptimizeForSize:
188 return Attribute::OptimizeForSize;
190 return Attribute::ReadOnly;
192 return Attribute::SExt;
194 return Attribute::StructRet;
196 return Attribute::UWTable;
198 return Attribute::ZExt;
200 return Attribute::InReg;
202 return Attribute::SanitizeThread;
203 case SanitizeAddress:
204 return Attribute::SanitizeAddress;
206 return Attribute::SanitizeMemory;
208 return Attribute::NonLazyBind;
210 return Attribute::OptimizeNone;
212 return Attribute::ReturnsTwice;
214 return Attribute::ReadNone;
215 case InaccessibleMemOnly:
216 return Attribute::InaccessibleMemOnly;
217 case SanitizeHWAddress:
218 return Attribute::SanitizeHWAddress;
220 return Attribute::WillReturn;
221 case StackProtectReq:
222 return Attribute::StackProtectReq;
223 case StackProtectStrong:
224 return Attribute::StackProtectStrong;
226 return Attribute::StackProtect;
228 return Attribute::NoUndef;
230 return Attribute::SanitizeMemTag;
232 report_fatal_error("bad AttributeKind");
235 template<typename T> static inline void AddAttributes(T *t, unsigned Index,
236 LLVMAttributeRef *Attrs, size_t AttrsLen) {
237 AttributeList PAL = t->getAttributes();
238 AttributeList PALNew;
239 #if LLVM_VERSION_LT(14, 0)
241 for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
242 B.addAttribute(unwrap(Attr));
243 PALNew = PAL.addAttributes(t->getContext(), Index, B);
245 AttrBuilder B(t->getContext());
246 for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
247 B.addAttribute(unwrap(Attr));
248 PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B);
250 t->setAttributes(PALNew);
253 template<typename T> static inline void RemoveAttributes(T *t, unsigned Index,
254 LLVMRustAttribute *RustAttrs,
255 size_t RustAttrsLen) {
256 AttributeList PAL = t->getAttributes();
257 AttributeList PALNew;
258 #if LLVM_VERSION_LT(14, 0)
260 for (LLVMRustAttribute RustAttr : makeArrayRef(RustAttrs, RustAttrsLen))
261 B.addAttribute(fromRust(RustAttr));
262 PALNew = PAL.removeAttributes(t->getContext(), Index, B);
265 for (LLVMRustAttribute RustAttr : makeArrayRef(RustAttrs, RustAttrsLen))
266 Mask.addAttribute(fromRust(RustAttr));
267 PALNew = PAL.removeAttributesAtIndex(t->getContext(), Index, Mask);
269 t->setAttributes(PALNew);
272 extern "C" void LLVMRustAddFunctionAttributes(LLVMValueRef Fn, unsigned Index,
273 LLVMAttributeRef *Attrs, size_t AttrsLen) {
274 Function *F = unwrap<Function>(Fn);
275 AddAttributes(F, Index, Attrs, AttrsLen);
278 extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, unsigned Index,
279 LLVMRustAttribute *RustAttrs,
280 size_t RustAttrsLen) {
281 Function *F = unwrap<Function>(Fn);
282 RemoveAttributes(F, Index, RustAttrs, RustAttrsLen);
285 extern "C" void LLVMRustAddCallSiteAttributes(LLVMValueRef Instr, unsigned Index,
286 LLVMAttributeRef *Attrs, size_t AttrsLen) {
287 CallBase *Call = unwrap<CallBase>(Instr);
288 AddAttributes(Call, Index, Attrs, AttrsLen);
291 extern "C" LLVMAttributeRef LLVMRustCreateAttrNoValue(LLVMContextRef C,
292 LLVMRustAttribute RustAttr) {
293 return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr)));
296 extern "C" LLVMAttributeRef LLVMRustCreateAttrStringValue(LLVMContextRef C,
299 return wrap(Attribute::get(*unwrap(C), StringRef(Name), StringRef(Value)));
302 extern "C" LLVMAttributeRef LLVMRustCreateAlignmentAttr(LLVMContextRef C,
304 return wrap(Attribute::getWithAlignment(*unwrap(C), llvm::Align(Bytes)));
307 extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableAttr(LLVMContextRef C,
309 return wrap(Attribute::getWithDereferenceableBytes(*unwrap(C), Bytes));
312 extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableOrNullAttr(LLVMContextRef C,
314 return wrap(Attribute::getWithDereferenceableOrNullBytes(*unwrap(C), Bytes));
317 extern "C" LLVMAttributeRef LLVMRustCreateByValAttr(LLVMContextRef C, LLVMTypeRef Ty) {
318 return wrap(Attribute::getWithByValType(*unwrap(C), unwrap(Ty)));
321 extern "C" LLVMAttributeRef LLVMRustCreateStructRetAttr(LLVMContextRef C, LLVMTypeRef Ty) {
322 return wrap(Attribute::getWithStructRetType(*unwrap(C), unwrap(Ty)));
325 extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Async) {
326 #if LLVM_VERSION_LT(15, 0)
327 return wrap(Attribute::get(*unwrap(C), Attribute::UWTable));
329 return wrap(Attribute::getWithUWTableKind(
330 *unwrap(C), Async ? UWTableKind::Async : UWTableKind::Sync));
334 // Enable a fast-math flag
336 // https://llvm.org/docs/LangRef.html#fast-math-flags
337 extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
338 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
343 extern "C" LLVMValueRef
344 LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
345 const char *Name, LLVMAtomicOrdering Order) {
346 Value *Ptr = unwrap(Source);
347 LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
348 LI->setAtomic(fromRust(Order));
352 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
355 LLVMAtomicOrdering Order) {
356 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
357 SI->setAtomic(fromRust(Order));
361 // FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
362 // once we raise our minimum support to LLVM 10.
363 extern "C" LLVMValueRef
364 LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
365 LLVMValueRef Old, LLVMValueRef Source,
366 LLVMAtomicOrdering Order,
367 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
368 #if LLVM_VERSION_GE(13,0)
369 // Rust probably knows the alignment of the target value and should be able to
370 // specify something more precise than MaybeAlign here. See also
371 // https://reviews.llvm.org/D97224 which may be a useful reference.
372 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
373 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
374 fromRust(FailureOrder));
376 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
377 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
378 fromRust(FailureOrder));
384 enum class LLVMRustSynchronizationScope {
389 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
391 case LLVMRustSynchronizationScope::SingleThread:
392 return SyncScope::SingleThread;
393 case LLVMRustSynchronizationScope::CrossThread:
394 return SyncScope::System;
396 report_fatal_error("bad SynchronizationScope.");
400 extern "C" LLVMValueRef
401 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
402 LLVMRustSynchronizationScope Scope) {
403 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
406 enum class LLVMRustAsmDialect {
411 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
413 case LLVMRustAsmDialect::Att:
414 return InlineAsm::AD_ATT;
415 case LLVMRustAsmDialect::Intel:
416 return InlineAsm::AD_Intel;
418 report_fatal_error("bad AsmDialect.");
422 extern "C" LLVMValueRef
423 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
424 char *Constraints, size_t ConstraintsLen,
425 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
426 LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
427 #if LLVM_VERSION_GE(13, 0)
428 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
429 StringRef(AsmString, AsmStringLen),
430 StringRef(Constraints, ConstraintsLen),
431 HasSideEffects, IsAlignStack,
432 fromRust(Dialect), CanThrow));
434 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
435 StringRef(AsmString, AsmStringLen),
436 StringRef(Constraints, ConstraintsLen),
437 HasSideEffects, IsAlignStack,
442 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
443 size_t ConstraintsLen) {
444 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
445 StringRef(Constraints, ConstraintsLen));
448 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
450 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
453 typedef DIBuilder *LLVMRustDIBuilderRef;
455 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
456 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
459 #define DIDescriptor DIScope
460 #define DIArray DINodeArray
461 #define unwrapDI unwrapDIPtr
463 // These values **must** match debuginfo::DIFlags! They also *happen*
464 // to match LLVM, but that isn't required as we do giant sets of
465 // matching below. The value shouldn't be directly passed to LLVM.
466 enum class LLVMRustDIFlags : uint32_t {
471 FlagFwdDecl = (1 << 2),
472 FlagAppleBlock = (1 << 3),
473 FlagBlockByrefStruct = (1 << 4),
474 FlagVirtual = (1 << 5),
475 FlagArtificial = (1 << 6),
476 FlagExplicit = (1 << 7),
477 FlagPrototyped = (1 << 8),
478 FlagObjcClassComplete = (1 << 9),
479 FlagObjectPointer = (1 << 10),
480 FlagVector = (1 << 11),
481 FlagStaticMember = (1 << 12),
482 FlagLValueReference = (1 << 13),
483 FlagRValueReference = (1 << 14),
484 FlagExternalTypeRef = (1 << 15),
485 FlagIntroducedVirtual = (1 << 18),
486 FlagBitField = (1 << 19),
487 FlagNoReturn = (1 << 20),
488 // Do not add values that are not supported by the minimum LLVM
489 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
492 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
493 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
494 static_cast<uint32_t>(B));
497 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
498 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
499 static_cast<uint32_t>(B));
502 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
506 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
508 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
509 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
512 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
513 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
515 switch (visibility(Flags)) {
516 case LLVMRustDIFlags::FlagPrivate:
517 Result |= DINode::DIFlags::FlagPrivate;
519 case LLVMRustDIFlags::FlagProtected:
520 Result |= DINode::DIFlags::FlagProtected;
522 case LLVMRustDIFlags::FlagPublic:
523 Result |= DINode::DIFlags::FlagPublic;
526 // The rest are handled below
530 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
531 Result |= DINode::DIFlags::FlagFwdDecl;
533 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
534 Result |= DINode::DIFlags::FlagAppleBlock;
536 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
537 Result |= DINode::DIFlags::FlagVirtual;
539 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
540 Result |= DINode::DIFlags::FlagArtificial;
542 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
543 Result |= DINode::DIFlags::FlagExplicit;
545 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
546 Result |= DINode::DIFlags::FlagPrototyped;
548 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
549 Result |= DINode::DIFlags::FlagObjcClassComplete;
551 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
552 Result |= DINode::DIFlags::FlagObjectPointer;
554 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
555 Result |= DINode::DIFlags::FlagVector;
557 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
558 Result |= DINode::DIFlags::FlagStaticMember;
560 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
561 Result |= DINode::DIFlags::FlagLValueReference;
563 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
564 Result |= DINode::DIFlags::FlagRValueReference;
566 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
567 Result |= DINode::DIFlags::FlagIntroducedVirtual;
569 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
570 Result |= DINode::DIFlags::FlagBitField;
572 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
573 Result |= DINode::DIFlags::FlagNoReturn;
579 // These values **must** match debuginfo::DISPFlags! They also *happen*
580 // to match LLVM, but that isn't required as we do giant sets of
581 // matching below. The value shouldn't be directly passed to LLVM.
582 enum class LLVMRustDISPFlags : uint32_t {
585 SPFlagPureVirtual = 2,
586 SPFlagLocalToUnit = (1 << 2),
587 SPFlagDefinition = (1 << 3),
588 SPFlagOptimized = (1 << 4),
589 SPFlagMainSubprogram = (1 << 5),
590 // Do not add values that are not supported by the minimum LLVM
591 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
592 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
595 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
596 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
597 static_cast<uint32_t>(B));
600 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
601 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
602 static_cast<uint32_t>(B));
605 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
609 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
611 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
612 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
615 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
616 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
618 switch (virtuality(SPFlags)) {
619 case LLVMRustDISPFlags::SPFlagVirtual:
620 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
622 case LLVMRustDISPFlags::SPFlagPureVirtual:
623 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
626 // The rest are handled below
630 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
631 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
633 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
634 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
636 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
637 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
639 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
640 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
646 enum class LLVMRustDebugEmissionKind {
652 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
654 case LLVMRustDebugEmissionKind::NoDebug:
655 return DICompileUnit::DebugEmissionKind::NoDebug;
656 case LLVMRustDebugEmissionKind::FullDebug:
657 return DICompileUnit::DebugEmissionKind::FullDebug;
658 case LLVMRustDebugEmissionKind::LineTablesOnly:
659 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
661 report_fatal_error("bad DebugEmissionKind.");
665 enum class LLVMRustChecksumKind {
672 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
674 case LLVMRustChecksumKind::None:
676 case LLVMRustChecksumKind::MD5:
677 return DIFile::ChecksumKind::CSK_MD5;
678 case LLVMRustChecksumKind::SHA1:
679 return DIFile::ChecksumKind::CSK_SHA1;
680 case LLVMRustChecksumKind::SHA256:
681 return DIFile::ChecksumKind::CSK_SHA256;
683 report_fatal_error("bad ChecksumKind.");
687 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
688 return DEBUG_METADATA_VERSION;
691 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
693 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
695 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
697 extern "C" bool LLVMRustIsRustLLVM() {
705 extern "C" void LLVMRustAddModuleFlag(
707 Module::ModFlagBehavior MergeBehavior,
710 unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
713 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
714 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
717 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
718 return new DIBuilder(*unwrap(M));
721 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
725 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
729 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
730 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
731 const char *Producer, size_t ProducerLen, bool isOptimized,
732 const char *Flags, unsigned RuntimeVer,
733 const char *SplitName, size_t SplitNameLen,
734 LLVMRustDebugEmissionKind Kind,
735 uint64_t DWOId, bool SplitDebugInlining) {
736 auto *File = unwrapDI<DIFile>(FileRef);
738 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
739 isOptimized, Flags, RuntimeVer,
740 StringRef(SplitName, SplitNameLen),
741 fromRust(Kind), DWOId, SplitDebugInlining));
744 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
745 LLVMRustDIBuilderRef Builder,
746 const char *Filename, size_t FilenameLen,
747 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
748 const char *Checksum, size_t ChecksumLen) {
749 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
750 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
752 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
753 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
754 StringRef(Directory, DirectoryLen),
758 extern "C" LLVMMetadataRef
759 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
760 LLVMMetadataRef ParameterTypes) {
761 return wrap(Builder->createSubroutineType(
762 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
765 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
766 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
767 const char *Name, size_t NameLen,
768 const char *LinkageName, size_t LinkageNameLen,
769 LLVMMetadataRef File, unsigned LineNo,
770 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
771 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
772 LLVMMetadataRef Decl) {
773 DITemplateParameterArray TParams =
774 DITemplateParameterArray(unwrap<MDTuple>(TParam));
775 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
776 DINode::DIFlags llvmFlags = fromRust(Flags);
777 DISubprogram *Sub = Builder->createFunction(
778 unwrapDI<DIScope>(Scope),
779 StringRef(Name, NameLen),
780 StringRef(LinkageName, LinkageNameLen),
781 unwrapDI<DIFile>(File), LineNo,
782 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
783 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
785 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
789 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
790 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
791 uint64_t SizeInBits, unsigned Encoding) {
792 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
795 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
796 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
797 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
798 return wrap(Builder->createTypedef(
799 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
800 LineNo, unwrapDIPtr<DIScope>(Scope)));
803 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
804 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
805 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
806 const char *Name, size_t NameLen) {
807 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
808 SizeInBits, AlignInBits,
810 StringRef(Name, NameLen)));
813 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
814 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
815 const char *Name, size_t NameLen,
816 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
817 uint32_t AlignInBits, LLVMRustDIFlags Flags,
818 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
819 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
820 const char *UniqueId, size_t UniqueIdLen) {
821 return wrap(Builder->createStructType(
822 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
823 unwrapDI<DIFile>(File), LineNumber,
824 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
825 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
826 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
829 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
830 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
831 const char *Name, size_t NameLen,
832 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
833 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
834 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
835 return wrap(Builder->createVariantPart(
836 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
837 unwrapDI<DIFile>(File), LineNumber,
838 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
839 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
842 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
843 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
844 const char *Name, size_t NameLen,
845 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
846 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
847 LLVMMetadataRef Ty) {
848 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
849 StringRef(Name, NameLen),
850 unwrapDI<DIFile>(File), LineNo,
851 SizeInBits, AlignInBits, OffsetInBits,
852 fromRust(Flags), unwrapDI<DIType>(Ty)));
855 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
856 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
857 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
858 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
859 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
860 llvm::ConstantInt* D = nullptr;
862 D = unwrap<llvm::ConstantInt>(Discriminant);
864 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
865 StringRef(Name, NameLen),
866 unwrapDI<DIFile>(File), LineNo,
867 SizeInBits, AlignInBits, OffsetInBits, D,
868 fromRust(Flags), unwrapDI<DIType>(Ty)));
871 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
872 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
873 LLVMMetadataRef File, unsigned Line, unsigned Col) {
874 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
875 unwrapDI<DIFile>(File), Line, Col));
878 extern "C" LLVMMetadataRef
879 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
880 LLVMMetadataRef Scope,
881 LLVMMetadataRef File) {
882 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
883 unwrapDI<DIFile>(File)));
886 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
887 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
888 const char *Name, size_t NameLen,
889 const char *LinkageName, size_t LinkageNameLen,
890 LLVMMetadataRef File, unsigned LineNo,
891 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
892 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
893 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
895 llvm::DIExpression *InitExpr = nullptr;
896 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
897 InitExpr = Builder->createConstantValueExpression(
898 IntVal->getValue().getSExtValue());
899 } else if (llvm::ConstantFP *FPVal =
900 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
901 InitExpr = Builder->createConstantValueExpression(
902 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
905 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
906 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
907 StringRef(LinkageName, LinkageNameLen),
908 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
909 /* isDefined */ true,
910 InitExpr, unwrapDIPtr<MDNode>(Decl),
911 /* templateParams */ nullptr,
914 InitVal->setMetadata("dbg", VarExpr);
916 return wrap(VarExpr);
919 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
920 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
921 const char *Name, size_t NameLen,
922 LLVMMetadataRef File, unsigned LineNo,
923 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
924 unsigned ArgNo, uint32_t AlignInBits) {
925 if (Tag == 0x100) { // DW_TAG_auto_variable
926 return wrap(Builder->createAutoVariable(
927 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
928 unwrapDI<DIFile>(File), LineNo,
929 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
931 return wrap(Builder->createParameterVariable(
932 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
933 unwrapDI<DIFile>(File), LineNo,
934 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
938 extern "C" LLVMMetadataRef
939 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
940 uint32_t AlignInBits, LLVMMetadataRef Ty,
941 LLVMMetadataRef Subscripts) {
943 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
944 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
947 extern "C" LLVMMetadataRef
948 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
950 return wrap(Builder->getOrCreateSubrange(Lo, Count));
953 extern "C" LLVMMetadataRef
954 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
955 LLVMMetadataRef *Ptr, unsigned Count) {
956 Metadata **DataValue = unwrap(Ptr);
958 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
961 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
962 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
963 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
964 LLVMBasicBlockRef InsertAtEnd) {
965 return wrap(Builder->insertDeclare(
966 unwrap(V), unwrap<DILocalVariable>(VarInfo),
967 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
968 DebugLoc(cast<MDNode>(unwrap(DL))),
969 unwrap(InsertAtEnd)));
972 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
973 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
974 int64_t Value, bool IsUnsigned) {
975 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
978 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
979 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
980 const char *Name, size_t NameLen,
981 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
982 uint32_t AlignInBits, LLVMMetadataRef Elements,
983 LLVMMetadataRef ClassTy, bool IsScoped) {
984 return wrap(Builder->createEnumerationType(
985 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
986 unwrapDI<DIFile>(File), LineNumber,
987 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
988 unwrapDI<DIType>(ClassTy), "", IsScoped));
991 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
992 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
993 const char *Name, size_t NameLen,
994 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
995 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
996 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
997 return wrap(Builder->createUnionType(
998 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
999 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1000 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1001 StringRef(UniqueId, UniqueIdLen)));
1004 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1005 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1006 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1007 bool IsDefault = false; // FIXME: should we ever set this true?
1008 return wrap(Builder->createTemplateTypeParameter(
1009 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1012 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1013 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1014 const char *Name, size_t NameLen, bool ExportSymbols) {
1015 return wrap(Builder->createNameSpace(
1016 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1021 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1022 LLVMMetadataRef CompositeTy,
1023 LLVMMetadataRef Elements,
1024 LLVMMetadataRef Params) {
1025 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1026 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1027 DINodeArray(unwrap<MDTuple>(Params)));
1030 extern "C" LLVMMetadataRef
1031 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1032 LLVMMetadataRef ScopeRef,
1033 LLVMMetadataRef InlinedAt) {
1034 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1035 DILocation *Loc = DILocation::get(
1036 Scope->getContext(), Line, Column, Scope,
1037 unwrapDIPtr<MDNode>(InlinedAt));
1041 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1042 return dwarf::DW_OP_deref;
1045 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1046 return dwarf::DW_OP_plus_uconst;
1049 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1050 RawRustStringOstream OS(Str);
1051 unwrap<llvm::Type>(Ty)->print(OS);
1054 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1055 RustStringRef Str) {
1056 RawRustStringOstream OS(Str);
1061 unwrap<llvm::Value>(V)->getType()->print(OS);
1063 unwrap<llvm::Value>(V)->print(OS);
1068 // LLVMArrayType function does not support 64-bit ElementCount
1069 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1070 uint64_t ElementCount) {
1071 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1074 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1076 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1077 RawRustStringOstream OS(Str);
1078 unwrap(T)->print(OS);
1081 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1082 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1083 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1084 RustStringRef FilenameOut, RustStringRef MessageOut) {
1085 // Undefined to call this not on an optimization diagnostic!
1086 llvm::DiagnosticInfoOptimizationBase *Opt =
1087 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1089 RawRustStringOstream PassNameOS(PassNameOut);
1090 PassNameOS << Opt->getPassName();
1091 *FunctionOut = wrap(&Opt->getFunction());
1093 RawRustStringOstream FilenameOS(FilenameOut);
1094 DiagnosticLocation loc = Opt->getLocation();
1095 if (loc.isValid()) {
1096 *Line = loc.getLine();
1097 *Column = loc.getColumn();
1098 FilenameOS << loc.getAbsolutePath();
1101 RawRustStringOstream MessageOS(MessageOut);
1102 MessageOS << Opt->getMsg();
1105 enum class LLVMRustDiagnosticLevel {
1113 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1114 LLVMRustDiagnosticLevel *LevelOut,
1115 unsigned *CookieOut,
1116 LLVMTwineRef *MessageOut) {
1117 // Undefined to call this not on an inline assembly diagnostic!
1118 llvm::DiagnosticInfoInlineAsm *IA =
1119 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1121 *CookieOut = IA->getLocCookie();
1122 *MessageOut = wrap(&IA->getMsgStr());
1124 switch (IA->getSeverity()) {
1126 *LevelOut = LLVMRustDiagnosticLevel::Error;
1129 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1132 *LevelOut = LLVMRustDiagnosticLevel::Note;
1135 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1138 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1142 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1143 RustStringRef Str) {
1144 RawRustStringOstream OS(Str);
1145 DiagnosticPrinterRawOStream DP(OS);
1146 unwrap(DI)->print(DP);
1149 enum class LLVMRustDiagnosticKind {
1153 DebugMetadataVersion,
1156 OptimizationRemarkMissed,
1157 OptimizationRemarkAnalysis,
1158 OptimizationRemarkAnalysisFPCommute,
1159 OptimizationRemarkAnalysisAliasing,
1160 OptimizationRemarkOther,
1161 OptimizationFailure,
1168 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1171 return LLVMRustDiagnosticKind::InlineAsm;
1173 return LLVMRustDiagnosticKind::StackSize;
1174 case DK_DebugMetadataVersion:
1175 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1176 case DK_SampleProfile:
1177 return LLVMRustDiagnosticKind::SampleProfile;
1178 case DK_OptimizationRemark:
1179 case DK_MachineOptimizationRemark:
1180 return LLVMRustDiagnosticKind::OptimizationRemark;
1181 case DK_OptimizationRemarkMissed:
1182 case DK_MachineOptimizationRemarkMissed:
1183 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1184 case DK_OptimizationRemarkAnalysis:
1185 case DK_MachineOptimizationRemarkAnalysis:
1186 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1187 case DK_OptimizationRemarkAnalysisFPCommute:
1188 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1189 case DK_OptimizationRemarkAnalysisAliasing:
1190 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1192 return LLVMRustDiagnosticKind::PGOProfile;
1194 return LLVMRustDiagnosticKind::Linker;
1195 case DK_Unsupported:
1196 return LLVMRustDiagnosticKind::Unsupported;
1197 #if LLVM_VERSION_GE(13, 0)
1199 return LLVMRustDiagnosticKind::SrcMgr;
1202 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1203 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1204 : LLVMRustDiagnosticKind::Other;
1208 extern "C" LLVMRustDiagnosticKind
1209 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1210 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1213 // This is kept distinct from LLVMGetTypeKind, because when
1214 // a new type kind is added, the Rust-side enum must be
1215 // updated or UB will result.
1216 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1217 switch (unwrap(Ty)->getTypeID()) {
1218 case Type::VoidTyID:
1219 return LLVMVoidTypeKind;
1220 case Type::HalfTyID:
1221 return LLVMHalfTypeKind;
1222 case Type::FloatTyID:
1223 return LLVMFloatTypeKind;
1224 case Type::DoubleTyID:
1225 return LLVMDoubleTypeKind;
1226 case Type::X86_FP80TyID:
1227 return LLVMX86_FP80TypeKind;
1228 case Type::FP128TyID:
1229 return LLVMFP128TypeKind;
1230 case Type::PPC_FP128TyID:
1231 return LLVMPPC_FP128TypeKind;
1232 case Type::LabelTyID:
1233 return LLVMLabelTypeKind;
1234 case Type::MetadataTyID:
1235 return LLVMMetadataTypeKind;
1236 case Type::IntegerTyID:
1237 return LLVMIntegerTypeKind;
1238 case Type::FunctionTyID:
1239 return LLVMFunctionTypeKind;
1240 case Type::StructTyID:
1241 return LLVMStructTypeKind;
1242 case Type::ArrayTyID:
1243 return LLVMArrayTypeKind;
1244 case Type::PointerTyID:
1245 return LLVMPointerTypeKind;
1246 case Type::FixedVectorTyID:
1247 return LLVMVectorTypeKind;
1248 case Type::X86_MMXTyID:
1249 return LLVMX86_MMXTypeKind;
1250 case Type::TokenTyID:
1251 return LLVMTokenTypeKind;
1252 case Type::ScalableVectorTyID:
1253 return LLVMScalableVectorTypeKind;
1254 case Type::BFloatTyID:
1255 return LLVMBFloatTypeKind;
1256 case Type::X86_AMXTyID:
1257 return LLVMX86_AMXTypeKind;
1259 report_fatal_error("Unhandled TypeID.");
1262 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1264 #if LLVM_VERSION_LT(13, 0)
1265 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1267 using LLVMInlineAsmDiagHandlerTy = void*;
1270 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1271 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1272 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1273 // with LLVM 13 this function is gone.
1274 #if LLVM_VERSION_LT(13, 0)
1275 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1279 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1280 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1281 #if LLVM_VERSION_GE(13, 0)
1282 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1283 *Cookie = SM->getLocCookie();
1284 return wrap(&SM->getSMDiag());
1286 report_fatal_error("Shouldn't get called on older versions");
1290 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1291 RustStringRef MessageOut,
1292 RustStringRef BufferOut,
1293 LLVMRustDiagnosticLevel* LevelOut,
1295 unsigned* RangesOut,
1296 size_t* NumRanges) {
1297 SMDiagnostic& D = *unwrap(DRef);
1298 RawRustStringOstream MessageOS(MessageOut);
1299 MessageOS << D.getMessage();
1301 switch (D.getKind()) {
1302 case SourceMgr::DK_Error:
1303 *LevelOut = LLVMRustDiagnosticLevel::Error;
1305 case SourceMgr::DK_Warning:
1306 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1308 case SourceMgr::DK_Note:
1309 *LevelOut = LLVMRustDiagnosticLevel::Note;
1311 case SourceMgr::DK_Remark:
1312 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1315 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1318 if (D.getLoc() == SMLoc())
1321 const SourceMgr &LSM = *D.getSourceMgr();
1322 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1323 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1325 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1327 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1328 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1329 for (size_t i = 0; i < *NumRanges; i++) {
1330 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1331 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1337 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1338 LLVMValueRef ParentPad,
1340 LLVMValueRef *LLArgs,
1342 Value **Args = unwrap(LLArgs);
1343 if (ParentPad == nullptr) {
1344 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1345 ParentPad = wrap(Constant::getNullValue(Ty));
1347 return wrap(unwrap(B)->CreateCleanupPad(
1348 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1351 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1352 LLVMValueRef CleanupPad,
1353 LLVMBasicBlockRef UnwindBB) {
1354 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1355 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1358 extern "C" LLVMValueRef
1359 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1360 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1361 Value **Args = unwrap(LLArgs);
1362 return wrap(unwrap(B)->CreateCatchPad(
1363 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1366 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1368 LLVMBasicBlockRef BB) {
1369 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1373 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1374 LLVMValueRef ParentPad,
1375 LLVMBasicBlockRef BB,
1376 unsigned NumHandlers,
1378 if (ParentPad == nullptr) {
1379 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1380 ParentPad = wrap(Constant::getNullValue(Ty));
1382 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1383 NumHandlers, Name));
1386 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1387 LLVMBasicBlockRef Handler) {
1388 Value *CatchSwitch = unwrap(CatchSwitchRef);
1389 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1392 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1393 LLVMValueRef *Inputs,
1394 unsigned NumInputs) {
1395 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1398 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1402 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1403 LLVMValueRef *Args, unsigned NumArgs,
1404 OperandBundleDef *Bundle) {
1405 Value *Callee = unwrap(Fn);
1406 FunctionType *FTy = unwrap<FunctionType>(Ty);
1407 unsigned Len = Bundle ? 1 : 0;
1408 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1409 return wrap(unwrap(B)->CreateCall(
1410 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1413 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1414 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1415 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1418 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1419 LLVMValueRef Dst, unsigned DstAlign,
1420 LLVMValueRef Src, unsigned SrcAlign,
1421 LLVMValueRef Size, bool IsVolatile) {
1422 return wrap(unwrap(B)->CreateMemCpy(
1423 unwrap(Dst), MaybeAlign(DstAlign),
1424 unwrap(Src), MaybeAlign(SrcAlign),
1425 unwrap(Size), IsVolatile));
1428 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1429 LLVMValueRef Dst, unsigned DstAlign,
1430 LLVMValueRef Src, unsigned SrcAlign,
1431 LLVMValueRef Size, bool IsVolatile) {
1432 return wrap(unwrap(B)->CreateMemMove(
1433 unwrap(Dst), MaybeAlign(DstAlign),
1434 unwrap(Src), MaybeAlign(SrcAlign),
1435 unwrap(Size), IsVolatile));
1438 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1439 LLVMValueRef Dst, unsigned DstAlign,
1441 LLVMValueRef Size, bool IsVolatile) {
1442 return wrap(unwrap(B)->CreateMemSet(
1443 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1446 extern "C" LLVMValueRef
1447 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1448 LLVMValueRef *Args, unsigned NumArgs,
1449 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1450 OperandBundleDef *Bundle, const char *Name) {
1451 Value *Callee = unwrap(Fn);
1452 FunctionType *FTy = unwrap<FunctionType>(Ty);
1453 unsigned Len = Bundle ? 1 : 0;
1454 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1455 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1456 makeArrayRef(unwrap(Args), NumArgs),
1460 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1461 LLVMBasicBlockRef BB) {
1462 auto Point = unwrap(BB)->getFirstInsertionPt();
1463 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1466 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1467 const char *Name, size_t NameLen) {
1468 Triple TargetTriple(unwrap(M)->getTargetTriple());
1469 GlobalObject *GV = unwrap<GlobalObject>(V);
1470 if (TargetTriple.supportsCOMDAT()) {
1471 StringRef NameRef(Name, NameLen);
1472 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1476 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1477 GlobalObject *GV = unwrap<GlobalObject>(V);
1478 GV->setComdat(nullptr);
1481 enum class LLVMRustLinkage {
1482 ExternalLinkage = 0,
1483 AvailableExternallyLinkage = 1,
1484 LinkOnceAnyLinkage = 2,
1485 LinkOnceODRLinkage = 3,
1488 AppendingLinkage = 6,
1489 InternalLinkage = 7,
1491 ExternalWeakLinkage = 9,
1495 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1497 case LLVMExternalLinkage:
1498 return LLVMRustLinkage::ExternalLinkage;
1499 case LLVMAvailableExternallyLinkage:
1500 return LLVMRustLinkage::AvailableExternallyLinkage;
1501 case LLVMLinkOnceAnyLinkage:
1502 return LLVMRustLinkage::LinkOnceAnyLinkage;
1503 case LLVMLinkOnceODRLinkage:
1504 return LLVMRustLinkage::LinkOnceODRLinkage;
1505 case LLVMWeakAnyLinkage:
1506 return LLVMRustLinkage::WeakAnyLinkage;
1507 case LLVMWeakODRLinkage:
1508 return LLVMRustLinkage::WeakODRLinkage;
1509 case LLVMAppendingLinkage:
1510 return LLVMRustLinkage::AppendingLinkage;
1511 case LLVMInternalLinkage:
1512 return LLVMRustLinkage::InternalLinkage;
1513 case LLVMPrivateLinkage:
1514 return LLVMRustLinkage::PrivateLinkage;
1515 case LLVMExternalWeakLinkage:
1516 return LLVMRustLinkage::ExternalWeakLinkage;
1517 case LLVMCommonLinkage:
1518 return LLVMRustLinkage::CommonLinkage;
1520 report_fatal_error("Invalid LLVMRustLinkage value!");
1524 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1526 case LLVMRustLinkage::ExternalLinkage:
1527 return LLVMExternalLinkage;
1528 case LLVMRustLinkage::AvailableExternallyLinkage:
1529 return LLVMAvailableExternallyLinkage;
1530 case LLVMRustLinkage::LinkOnceAnyLinkage:
1531 return LLVMLinkOnceAnyLinkage;
1532 case LLVMRustLinkage::LinkOnceODRLinkage:
1533 return LLVMLinkOnceODRLinkage;
1534 case LLVMRustLinkage::WeakAnyLinkage:
1535 return LLVMWeakAnyLinkage;
1536 case LLVMRustLinkage::WeakODRLinkage:
1537 return LLVMWeakODRLinkage;
1538 case LLVMRustLinkage::AppendingLinkage:
1539 return LLVMAppendingLinkage;
1540 case LLVMRustLinkage::InternalLinkage:
1541 return LLVMInternalLinkage;
1542 case LLVMRustLinkage::PrivateLinkage:
1543 return LLVMPrivateLinkage;
1544 case LLVMRustLinkage::ExternalWeakLinkage:
1545 return LLVMExternalWeakLinkage;
1546 case LLVMRustLinkage::CommonLinkage:
1547 return LLVMCommonLinkage;
1549 report_fatal_error("Invalid LLVMRustLinkage value!");
1552 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1553 return toRust(LLVMGetLinkage(V));
1556 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1557 LLVMRustLinkage RustLinkage) {
1558 LLVMSetLinkage(V, fromRust(RustLinkage));
1561 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1562 LLVMValueRef ConstantVal,
1563 LLVMValueRef *ConstantIndices,
1564 unsigned NumIndices) {
1565 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1567 Constant *Val = unwrap<Constant>(ConstantVal);
1568 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1571 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1572 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1573 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1575 auto C = unwrap<llvm::ConstantInt>(CV);
1576 if (C->getBitWidth() > 128) { return false; }
1579 AP = C->getValue().sextOrSelf(128);
1581 AP = C->getValue().zextOrSelf(128);
1583 *low = AP.getLoBits(64).getZExtValue();
1584 *high = AP.getHiBits(64).getZExtValue();
1588 enum class LLVMRustVisibility {
1594 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1596 case LLVMDefaultVisibility:
1597 return LLVMRustVisibility::Default;
1598 case LLVMHiddenVisibility:
1599 return LLVMRustVisibility::Hidden;
1600 case LLVMProtectedVisibility:
1601 return LLVMRustVisibility::Protected;
1603 report_fatal_error("Invalid LLVMRustVisibility value!");
1606 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1608 case LLVMRustVisibility::Default:
1609 return LLVMDefaultVisibility;
1610 case LLVMRustVisibility::Hidden:
1611 return LLVMHiddenVisibility;
1612 case LLVMRustVisibility::Protected:
1613 return LLVMProtectedVisibility;
1615 report_fatal_error("Invalid LLVMRustVisibility value!");
1618 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1619 return toRust(LLVMGetVisibility(V));
1622 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1623 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1624 LLVMTypeRef DestTy, bool isSigned) {
1625 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1628 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1629 LLVMRustVisibility RustVisibility) {
1630 LLVMSetVisibility(V, fromRust(RustVisibility));
1633 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1634 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1637 struct LLVMRustModuleBuffer {
1641 extern "C" LLVMRustModuleBuffer*
1642 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1643 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1645 raw_string_ostream OS(Ret->data);
1647 legacy::PassManager PM;
1648 PM.add(createBitcodeWriterPass(OS));
1652 return Ret.release();
1656 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1660 extern "C" const void*
1661 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1662 return Buffer->data.data();
1666 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1667 return Buffer->data.length();
1671 LLVMRustModuleCost(LLVMModuleRef M) {
1672 auto f = unwrap(M)->functions();
1673 return std::distance(std::begin(f), std::end(f));
1676 // Vector reductions:
1677 extern "C" LLVMValueRef
1678 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1679 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1681 extern "C" LLVMValueRef
1682 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1683 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1685 extern "C" LLVMValueRef
1686 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1687 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1689 extern "C" LLVMValueRef
1690 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1691 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1693 extern "C" LLVMValueRef
1694 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1695 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1697 extern "C" LLVMValueRef
1698 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1699 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1701 extern "C" LLVMValueRef
1702 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1703 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1705 extern "C" LLVMValueRef
1706 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1707 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1709 extern "C" LLVMValueRef
1710 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1711 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1713 extern "C" LLVMValueRef
1714 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1715 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1716 I->setHasNoNaNs(NoNaN);
1719 extern "C" LLVMValueRef
1720 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1721 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1722 I->setHasNoNaNs(NoNaN);
1726 extern "C" LLVMValueRef
1727 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1728 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1730 extern "C" LLVMValueRef
1731 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1732 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1735 // This struct contains all necessary info about a symbol exported from a DLL.
1736 struct LLVMRustCOFFShortExport {
1738 bool ordinal_present;
1739 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1743 // Machine must be a COFF machine type, as defined in PE specs.
1744 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1745 const char* ImportName,
1747 const LLVMRustCOFFShortExport* Exports,
1752 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1753 ConvertedExports.reserve(NumExports);
1755 for (size_t i = 0; i < NumExports; ++i) {
1756 bool ordinal_present = Exports[i].ordinal_present;
1757 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1758 ConvertedExports.push_back(llvm::object::COFFShortExport{
1759 Exports[i].name, // Name
1760 std::string{}, // ExtName
1761 std::string{}, // SymbolName
1762 std::string{}, // AliasTarget
1764 ordinal_present, // Noname
1771 auto Error = llvm::object::writeImportLibrary(
1775 static_cast<llvm::COFF::MachineTypes>(Machine),
1778 std::string errorString;
1779 llvm::raw_string_ostream stream(errorString);
1782 LLVMRustSetLastError(errorString.c_str());
1783 return LLVMRustResult::Failure;
1785 return LLVMRustResult::Success;
1789 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1790 extern "C" DiagnosticHandler *
1791 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1792 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1793 return DH.release();
1796 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1797 // handling. Ownership of the handler is moved to the LLVMContext.
1798 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1799 DiagnosticHandler *DH) {
1800 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1803 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1805 // Configures a diagnostic handler that invokes provided callback when a
1806 // backend needs to emit a diagnostic.
1808 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1809 // the RemarkPasses array specifies individual passes for which remarks will be
1811 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1812 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1813 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1814 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1816 class RustDiagnosticHandler final : public DiagnosticHandler {
1818 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1819 void *DiagnosticHandlerContext,
1820 bool RemarkAllPasses,
1821 std::vector<std::string> RemarkPasses)
1822 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1823 DiagnosticHandlerContext(DiagnosticHandlerContext),
1824 RemarkAllPasses(RemarkAllPasses),
1825 RemarkPasses(RemarkPasses) {}
1827 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1828 if (DiagnosticHandlerCallback) {
1829 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1835 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1836 return isRemarkEnabled(PassName);
1839 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1840 return isRemarkEnabled(PassName);
1843 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1844 return isRemarkEnabled(PassName);
1847 bool isAnyRemarkEnabled() const override {
1848 return RemarkAllPasses || !RemarkPasses.empty();
1852 bool isRemarkEnabled(StringRef PassName) const {
1853 if (RemarkAllPasses)
1856 for (auto &Pass : RemarkPasses)
1857 if (Pass == PassName)
1863 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1864 void *DiagnosticHandlerContext = nullptr;
1866 bool RemarkAllPasses = false;
1867 std::vector<std::string> RemarkPasses;
1870 std::vector<std::string> Passes;
1871 for (size_t I = 0; I != RemarkPassesLen; ++I)
1872 Passes.push_back(RemarkPasses[I]);
1874 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1875 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));