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/IR/IntrinsicsARM.h"
10 #include "llvm/IR/Mangler.h"
11 #include "llvm/Object/Archive.h"
12 #include "llvm/Object/COFFImportFile.h"
13 #include "llvm/Object/ObjectFile.h"
14 #include "llvm/Pass.h"
15 #include "llvm/Bitcode/BitcodeWriterPass.h"
16 #include "llvm/Support/Signals.h"
17 #include "llvm/ADT/Optional.h"
21 //===----------------------------------------------------------------------===
23 // This file defines alternate interfaces to core functions that are more
24 // readily callable by Rust's FFI.
26 //===----------------------------------------------------------------------===
29 using namespace llvm::sys;
30 using namespace llvm::object;
32 // LLVMAtomicOrdering is already an enum - don't create another
34 static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
36 case LLVMAtomicOrderingNotAtomic:
37 return AtomicOrdering::NotAtomic;
38 case LLVMAtomicOrderingUnordered:
39 return AtomicOrdering::Unordered;
40 case LLVMAtomicOrderingMonotonic:
41 return AtomicOrdering::Monotonic;
42 case LLVMAtomicOrderingAcquire:
43 return AtomicOrdering::Acquire;
44 case LLVMAtomicOrderingRelease:
45 return AtomicOrdering::Release;
46 case LLVMAtomicOrderingAcquireRelease:
47 return AtomicOrdering::AcquireRelease;
48 case LLVMAtomicOrderingSequentiallyConsistent:
49 return AtomicOrdering::SequentiallyConsistent;
52 report_fatal_error("Invalid LLVMAtomicOrdering value!");
55 static LLVM_THREAD_LOCAL char *LastError;
57 // Custom error handler for fatal LLVM errors.
59 // Notably it exits the process with code 101, unlike LLVM's default of 1.
60 static void FatalErrorHandler(void *UserData,
61 #if LLVM_VERSION_LT(14, 0)
62 const std::string& Reason,
67 // Do the same thing that the default error handler does.
68 std::cerr << "LLVM ERROR: " << Reason << std::endl;
70 // Since this error handler exits the process, we have to run any cleanup that
71 // LLVM would run after handling the error. This might change with an LLVM
73 sys::RunInterruptHandlers();
78 extern "C" void LLVMRustInstallFatalErrorHandler() {
79 install_fatal_error_handler(FatalErrorHandler);
82 extern "C" void LLVMRustDisableSystemDialogsOnCrash() {
83 sys::DisableSystemDialogsOnCrash();
86 extern "C" char *LLVMRustGetLastError(void) {
87 char *Ret = LastError;
92 extern "C" void LLVMRustSetLastError(const char *Err) {
93 free((void *)LastError);
94 LastError = strdup(Err);
97 extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
98 auto ctx = new LLVMContext();
99 ctx->setDiscardValueNames(shouldDiscardNames);
103 extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
104 const char *Triple) {
105 unwrap(M)->setTargetTriple(Triple::normalize(Triple));
108 extern "C" void LLVMRustPrintPassTimings() {
109 raw_fd_ostream OS(2, false); // stderr.
110 TimerGroup::printAll(OS);
113 extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
115 return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
118 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
121 LLVMTypeRef FunctionTy) {
122 return wrap(unwrap(M)
123 ->getOrInsertFunction(StringRef(Name, NameLen),
124 unwrap<FunctionType>(FunctionTy))
129 extern "C" LLVMValueRef
130 LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
131 Module *Mod = unwrap(M);
132 StringRef NameRef(Name, NameLen);
134 // We don't use Module::getOrInsertGlobal because that returns a Constant*,
135 // which may either be the real GlobalVariable*, or a constant bitcast of it
136 // if our type doesn't match the original declaration. We always want the
137 // GlobalVariable* so we can access linkage, visibility, etc.
138 GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true);
140 GV = new GlobalVariable(*Mod, unwrap(Ty), false,
141 GlobalValue::ExternalLinkage, nullptr, NameRef);
145 extern "C" LLVMValueRef
146 LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
147 return wrap(new GlobalVariable(*unwrap(M),
150 GlobalValue::PrivateLinkage,
154 extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
155 return wrap(Type::getMetadataTy(*unwrap(C)));
158 static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
161 return Attribute::AlwaysInline;
163 return Attribute::ByVal;
165 return Attribute::Cold;
167 return Attribute::InlineHint;
169 return Attribute::MinSize;
171 return Attribute::Naked;
173 return Attribute::NoAlias;
175 return Attribute::NoCapture;
177 return Attribute::NoCfCheck;
179 return Attribute::NoInline;
181 return Attribute::NonNull;
183 return Attribute::NoRedZone;
185 return Attribute::NoReturn;
187 return Attribute::NoUnwind;
188 case OptimizeForSize:
189 return Attribute::OptimizeForSize;
191 return Attribute::ReadOnly;
193 return Attribute::SExt;
195 return Attribute::StructRet;
197 return Attribute::UWTable;
199 return Attribute::ZExt;
201 return Attribute::InReg;
203 return Attribute::SanitizeThread;
204 case SanitizeAddress:
205 return Attribute::SanitizeAddress;
207 return Attribute::SanitizeMemory;
209 return Attribute::NonLazyBind;
211 return Attribute::OptimizeNone;
213 return Attribute::ReturnsTwice;
215 return Attribute::ReadNone;
216 case InaccessibleMemOnly:
217 return Attribute::InaccessibleMemOnly;
218 case SanitizeHWAddress:
219 return Attribute::SanitizeHWAddress;
221 return Attribute::WillReturn;
222 case StackProtectReq:
223 return Attribute::StackProtectReq;
224 case StackProtectStrong:
225 return Attribute::StackProtectStrong;
227 return Attribute::StackProtect;
229 return Attribute::NoUndef;
231 return Attribute::SanitizeMemTag;
232 case ShadowCallStack:
233 return Attribute::ShadowCallStack;
235 return Attribute::AllocSize;
236 #if LLVM_VERSION_GE(15, 0)
237 case AllocatedPointer:
238 return Attribute::AllocatedPointer;
240 return Attribute::AllocAlign;
243 report_fatal_error("bad AttributeKind");
246 template<typename T> static inline void AddAttributes(T *t, unsigned Index,
247 LLVMAttributeRef *Attrs, size_t AttrsLen) {
248 AttributeList PAL = t->getAttributes();
249 AttributeList PALNew;
250 #if LLVM_VERSION_LT(14, 0)
252 for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
253 B.addAttribute(unwrap(Attr));
254 PALNew = PAL.addAttributes(t->getContext(), Index, B);
256 AttrBuilder B(t->getContext());
257 for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
258 B.addAttribute(unwrap(Attr));
259 PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B);
261 t->setAttributes(PALNew);
264 extern "C" void LLVMRustAddFunctionAttributes(LLVMValueRef Fn, unsigned Index,
265 LLVMAttributeRef *Attrs, size_t AttrsLen) {
266 Function *F = unwrap<Function>(Fn);
267 AddAttributes(F, Index, Attrs, AttrsLen);
270 extern "C" void LLVMRustAddCallSiteAttributes(LLVMValueRef Instr, unsigned Index,
271 LLVMAttributeRef *Attrs, size_t AttrsLen) {
272 CallBase *Call = unwrap<CallBase>(Instr);
273 AddAttributes(Call, Index, Attrs, AttrsLen);
276 extern "C" LLVMAttributeRef LLVMRustCreateAttrNoValue(LLVMContextRef C,
277 LLVMRustAttribute RustAttr) {
278 return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr)));
281 extern "C" LLVMAttributeRef LLVMRustCreateAlignmentAttr(LLVMContextRef C,
283 return wrap(Attribute::getWithAlignment(*unwrap(C), llvm::Align(Bytes)));
286 extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableAttr(LLVMContextRef C,
288 return wrap(Attribute::getWithDereferenceableBytes(*unwrap(C), Bytes));
291 extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableOrNullAttr(LLVMContextRef C,
293 return wrap(Attribute::getWithDereferenceableOrNullBytes(*unwrap(C), Bytes));
296 extern "C" LLVMAttributeRef LLVMRustCreateByValAttr(LLVMContextRef C, LLVMTypeRef Ty) {
297 return wrap(Attribute::getWithByValType(*unwrap(C), unwrap(Ty)));
300 extern "C" LLVMAttributeRef LLVMRustCreateStructRetAttr(LLVMContextRef C, LLVMTypeRef Ty) {
301 return wrap(Attribute::getWithStructRetType(*unwrap(C), unwrap(Ty)));
304 extern "C" LLVMAttributeRef LLVMRustCreateElementTypeAttr(LLVMContextRef C, LLVMTypeRef Ty) {
305 #if LLVM_VERSION_GE(15, 0)
306 return wrap(Attribute::get(*unwrap(C), Attribute::ElementType, unwrap(Ty)));
308 report_fatal_error("Should not be needed on LLVM < 15");
312 extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Async) {
313 #if LLVM_VERSION_LT(15, 0)
314 return wrap(Attribute::get(*unwrap(C), Attribute::UWTable));
316 return wrap(Attribute::getWithUWTableKind(
317 *unwrap(C), Async ? UWTableKind::Async : UWTableKind::Sync));
321 extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) {
322 return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, None));
325 #if LLVM_VERSION_GE(15, 0)
327 // These values **must** match ffi::AllocKindFlags.
328 // It _happens_ to match the LLVM values of llvm::AllocFnKind,
329 // but that's happenstance and we do explicit conversions before
330 // passing them to LLVM.
331 enum class LLVMRustAllocKindFlags : uint64_t {
336 Uninitialized = 1 << 3,
341 static LLVMRustAllocKindFlags operator&(LLVMRustAllocKindFlags A, LLVMRustAllocKindFlags B) {
342 return static_cast<LLVMRustAllocKindFlags>(static_cast<uint64_t>(A) &
343 static_cast<uint64_t>(B));
346 static bool isSet(LLVMRustAllocKindFlags F) { return F != LLVMRustAllocKindFlags::Unknown; }
348 static llvm::AllocFnKind allocKindFromRust(LLVMRustAllocKindFlags F) {
349 llvm::AllocFnKind AFK = llvm::AllocFnKind::Unknown;
350 if (isSet(F & LLVMRustAllocKindFlags::Alloc)) {
351 AFK |= llvm::AllocFnKind::Alloc;
353 if (isSet(F & LLVMRustAllocKindFlags::Realloc)) {
354 AFK |= llvm::AllocFnKind::Realloc;
356 if (isSet(F & LLVMRustAllocKindFlags::Free)) {
357 AFK |= llvm::AllocFnKind::Free;
359 if (isSet(F & LLVMRustAllocKindFlags::Uninitialized)) {
360 AFK |= llvm::AllocFnKind::Uninitialized;
362 if (isSet(F & LLVMRustAllocKindFlags::Zeroed)) {
363 AFK |= llvm::AllocFnKind::Zeroed;
365 if (isSet(F & LLVMRustAllocKindFlags::Aligned)) {
366 AFK |= llvm::AllocFnKind::Aligned;
372 extern "C" LLVMAttributeRef LLVMRustCreateAllocKindAttr(LLVMContextRef C, uint64_t AllocKindArg) {
373 #if LLVM_VERSION_GE(15, 0)
374 return wrap(Attribute::get(*unwrap(C), Attribute::AllocKind,
375 static_cast<uint64_t>(allocKindFromRust(static_cast<LLVMRustAllocKindFlags>(AllocKindArg)))));
378 "allockind attributes are new in LLVM 15 and should not be used on older LLVMs");
382 // Enable a fast-math flag
384 // https://llvm.org/docs/LangRef.html#fast-math-flags
385 extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
386 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
391 extern "C" LLVMValueRef
392 LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
393 const char *Name, LLVMAtomicOrdering Order) {
394 Value *Ptr = unwrap(Source);
395 LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
396 LI->setAtomic(fromRust(Order));
400 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
403 LLVMAtomicOrdering Order) {
404 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
405 SI->setAtomic(fromRust(Order));
409 // FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
410 // once we raise our minimum support to LLVM 10.
411 extern "C" LLVMValueRef
412 LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
413 LLVMValueRef Old, LLVMValueRef Source,
414 LLVMAtomicOrdering Order,
415 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
416 #if LLVM_VERSION_GE(13,0)
417 // Rust probably knows the alignment of the target value and should be able to
418 // specify something more precise than MaybeAlign here. See also
419 // https://reviews.llvm.org/D97224 which may be a useful reference.
420 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
421 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
422 fromRust(FailureOrder));
424 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
425 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
426 fromRust(FailureOrder));
432 enum class LLVMRustSynchronizationScope {
437 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
439 case LLVMRustSynchronizationScope::SingleThread:
440 return SyncScope::SingleThread;
441 case LLVMRustSynchronizationScope::CrossThread:
442 return SyncScope::System;
444 report_fatal_error("bad SynchronizationScope.");
448 extern "C" LLVMValueRef
449 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
450 LLVMRustSynchronizationScope Scope) {
451 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
454 enum class LLVMRustAsmDialect {
459 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
461 case LLVMRustAsmDialect::Att:
462 return InlineAsm::AD_ATT;
463 case LLVMRustAsmDialect::Intel:
464 return InlineAsm::AD_Intel;
466 report_fatal_error("bad AsmDialect.");
470 extern "C" LLVMValueRef
471 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
472 char *Constraints, size_t ConstraintsLen,
473 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
474 LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
475 #if LLVM_VERSION_GE(13, 0)
476 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
477 StringRef(AsmString, AsmStringLen),
478 StringRef(Constraints, ConstraintsLen),
479 HasSideEffects, IsAlignStack,
480 fromRust(Dialect), CanThrow));
482 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
483 StringRef(AsmString, AsmStringLen),
484 StringRef(Constraints, ConstraintsLen),
485 HasSideEffects, IsAlignStack,
490 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
491 size_t ConstraintsLen) {
492 #if LLVM_VERSION_LT(15, 0)
493 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
494 StringRef(Constraints, ConstraintsLen));
496 // llvm::Error converts to true if it is an error.
497 return !llvm::errorToBool(InlineAsm::verify(
498 unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen)));
502 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
504 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
507 typedef DIBuilder *LLVMRustDIBuilderRef;
509 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
510 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
513 #define DIDescriptor DIScope
514 #define DIArray DINodeArray
515 #define unwrapDI unwrapDIPtr
517 // These values **must** match debuginfo::DIFlags! They also *happen*
518 // to match LLVM, but that isn't required as we do giant sets of
519 // matching below. The value shouldn't be directly passed to LLVM.
520 enum class LLVMRustDIFlags : uint32_t {
525 FlagFwdDecl = (1 << 2),
526 FlagAppleBlock = (1 << 3),
527 FlagBlockByrefStruct = (1 << 4),
528 FlagVirtual = (1 << 5),
529 FlagArtificial = (1 << 6),
530 FlagExplicit = (1 << 7),
531 FlagPrototyped = (1 << 8),
532 FlagObjcClassComplete = (1 << 9),
533 FlagObjectPointer = (1 << 10),
534 FlagVector = (1 << 11),
535 FlagStaticMember = (1 << 12),
536 FlagLValueReference = (1 << 13),
537 FlagRValueReference = (1 << 14),
538 FlagExternalTypeRef = (1 << 15),
539 FlagIntroducedVirtual = (1 << 18),
540 FlagBitField = (1 << 19),
541 FlagNoReturn = (1 << 20),
542 // Do not add values that are not supported by the minimum LLVM
543 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
546 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
547 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
548 static_cast<uint32_t>(B));
551 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
552 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
553 static_cast<uint32_t>(B));
556 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
560 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
562 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
563 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
566 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
567 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
569 switch (visibility(Flags)) {
570 case LLVMRustDIFlags::FlagPrivate:
571 Result |= DINode::DIFlags::FlagPrivate;
573 case LLVMRustDIFlags::FlagProtected:
574 Result |= DINode::DIFlags::FlagProtected;
576 case LLVMRustDIFlags::FlagPublic:
577 Result |= DINode::DIFlags::FlagPublic;
580 // The rest are handled below
584 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
585 Result |= DINode::DIFlags::FlagFwdDecl;
587 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
588 Result |= DINode::DIFlags::FlagAppleBlock;
590 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
591 Result |= DINode::DIFlags::FlagVirtual;
593 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
594 Result |= DINode::DIFlags::FlagArtificial;
596 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
597 Result |= DINode::DIFlags::FlagExplicit;
599 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
600 Result |= DINode::DIFlags::FlagPrototyped;
602 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
603 Result |= DINode::DIFlags::FlagObjcClassComplete;
605 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
606 Result |= DINode::DIFlags::FlagObjectPointer;
608 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
609 Result |= DINode::DIFlags::FlagVector;
611 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
612 Result |= DINode::DIFlags::FlagStaticMember;
614 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
615 Result |= DINode::DIFlags::FlagLValueReference;
617 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
618 Result |= DINode::DIFlags::FlagRValueReference;
620 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
621 Result |= DINode::DIFlags::FlagIntroducedVirtual;
623 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
624 Result |= DINode::DIFlags::FlagBitField;
626 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
627 Result |= DINode::DIFlags::FlagNoReturn;
633 // These values **must** match debuginfo::DISPFlags! They also *happen*
634 // to match LLVM, but that isn't required as we do giant sets of
635 // matching below. The value shouldn't be directly passed to LLVM.
636 enum class LLVMRustDISPFlags : uint32_t {
639 SPFlagPureVirtual = 2,
640 SPFlagLocalToUnit = (1 << 2),
641 SPFlagDefinition = (1 << 3),
642 SPFlagOptimized = (1 << 4),
643 SPFlagMainSubprogram = (1 << 5),
644 // Do not add values that are not supported by the minimum LLVM
645 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
646 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
649 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
650 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
651 static_cast<uint32_t>(B));
654 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
655 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
656 static_cast<uint32_t>(B));
659 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
663 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
665 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
666 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
669 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
670 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
672 switch (virtuality(SPFlags)) {
673 case LLVMRustDISPFlags::SPFlagVirtual:
674 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
676 case LLVMRustDISPFlags::SPFlagPureVirtual:
677 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
680 // The rest are handled below
684 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
685 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
687 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
688 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
690 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
691 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
693 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
694 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
700 enum class LLVMRustDebugEmissionKind {
706 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
708 case LLVMRustDebugEmissionKind::NoDebug:
709 return DICompileUnit::DebugEmissionKind::NoDebug;
710 case LLVMRustDebugEmissionKind::FullDebug:
711 return DICompileUnit::DebugEmissionKind::FullDebug;
712 case LLVMRustDebugEmissionKind::LineTablesOnly:
713 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
715 report_fatal_error("bad DebugEmissionKind.");
719 enum class LLVMRustChecksumKind {
726 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
728 case LLVMRustChecksumKind::None:
730 case LLVMRustChecksumKind::MD5:
731 return DIFile::ChecksumKind::CSK_MD5;
732 case LLVMRustChecksumKind::SHA1:
733 return DIFile::ChecksumKind::CSK_SHA1;
734 case LLVMRustChecksumKind::SHA256:
735 return DIFile::ChecksumKind::CSK_SHA256;
737 report_fatal_error("bad ChecksumKind.");
741 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
742 return DEBUG_METADATA_VERSION;
745 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
747 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
749 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
751 extern "C" void LLVMRustAddModuleFlag(
753 Module::ModFlagBehavior MergeBehavior,
756 unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
759 extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
761 return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
764 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
765 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
768 extern "C" void LLVMRustGlobalAddMetadata(
769 LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) {
770 unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
773 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
774 return new DIBuilder(*unwrap(M));
777 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
781 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
785 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
786 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
787 const char *Producer, size_t ProducerLen, bool isOptimized,
788 const char *Flags, unsigned RuntimeVer,
789 const char *SplitName, size_t SplitNameLen,
790 LLVMRustDebugEmissionKind Kind,
791 uint64_t DWOId, bool SplitDebugInlining) {
792 auto *File = unwrapDI<DIFile>(FileRef);
794 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
795 isOptimized, Flags, RuntimeVer,
796 StringRef(SplitName, SplitNameLen),
797 fromRust(Kind), DWOId, SplitDebugInlining));
800 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
801 LLVMRustDIBuilderRef Builder,
802 const char *Filename, size_t FilenameLen,
803 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
804 const char *Checksum, size_t ChecksumLen) {
805 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
806 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
808 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
809 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
810 StringRef(Directory, DirectoryLen),
814 extern "C" LLVMMetadataRef
815 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
816 LLVMMetadataRef ParameterTypes) {
817 return wrap(Builder->createSubroutineType(
818 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
821 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
822 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
823 const char *Name, size_t NameLen,
824 const char *LinkageName, size_t LinkageNameLen,
825 LLVMMetadataRef File, unsigned LineNo,
826 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
827 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
828 LLVMMetadataRef Decl) {
829 DITemplateParameterArray TParams =
830 DITemplateParameterArray(unwrap<MDTuple>(TParam));
831 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
832 DINode::DIFlags llvmFlags = fromRust(Flags);
833 DISubprogram *Sub = Builder->createFunction(
834 unwrapDI<DIScope>(Scope),
835 StringRef(Name, NameLen),
836 StringRef(LinkageName, LinkageNameLen),
837 unwrapDI<DIFile>(File), LineNo,
838 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
839 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
841 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
845 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
846 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
847 uint64_t SizeInBits, unsigned Encoding) {
848 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
851 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
852 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
853 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
854 return wrap(Builder->createTypedef(
855 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
856 LineNo, unwrapDIPtr<DIScope>(Scope)));
859 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
860 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
861 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
862 const char *Name, size_t NameLen) {
863 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
864 SizeInBits, AlignInBits,
866 StringRef(Name, NameLen)));
869 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
870 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
871 const char *Name, size_t NameLen,
872 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
873 uint32_t AlignInBits, LLVMRustDIFlags Flags,
874 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
875 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
876 const char *UniqueId, size_t UniqueIdLen) {
877 return wrap(Builder->createStructType(
878 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
879 unwrapDI<DIFile>(File), LineNumber,
880 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
881 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
882 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
885 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
886 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
887 const char *Name, size_t NameLen,
888 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
889 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
890 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
891 return wrap(Builder->createVariantPart(
892 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
893 unwrapDI<DIFile>(File), LineNumber,
894 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
895 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
898 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
899 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
900 const char *Name, size_t NameLen,
901 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
902 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
903 LLVMMetadataRef Ty) {
904 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
905 StringRef(Name, NameLen),
906 unwrapDI<DIFile>(File), LineNo,
907 SizeInBits, AlignInBits, OffsetInBits,
908 fromRust(Flags), unwrapDI<DIType>(Ty)));
911 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
912 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
913 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
914 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
915 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
916 llvm::ConstantInt* D = nullptr;
918 D = unwrap<llvm::ConstantInt>(Discriminant);
920 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
921 StringRef(Name, NameLen),
922 unwrapDI<DIFile>(File), LineNo,
923 SizeInBits, AlignInBits, OffsetInBits, D,
924 fromRust(Flags), unwrapDI<DIType>(Ty)));
927 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
928 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
929 LLVMMetadataRef File, unsigned Line, unsigned Col) {
930 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
931 unwrapDI<DIFile>(File), Line, Col));
934 extern "C" LLVMMetadataRef
935 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
936 LLVMMetadataRef Scope,
937 LLVMMetadataRef File) {
938 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
939 unwrapDI<DIFile>(File)));
942 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
943 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
944 const char *Name, size_t NameLen,
945 const char *LinkageName, size_t LinkageNameLen,
946 LLVMMetadataRef File, unsigned LineNo,
947 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
948 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
949 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
951 llvm::DIExpression *InitExpr = nullptr;
952 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
953 InitExpr = Builder->createConstantValueExpression(
954 IntVal->getValue().getSExtValue());
955 } else if (llvm::ConstantFP *FPVal =
956 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
957 InitExpr = Builder->createConstantValueExpression(
958 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
961 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
962 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
963 StringRef(LinkageName, LinkageNameLen),
964 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
965 /* isDefined */ true,
966 InitExpr, unwrapDIPtr<MDNode>(Decl),
967 /* templateParams */ nullptr,
970 InitVal->setMetadata("dbg", VarExpr);
972 return wrap(VarExpr);
975 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
976 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
977 const char *Name, size_t NameLen,
978 LLVMMetadataRef File, unsigned LineNo,
979 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
980 unsigned ArgNo, uint32_t AlignInBits) {
981 if (Tag == 0x100) { // DW_TAG_auto_variable
982 return wrap(Builder->createAutoVariable(
983 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
984 unwrapDI<DIFile>(File), LineNo,
985 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
987 return wrap(Builder->createParameterVariable(
988 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
989 unwrapDI<DIFile>(File), LineNo,
990 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
994 extern "C" LLVMMetadataRef
995 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
996 uint32_t AlignInBits, LLVMMetadataRef Ty,
997 LLVMMetadataRef Subscripts) {
999 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
1000 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
1003 extern "C" LLVMMetadataRef
1004 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
1006 return wrap(Builder->getOrCreateSubrange(Lo, Count));
1009 extern "C" LLVMMetadataRef
1010 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
1011 LLVMMetadataRef *Ptr, unsigned Count) {
1012 Metadata **DataValue = unwrap(Ptr);
1014 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
1017 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
1018 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
1019 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
1020 LLVMBasicBlockRef InsertAtEnd) {
1021 return wrap(Builder->insertDeclare(
1022 unwrap(V), unwrap<DILocalVariable>(VarInfo),
1023 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
1024 DebugLoc(cast<MDNode>(unwrap(DL))),
1025 unwrap(InsertAtEnd)));
1028 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
1029 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
1030 int64_t Value, bool IsUnsigned) {
1031 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
1034 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
1035 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1036 const char *Name, size_t NameLen,
1037 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1038 uint32_t AlignInBits, LLVMMetadataRef Elements,
1039 LLVMMetadataRef ClassTy, bool IsScoped) {
1040 return wrap(Builder->createEnumerationType(
1041 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
1042 unwrapDI<DIFile>(File), LineNumber,
1043 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
1044 unwrapDI<DIType>(ClassTy), "", IsScoped));
1047 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
1048 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1049 const char *Name, size_t NameLen,
1050 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1051 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
1052 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
1053 return wrap(Builder->createUnionType(
1054 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1055 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1056 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1057 StringRef(UniqueId, UniqueIdLen)));
1060 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1061 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1062 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1063 bool IsDefault = false; // FIXME: should we ever set this true?
1064 return wrap(Builder->createTemplateTypeParameter(
1065 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1068 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1069 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1070 const char *Name, size_t NameLen, bool ExportSymbols) {
1071 return wrap(Builder->createNameSpace(
1072 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1077 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1078 LLVMMetadataRef CompositeTy,
1079 LLVMMetadataRef Elements,
1080 LLVMMetadataRef Params) {
1081 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1082 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1083 DINodeArray(unwrap<MDTuple>(Params)));
1086 extern "C" LLVMMetadataRef
1087 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1088 LLVMMetadataRef ScopeRef,
1089 LLVMMetadataRef InlinedAt) {
1090 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1091 DILocation *Loc = DILocation::get(
1092 Scope->getContext(), Line, Column, Scope,
1093 unwrapDIPtr<MDNode>(InlinedAt));
1097 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1098 return dwarf::DW_OP_deref;
1101 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1102 return dwarf::DW_OP_plus_uconst;
1105 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1106 RawRustStringOstream OS(Str);
1107 unwrap<llvm::Type>(Ty)->print(OS);
1110 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1111 RustStringRef Str) {
1112 RawRustStringOstream OS(Str);
1117 unwrap<llvm::Value>(V)->getType()->print(OS);
1119 unwrap<llvm::Value>(V)->print(OS);
1124 // LLVMArrayType function does not support 64-bit ElementCount
1125 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1126 uint64_t ElementCount) {
1127 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1130 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1132 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1133 RawRustStringOstream OS(Str);
1134 unwrap(T)->print(OS);
1137 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1138 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1139 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1140 RustStringRef FilenameOut, RustStringRef MessageOut) {
1141 // Undefined to call this not on an optimization diagnostic!
1142 llvm::DiagnosticInfoOptimizationBase *Opt =
1143 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1145 RawRustStringOstream PassNameOS(PassNameOut);
1146 PassNameOS << Opt->getPassName();
1147 *FunctionOut = wrap(&Opt->getFunction());
1149 RawRustStringOstream FilenameOS(FilenameOut);
1150 DiagnosticLocation loc = Opt->getLocation();
1151 if (loc.isValid()) {
1152 *Line = loc.getLine();
1153 *Column = loc.getColumn();
1154 FilenameOS << loc.getAbsolutePath();
1157 RawRustStringOstream MessageOS(MessageOut);
1158 MessageOS << Opt->getMsg();
1161 enum class LLVMRustDiagnosticLevel {
1169 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1170 LLVMRustDiagnosticLevel *LevelOut,
1171 unsigned *CookieOut,
1172 LLVMTwineRef *MessageOut) {
1173 // Undefined to call this not on an inline assembly diagnostic!
1174 llvm::DiagnosticInfoInlineAsm *IA =
1175 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1177 *CookieOut = IA->getLocCookie();
1178 *MessageOut = wrap(&IA->getMsgStr());
1180 switch (IA->getSeverity()) {
1182 *LevelOut = LLVMRustDiagnosticLevel::Error;
1185 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1188 *LevelOut = LLVMRustDiagnosticLevel::Note;
1191 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1194 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1198 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1199 RustStringRef Str) {
1200 RawRustStringOstream OS(Str);
1201 DiagnosticPrinterRawOStream DP(OS);
1202 unwrap(DI)->print(DP);
1205 enum class LLVMRustDiagnosticKind {
1209 DebugMetadataVersion,
1212 OptimizationRemarkMissed,
1213 OptimizationRemarkAnalysis,
1214 OptimizationRemarkAnalysisFPCommute,
1215 OptimizationRemarkAnalysisAliasing,
1216 OptimizationRemarkOther,
1217 OptimizationFailure,
1224 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1227 return LLVMRustDiagnosticKind::InlineAsm;
1229 return LLVMRustDiagnosticKind::StackSize;
1230 case DK_DebugMetadataVersion:
1231 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1232 case DK_SampleProfile:
1233 return LLVMRustDiagnosticKind::SampleProfile;
1234 case DK_OptimizationRemark:
1235 case DK_MachineOptimizationRemark:
1236 return LLVMRustDiagnosticKind::OptimizationRemark;
1237 case DK_OptimizationRemarkMissed:
1238 case DK_MachineOptimizationRemarkMissed:
1239 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1240 case DK_OptimizationRemarkAnalysis:
1241 case DK_MachineOptimizationRemarkAnalysis:
1242 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1243 case DK_OptimizationRemarkAnalysisFPCommute:
1244 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1245 case DK_OptimizationRemarkAnalysisAliasing:
1246 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1248 return LLVMRustDiagnosticKind::PGOProfile;
1250 return LLVMRustDiagnosticKind::Linker;
1251 case DK_Unsupported:
1252 return LLVMRustDiagnosticKind::Unsupported;
1253 #if LLVM_VERSION_GE(13, 0)
1255 return LLVMRustDiagnosticKind::SrcMgr;
1258 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1259 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1260 : LLVMRustDiagnosticKind::Other;
1264 extern "C" LLVMRustDiagnosticKind
1265 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1266 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1269 // This is kept distinct from LLVMGetTypeKind, because when
1270 // a new type kind is added, the Rust-side enum must be
1271 // updated or UB will result.
1272 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1273 switch (unwrap(Ty)->getTypeID()) {
1274 case Type::VoidTyID:
1275 return LLVMVoidTypeKind;
1276 case Type::HalfTyID:
1277 return LLVMHalfTypeKind;
1278 case Type::FloatTyID:
1279 return LLVMFloatTypeKind;
1280 case Type::DoubleTyID:
1281 return LLVMDoubleTypeKind;
1282 case Type::X86_FP80TyID:
1283 return LLVMX86_FP80TypeKind;
1284 case Type::FP128TyID:
1285 return LLVMFP128TypeKind;
1286 case Type::PPC_FP128TyID:
1287 return LLVMPPC_FP128TypeKind;
1288 case Type::LabelTyID:
1289 return LLVMLabelTypeKind;
1290 case Type::MetadataTyID:
1291 return LLVMMetadataTypeKind;
1292 case Type::IntegerTyID:
1293 return LLVMIntegerTypeKind;
1294 case Type::FunctionTyID:
1295 return LLVMFunctionTypeKind;
1296 case Type::StructTyID:
1297 return LLVMStructTypeKind;
1298 case Type::ArrayTyID:
1299 return LLVMArrayTypeKind;
1300 case Type::PointerTyID:
1301 return LLVMPointerTypeKind;
1302 case Type::FixedVectorTyID:
1303 return LLVMVectorTypeKind;
1304 case Type::X86_MMXTyID:
1305 return LLVMX86_MMXTypeKind;
1306 case Type::TokenTyID:
1307 return LLVMTokenTypeKind;
1308 case Type::ScalableVectorTyID:
1309 return LLVMScalableVectorTypeKind;
1310 case Type::BFloatTyID:
1311 return LLVMBFloatTypeKind;
1312 case Type::X86_AMXTyID:
1313 return LLVMX86_AMXTypeKind;
1314 #if LLVM_VERSION_GE(15, 0)
1315 case Type::DXILPointerTyID:
1316 report_fatal_error("Rust does not support DirectX typed pointers.");
1320 report_fatal_error("Unhandled TypeID.");
1323 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1325 #if LLVM_VERSION_LT(13, 0)
1326 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1328 using LLVMInlineAsmDiagHandlerTy = void*;
1331 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1332 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1333 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1334 // with LLVM 13 this function is gone.
1335 #if LLVM_VERSION_LT(13, 0)
1336 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1340 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1341 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1342 #if LLVM_VERSION_GE(13, 0)
1343 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1344 *Cookie = SM->getLocCookie();
1345 return wrap(&SM->getSMDiag());
1347 report_fatal_error("Shouldn't get called on older versions");
1351 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1352 RustStringRef MessageOut,
1353 RustStringRef BufferOut,
1354 LLVMRustDiagnosticLevel* LevelOut,
1356 unsigned* RangesOut,
1357 size_t* NumRanges) {
1358 SMDiagnostic& D = *unwrap(DRef);
1359 RawRustStringOstream MessageOS(MessageOut);
1360 MessageOS << D.getMessage();
1362 switch (D.getKind()) {
1363 case SourceMgr::DK_Error:
1364 *LevelOut = LLVMRustDiagnosticLevel::Error;
1366 case SourceMgr::DK_Warning:
1367 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1369 case SourceMgr::DK_Note:
1370 *LevelOut = LLVMRustDiagnosticLevel::Note;
1372 case SourceMgr::DK_Remark:
1373 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1376 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1379 if (D.getLoc() == SMLoc())
1382 const SourceMgr &LSM = *D.getSourceMgr();
1383 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1384 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1386 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1388 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1389 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1390 for (size_t i = 0; i < *NumRanges; i++) {
1391 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1392 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1398 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1399 LLVMValueRef ParentPad,
1401 LLVMValueRef *LLArgs,
1403 Value **Args = unwrap(LLArgs);
1404 if (ParentPad == nullptr) {
1405 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1406 ParentPad = wrap(Constant::getNullValue(Ty));
1408 return wrap(unwrap(B)->CreateCleanupPad(
1409 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1412 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1413 LLVMValueRef CleanupPad,
1414 LLVMBasicBlockRef UnwindBB) {
1415 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1416 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1419 extern "C" LLVMValueRef
1420 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1421 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1422 Value **Args = unwrap(LLArgs);
1423 return wrap(unwrap(B)->CreateCatchPad(
1424 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1427 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1429 LLVMBasicBlockRef BB) {
1430 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1434 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1435 LLVMValueRef ParentPad,
1436 LLVMBasicBlockRef BB,
1437 unsigned NumHandlers,
1439 if (ParentPad == nullptr) {
1440 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1441 ParentPad = wrap(Constant::getNullValue(Ty));
1443 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1444 NumHandlers, Name));
1447 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1448 LLVMBasicBlockRef Handler) {
1449 Value *CatchSwitch = unwrap(CatchSwitchRef);
1450 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1453 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1454 LLVMValueRef *Inputs,
1455 unsigned NumInputs) {
1456 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1459 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1463 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1464 LLVMValueRef *Args, unsigned NumArgs,
1465 OperandBundleDef *Bundle) {
1466 Value *Callee = unwrap(Fn);
1467 FunctionType *FTy = unwrap<FunctionType>(Ty);
1468 unsigned Len = Bundle ? 1 : 0;
1469 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1470 return wrap(unwrap(B)->CreateCall(
1471 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1474 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1475 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1476 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1479 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1480 LLVMValueRef Dst, unsigned DstAlign,
1481 LLVMValueRef Src, unsigned SrcAlign,
1482 LLVMValueRef Size, bool IsVolatile) {
1483 return wrap(unwrap(B)->CreateMemCpy(
1484 unwrap(Dst), MaybeAlign(DstAlign),
1485 unwrap(Src), MaybeAlign(SrcAlign),
1486 unwrap(Size), IsVolatile));
1489 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1490 LLVMValueRef Dst, unsigned DstAlign,
1491 LLVMValueRef Src, unsigned SrcAlign,
1492 LLVMValueRef Size, bool IsVolatile) {
1493 return wrap(unwrap(B)->CreateMemMove(
1494 unwrap(Dst), MaybeAlign(DstAlign),
1495 unwrap(Src), MaybeAlign(SrcAlign),
1496 unwrap(Size), IsVolatile));
1499 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1500 LLVMValueRef Dst, unsigned DstAlign,
1502 LLVMValueRef Size, bool IsVolatile) {
1503 return wrap(unwrap(B)->CreateMemSet(
1504 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1507 extern "C" LLVMValueRef
1508 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1509 LLVMValueRef *Args, unsigned NumArgs,
1510 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1511 OperandBundleDef *Bundle, const char *Name) {
1512 Value *Callee = unwrap(Fn);
1513 FunctionType *FTy = unwrap<FunctionType>(Ty);
1514 unsigned Len = Bundle ? 1 : 0;
1515 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1516 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1517 makeArrayRef(unwrap(Args), NumArgs),
1521 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1522 LLVMBasicBlockRef BB) {
1523 auto Point = unwrap(BB)->getFirstInsertionPt();
1524 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1527 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1528 const char *Name, size_t NameLen) {
1529 Triple TargetTriple(unwrap(M)->getTargetTriple());
1530 GlobalObject *GV = unwrap<GlobalObject>(V);
1531 if (TargetTriple.supportsCOMDAT()) {
1532 StringRef NameRef(Name, NameLen);
1533 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1537 enum class LLVMRustLinkage {
1538 ExternalLinkage = 0,
1539 AvailableExternallyLinkage = 1,
1540 LinkOnceAnyLinkage = 2,
1541 LinkOnceODRLinkage = 3,
1544 AppendingLinkage = 6,
1545 InternalLinkage = 7,
1547 ExternalWeakLinkage = 9,
1551 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1553 case LLVMExternalLinkage:
1554 return LLVMRustLinkage::ExternalLinkage;
1555 case LLVMAvailableExternallyLinkage:
1556 return LLVMRustLinkage::AvailableExternallyLinkage;
1557 case LLVMLinkOnceAnyLinkage:
1558 return LLVMRustLinkage::LinkOnceAnyLinkage;
1559 case LLVMLinkOnceODRLinkage:
1560 return LLVMRustLinkage::LinkOnceODRLinkage;
1561 case LLVMWeakAnyLinkage:
1562 return LLVMRustLinkage::WeakAnyLinkage;
1563 case LLVMWeakODRLinkage:
1564 return LLVMRustLinkage::WeakODRLinkage;
1565 case LLVMAppendingLinkage:
1566 return LLVMRustLinkage::AppendingLinkage;
1567 case LLVMInternalLinkage:
1568 return LLVMRustLinkage::InternalLinkage;
1569 case LLVMPrivateLinkage:
1570 return LLVMRustLinkage::PrivateLinkage;
1571 case LLVMExternalWeakLinkage:
1572 return LLVMRustLinkage::ExternalWeakLinkage;
1573 case LLVMCommonLinkage:
1574 return LLVMRustLinkage::CommonLinkage;
1576 report_fatal_error("Invalid LLVMRustLinkage value!");
1580 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1582 case LLVMRustLinkage::ExternalLinkage:
1583 return LLVMExternalLinkage;
1584 case LLVMRustLinkage::AvailableExternallyLinkage:
1585 return LLVMAvailableExternallyLinkage;
1586 case LLVMRustLinkage::LinkOnceAnyLinkage:
1587 return LLVMLinkOnceAnyLinkage;
1588 case LLVMRustLinkage::LinkOnceODRLinkage:
1589 return LLVMLinkOnceODRLinkage;
1590 case LLVMRustLinkage::WeakAnyLinkage:
1591 return LLVMWeakAnyLinkage;
1592 case LLVMRustLinkage::WeakODRLinkage:
1593 return LLVMWeakODRLinkage;
1594 case LLVMRustLinkage::AppendingLinkage:
1595 return LLVMAppendingLinkage;
1596 case LLVMRustLinkage::InternalLinkage:
1597 return LLVMInternalLinkage;
1598 case LLVMRustLinkage::PrivateLinkage:
1599 return LLVMPrivateLinkage;
1600 case LLVMRustLinkage::ExternalWeakLinkage:
1601 return LLVMExternalWeakLinkage;
1602 case LLVMRustLinkage::CommonLinkage:
1603 return LLVMCommonLinkage;
1605 report_fatal_error("Invalid LLVMRustLinkage value!");
1608 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1609 return toRust(LLVMGetLinkage(V));
1612 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1613 LLVMRustLinkage RustLinkage) {
1614 LLVMSetLinkage(V, fromRust(RustLinkage));
1617 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1618 LLVMValueRef ConstantVal,
1619 LLVMValueRef *ConstantIndices,
1620 unsigned NumIndices) {
1621 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1623 Constant *Val = unwrap<Constant>(ConstantVal);
1624 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1627 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1628 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1629 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1631 auto C = unwrap<llvm::ConstantInt>(CV);
1632 if (C->getBitWidth() > 128) { return false; }
1634 #if LLVM_VERSION_GE(15, 0)
1636 AP = C->getValue().sext(128);
1638 AP = C->getValue().zext(128);
1642 AP = C->getValue().sextOrSelf(128);
1644 AP = C->getValue().zextOrSelf(128);
1647 *low = AP.getLoBits(64).getZExtValue();
1648 *high = AP.getHiBits(64).getZExtValue();
1652 enum class LLVMRustVisibility {
1658 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1660 case LLVMDefaultVisibility:
1661 return LLVMRustVisibility::Default;
1662 case LLVMHiddenVisibility:
1663 return LLVMRustVisibility::Hidden;
1664 case LLVMProtectedVisibility:
1665 return LLVMRustVisibility::Protected;
1667 report_fatal_error("Invalid LLVMRustVisibility value!");
1670 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1672 case LLVMRustVisibility::Default:
1673 return LLVMDefaultVisibility;
1674 case LLVMRustVisibility::Hidden:
1675 return LLVMHiddenVisibility;
1676 case LLVMRustVisibility::Protected:
1677 return LLVMProtectedVisibility;
1679 report_fatal_error("Invalid LLVMRustVisibility value!");
1682 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1683 return toRust(LLVMGetVisibility(V));
1686 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1687 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1688 LLVMTypeRef DestTy, bool isSigned) {
1689 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1692 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1693 LLVMRustVisibility RustVisibility) {
1694 LLVMSetVisibility(V, fromRust(RustVisibility));
1697 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1698 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1701 struct LLVMRustModuleBuffer {
1705 extern "C" LLVMRustModuleBuffer*
1706 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1707 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1709 raw_string_ostream OS(Ret->data);
1711 legacy::PassManager PM;
1712 PM.add(createBitcodeWriterPass(OS));
1716 return Ret.release();
1720 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1724 extern "C" const void*
1725 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1726 return Buffer->data.data();
1730 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1731 return Buffer->data.length();
1735 LLVMRustModuleCost(LLVMModuleRef M) {
1736 auto f = unwrap(M)->functions();
1737 return std::distance(std::begin(f), std::end(f));
1740 // Vector reductions:
1741 extern "C" LLVMValueRef
1742 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1743 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1745 extern "C" LLVMValueRef
1746 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1747 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1749 extern "C" LLVMValueRef
1750 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1751 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1753 extern "C" LLVMValueRef
1754 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1755 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1757 extern "C" LLVMValueRef
1758 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1759 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1761 extern "C" LLVMValueRef
1762 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1763 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1765 extern "C" LLVMValueRef
1766 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1767 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1769 extern "C" LLVMValueRef
1770 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1771 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1773 extern "C" LLVMValueRef
1774 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1775 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1777 extern "C" LLVMValueRef
1778 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1779 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1780 I->setHasNoNaNs(NoNaN);
1783 extern "C" LLVMValueRef
1784 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1785 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1786 I->setHasNoNaNs(NoNaN);
1790 extern "C" LLVMValueRef
1791 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1792 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1794 extern "C" LLVMValueRef
1795 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1796 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1799 // This struct contains all necessary info about a symbol exported from a DLL.
1800 struct LLVMRustCOFFShortExport {
1802 bool ordinal_present;
1803 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1807 // Machine must be a COFF machine type, as defined in PE specs.
1808 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1809 const char* ImportName,
1811 const LLVMRustCOFFShortExport* Exports,
1816 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1817 ConvertedExports.reserve(NumExports);
1819 for (size_t i = 0; i < NumExports; ++i) {
1820 bool ordinal_present = Exports[i].ordinal_present;
1821 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1822 ConvertedExports.push_back(llvm::object::COFFShortExport{
1823 Exports[i].name, // Name
1824 std::string{}, // ExtName
1825 std::string{}, // SymbolName
1826 std::string{}, // AliasTarget
1828 ordinal_present, // Noname
1835 auto Error = llvm::object::writeImportLibrary(
1839 static_cast<llvm::COFF::MachineTypes>(Machine),
1842 std::string errorString;
1843 llvm::raw_string_ostream stream(errorString);
1846 LLVMRustSetLastError(errorString.c_str());
1847 return LLVMRustResult::Failure;
1849 return LLVMRustResult::Success;
1853 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1854 extern "C" DiagnosticHandler *
1855 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1856 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1857 return DH.release();
1860 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1861 // handling. Ownership of the handler is moved to the LLVMContext.
1862 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1863 DiagnosticHandler *DH) {
1864 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1867 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1869 // Configures a diagnostic handler that invokes provided callback when a
1870 // backend needs to emit a diagnostic.
1872 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1873 // the RemarkPasses array specifies individual passes for which remarks will be
1875 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1876 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1877 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1878 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1880 class RustDiagnosticHandler final : public DiagnosticHandler {
1882 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1883 void *DiagnosticHandlerContext,
1884 bool RemarkAllPasses,
1885 std::vector<std::string> RemarkPasses)
1886 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1887 DiagnosticHandlerContext(DiagnosticHandlerContext),
1888 RemarkAllPasses(RemarkAllPasses),
1889 RemarkPasses(RemarkPasses) {}
1891 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1892 if (DiagnosticHandlerCallback) {
1893 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1899 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1900 return isRemarkEnabled(PassName);
1903 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1904 return isRemarkEnabled(PassName);
1907 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1908 return isRemarkEnabled(PassName);
1911 bool isAnyRemarkEnabled() const override {
1912 return RemarkAllPasses || !RemarkPasses.empty();
1916 bool isRemarkEnabled(StringRef PassName) const {
1917 if (RemarkAllPasses)
1920 for (auto &Pass : RemarkPasses)
1921 if (Pass == PassName)
1927 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1928 void *DiagnosticHandlerContext = nullptr;
1930 bool RemarkAllPasses = false;
1931 std::vector<std::string> RemarkPasses;
1934 std::vector<std::string> Passes;
1935 for (size_t I = 0; I != RemarkPassesLen; ++I)
1936 Passes.push_back(RemarkPasses[I]);
1938 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1939 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
1942 extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
1943 RawRustStringOstream OS(Str);
1944 GlobalValue *GV = unwrap<GlobalValue>(V);
1945 Mangler().getNameWithPrefix(OS, GV, true);
1948 // LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just
1949 // use its implementation.
1950 #if LLVM_VERSION_LT(15, 0)
1951 extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
1952 return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));
1956 extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
1957 #if LLVM_VERSION_GE(15, 0)
1958 auto *CB = unwrap<CallBase>(CallSite);
1959 switch (CB->getIntrinsicID()) {
1960 case Intrinsic::arm_ldrex:
1962 case Intrinsic::arm_strex: