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 // Rust probably knows the alignment of the target value and should be able to
417 // specify something more precise than MaybeAlign here. See also
418 // https://reviews.llvm.org/D97224 which may be a useful reference.
419 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
420 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
421 fromRust(FailureOrder));
426 enum class LLVMRustSynchronizationScope {
431 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
433 case LLVMRustSynchronizationScope::SingleThread:
434 return SyncScope::SingleThread;
435 case LLVMRustSynchronizationScope::CrossThread:
436 return SyncScope::System;
438 report_fatal_error("bad SynchronizationScope.");
442 extern "C" LLVMValueRef
443 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
444 LLVMRustSynchronizationScope Scope) {
445 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
448 enum class LLVMRustAsmDialect {
453 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
455 case LLVMRustAsmDialect::Att:
456 return InlineAsm::AD_ATT;
457 case LLVMRustAsmDialect::Intel:
458 return InlineAsm::AD_Intel;
460 report_fatal_error("bad AsmDialect.");
464 extern "C" LLVMValueRef
465 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
466 char *Constraints, size_t ConstraintsLen,
467 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
468 LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
469 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
470 StringRef(AsmString, AsmStringLen),
471 StringRef(Constraints, ConstraintsLen),
472 HasSideEffects, IsAlignStack,
473 fromRust(Dialect), CanThrow));
476 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
477 size_t ConstraintsLen) {
478 #if LLVM_VERSION_LT(15, 0)
479 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
480 StringRef(Constraints, ConstraintsLen));
482 // llvm::Error converts to true if it is an error.
483 return !llvm::errorToBool(InlineAsm::verify(
484 unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen)));
488 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
490 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
493 typedef DIBuilder *LLVMRustDIBuilderRef;
495 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
496 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
499 #define DIDescriptor DIScope
500 #define DIArray DINodeArray
501 #define unwrapDI unwrapDIPtr
503 // These values **must** match debuginfo::DIFlags! They also *happen*
504 // to match LLVM, but that isn't required as we do giant sets of
505 // matching below. The value shouldn't be directly passed to LLVM.
506 enum class LLVMRustDIFlags : uint32_t {
511 FlagFwdDecl = (1 << 2),
512 FlagAppleBlock = (1 << 3),
513 FlagBlockByrefStruct = (1 << 4),
514 FlagVirtual = (1 << 5),
515 FlagArtificial = (1 << 6),
516 FlagExplicit = (1 << 7),
517 FlagPrototyped = (1 << 8),
518 FlagObjcClassComplete = (1 << 9),
519 FlagObjectPointer = (1 << 10),
520 FlagVector = (1 << 11),
521 FlagStaticMember = (1 << 12),
522 FlagLValueReference = (1 << 13),
523 FlagRValueReference = (1 << 14),
524 FlagExternalTypeRef = (1 << 15),
525 FlagIntroducedVirtual = (1 << 18),
526 FlagBitField = (1 << 19),
527 FlagNoReturn = (1 << 20),
528 // Do not add values that are not supported by the minimum LLVM
529 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
532 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
533 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
534 static_cast<uint32_t>(B));
537 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
538 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
539 static_cast<uint32_t>(B));
542 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
546 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
548 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
549 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
552 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
553 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
555 switch (visibility(Flags)) {
556 case LLVMRustDIFlags::FlagPrivate:
557 Result |= DINode::DIFlags::FlagPrivate;
559 case LLVMRustDIFlags::FlagProtected:
560 Result |= DINode::DIFlags::FlagProtected;
562 case LLVMRustDIFlags::FlagPublic:
563 Result |= DINode::DIFlags::FlagPublic;
566 // The rest are handled below
570 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
571 Result |= DINode::DIFlags::FlagFwdDecl;
573 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
574 Result |= DINode::DIFlags::FlagAppleBlock;
576 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
577 Result |= DINode::DIFlags::FlagVirtual;
579 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
580 Result |= DINode::DIFlags::FlagArtificial;
582 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
583 Result |= DINode::DIFlags::FlagExplicit;
585 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
586 Result |= DINode::DIFlags::FlagPrototyped;
588 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
589 Result |= DINode::DIFlags::FlagObjcClassComplete;
591 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
592 Result |= DINode::DIFlags::FlagObjectPointer;
594 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
595 Result |= DINode::DIFlags::FlagVector;
597 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
598 Result |= DINode::DIFlags::FlagStaticMember;
600 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
601 Result |= DINode::DIFlags::FlagLValueReference;
603 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
604 Result |= DINode::DIFlags::FlagRValueReference;
606 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
607 Result |= DINode::DIFlags::FlagIntroducedVirtual;
609 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
610 Result |= DINode::DIFlags::FlagBitField;
612 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
613 Result |= DINode::DIFlags::FlagNoReturn;
619 // These values **must** match debuginfo::DISPFlags! They also *happen*
620 // to match LLVM, but that isn't required as we do giant sets of
621 // matching below. The value shouldn't be directly passed to LLVM.
622 enum class LLVMRustDISPFlags : uint32_t {
625 SPFlagPureVirtual = 2,
626 SPFlagLocalToUnit = (1 << 2),
627 SPFlagDefinition = (1 << 3),
628 SPFlagOptimized = (1 << 4),
629 SPFlagMainSubprogram = (1 << 5),
630 // Do not add values that are not supported by the minimum LLVM
631 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
632 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
635 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
636 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
637 static_cast<uint32_t>(B));
640 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
641 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
642 static_cast<uint32_t>(B));
645 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
649 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
651 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
652 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
655 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
656 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
658 switch (virtuality(SPFlags)) {
659 case LLVMRustDISPFlags::SPFlagVirtual:
660 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
662 case LLVMRustDISPFlags::SPFlagPureVirtual:
663 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
666 // The rest are handled below
670 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
671 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
673 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
674 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
676 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
677 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
679 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
680 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
686 enum class LLVMRustDebugEmissionKind {
692 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
694 case LLVMRustDebugEmissionKind::NoDebug:
695 return DICompileUnit::DebugEmissionKind::NoDebug;
696 case LLVMRustDebugEmissionKind::FullDebug:
697 return DICompileUnit::DebugEmissionKind::FullDebug;
698 case LLVMRustDebugEmissionKind::LineTablesOnly:
699 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
701 report_fatal_error("bad DebugEmissionKind.");
705 enum class LLVMRustChecksumKind {
712 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
714 case LLVMRustChecksumKind::None:
716 case LLVMRustChecksumKind::MD5:
717 return DIFile::ChecksumKind::CSK_MD5;
718 case LLVMRustChecksumKind::SHA1:
719 return DIFile::ChecksumKind::CSK_SHA1;
720 case LLVMRustChecksumKind::SHA256:
721 return DIFile::ChecksumKind::CSK_SHA256;
723 report_fatal_error("bad ChecksumKind.");
727 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
728 return DEBUG_METADATA_VERSION;
731 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
733 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
735 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
737 extern "C" void LLVMRustAddModuleFlag(
739 Module::ModFlagBehavior MergeBehavior,
742 unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
745 extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
747 return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
750 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
751 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
754 extern "C" void LLVMRustGlobalAddMetadata(
755 LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) {
756 unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
759 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
760 return new DIBuilder(*unwrap(M));
763 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
767 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
771 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
772 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
773 const char *Producer, size_t ProducerLen, bool isOptimized,
774 const char *Flags, unsigned RuntimeVer,
775 const char *SplitName, size_t SplitNameLen,
776 LLVMRustDebugEmissionKind Kind,
777 uint64_t DWOId, bool SplitDebugInlining) {
778 auto *File = unwrapDI<DIFile>(FileRef);
780 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
781 isOptimized, Flags, RuntimeVer,
782 StringRef(SplitName, SplitNameLen),
783 fromRust(Kind), DWOId, SplitDebugInlining));
786 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
787 LLVMRustDIBuilderRef Builder,
788 const char *Filename, size_t FilenameLen,
789 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
790 const char *Checksum, size_t ChecksumLen) {
791 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
792 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
794 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
795 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
796 StringRef(Directory, DirectoryLen),
800 extern "C" LLVMMetadataRef
801 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
802 LLVMMetadataRef ParameterTypes) {
803 return wrap(Builder->createSubroutineType(
804 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
807 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
808 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
809 const char *Name, size_t NameLen,
810 const char *LinkageName, size_t LinkageNameLen,
811 LLVMMetadataRef File, unsigned LineNo,
812 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
813 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
814 LLVMMetadataRef Decl) {
815 DITemplateParameterArray TParams =
816 DITemplateParameterArray(unwrap<MDTuple>(TParam));
817 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
818 DINode::DIFlags llvmFlags = fromRust(Flags);
819 DISubprogram *Sub = Builder->createFunction(
820 unwrapDI<DIScope>(Scope),
821 StringRef(Name, NameLen),
822 StringRef(LinkageName, LinkageNameLen),
823 unwrapDI<DIFile>(File), LineNo,
824 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
825 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
827 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
831 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
832 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
833 uint64_t SizeInBits, unsigned Encoding) {
834 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
837 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
838 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
839 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
840 return wrap(Builder->createTypedef(
841 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
842 LineNo, unwrapDIPtr<DIScope>(Scope)));
845 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
846 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
847 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
848 const char *Name, size_t NameLen) {
849 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
850 SizeInBits, AlignInBits,
852 StringRef(Name, NameLen)));
855 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
856 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
857 const char *Name, size_t NameLen,
858 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
859 uint32_t AlignInBits, LLVMRustDIFlags Flags,
860 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
861 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
862 const char *UniqueId, size_t UniqueIdLen) {
863 return wrap(Builder->createStructType(
864 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
865 unwrapDI<DIFile>(File), LineNumber,
866 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
867 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
868 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
871 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
872 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
873 const char *Name, size_t NameLen,
874 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
875 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
876 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
877 return wrap(Builder->createVariantPart(
878 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
879 unwrapDI<DIFile>(File), LineNumber,
880 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
881 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
884 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
885 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
886 const char *Name, size_t NameLen,
887 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
888 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
889 LLVMMetadataRef Ty) {
890 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
891 StringRef(Name, NameLen),
892 unwrapDI<DIFile>(File), LineNo,
893 SizeInBits, AlignInBits, OffsetInBits,
894 fromRust(Flags), unwrapDI<DIType>(Ty)));
897 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
898 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
899 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
900 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
901 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
902 llvm::ConstantInt* D = nullptr;
904 D = unwrap<llvm::ConstantInt>(Discriminant);
906 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
907 StringRef(Name, NameLen),
908 unwrapDI<DIFile>(File), LineNo,
909 SizeInBits, AlignInBits, OffsetInBits, D,
910 fromRust(Flags), unwrapDI<DIType>(Ty)));
913 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
914 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
915 LLVMMetadataRef File, unsigned Line, unsigned Col) {
916 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
917 unwrapDI<DIFile>(File), Line, Col));
920 extern "C" LLVMMetadataRef
921 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
922 LLVMMetadataRef Scope,
923 LLVMMetadataRef File) {
924 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
925 unwrapDI<DIFile>(File)));
928 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
929 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
930 const char *Name, size_t NameLen,
931 const char *LinkageName, size_t LinkageNameLen,
932 LLVMMetadataRef File, unsigned LineNo,
933 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
934 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
935 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
937 llvm::DIExpression *InitExpr = nullptr;
938 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
939 InitExpr = Builder->createConstantValueExpression(
940 IntVal->getValue().getSExtValue());
941 } else if (llvm::ConstantFP *FPVal =
942 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
943 InitExpr = Builder->createConstantValueExpression(
944 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
947 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
948 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
949 StringRef(LinkageName, LinkageNameLen),
950 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
951 /* isDefined */ true,
952 InitExpr, unwrapDIPtr<MDNode>(Decl),
953 /* templateParams */ nullptr,
956 InitVal->setMetadata("dbg", VarExpr);
958 return wrap(VarExpr);
961 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
962 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
963 const char *Name, size_t NameLen,
964 LLVMMetadataRef File, unsigned LineNo,
965 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
966 unsigned ArgNo, uint32_t AlignInBits) {
967 if (Tag == 0x100) { // DW_TAG_auto_variable
968 return wrap(Builder->createAutoVariable(
969 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
970 unwrapDI<DIFile>(File), LineNo,
971 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
973 return wrap(Builder->createParameterVariable(
974 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
975 unwrapDI<DIFile>(File), LineNo,
976 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
980 extern "C" LLVMMetadataRef
981 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
982 uint32_t AlignInBits, LLVMMetadataRef Ty,
983 LLVMMetadataRef Subscripts) {
985 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
986 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
989 extern "C" LLVMMetadataRef
990 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
992 return wrap(Builder->getOrCreateSubrange(Lo, Count));
995 extern "C" LLVMMetadataRef
996 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
997 LLVMMetadataRef *Ptr, unsigned Count) {
998 Metadata **DataValue = unwrap(Ptr);
1000 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
1003 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
1004 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
1005 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
1006 LLVMBasicBlockRef InsertAtEnd) {
1007 return wrap(Builder->insertDeclare(
1008 unwrap(V), unwrap<DILocalVariable>(VarInfo),
1009 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
1010 DebugLoc(cast<MDNode>(unwrap(DL))),
1011 unwrap(InsertAtEnd)));
1014 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
1015 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
1016 int64_t Value, bool IsUnsigned) {
1017 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
1020 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
1021 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1022 const char *Name, size_t NameLen,
1023 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1024 uint32_t AlignInBits, LLVMMetadataRef Elements,
1025 LLVMMetadataRef ClassTy, bool IsScoped) {
1026 return wrap(Builder->createEnumerationType(
1027 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
1028 unwrapDI<DIFile>(File), LineNumber,
1029 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
1030 unwrapDI<DIType>(ClassTy), "", IsScoped));
1033 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
1034 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1035 const char *Name, size_t NameLen,
1036 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1037 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
1038 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
1039 return wrap(Builder->createUnionType(
1040 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1041 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1042 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1043 StringRef(UniqueId, UniqueIdLen)));
1046 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1047 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1048 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1049 bool IsDefault = false; // FIXME: should we ever set this true?
1050 return wrap(Builder->createTemplateTypeParameter(
1051 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1054 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1055 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1056 const char *Name, size_t NameLen, bool ExportSymbols) {
1057 return wrap(Builder->createNameSpace(
1058 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1063 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1064 LLVMMetadataRef CompositeTy,
1065 LLVMMetadataRef Elements,
1066 LLVMMetadataRef Params) {
1067 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1068 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1069 DINodeArray(unwrap<MDTuple>(Params)));
1072 extern "C" LLVMMetadataRef
1073 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1074 LLVMMetadataRef ScopeRef,
1075 LLVMMetadataRef InlinedAt) {
1076 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1077 DILocation *Loc = DILocation::get(
1078 Scope->getContext(), Line, Column, Scope,
1079 unwrapDIPtr<MDNode>(InlinedAt));
1083 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1084 return dwarf::DW_OP_deref;
1087 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1088 return dwarf::DW_OP_plus_uconst;
1091 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1092 RawRustStringOstream OS(Str);
1093 unwrap<llvm::Type>(Ty)->print(OS);
1096 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1097 RustStringRef Str) {
1098 RawRustStringOstream OS(Str);
1103 unwrap<llvm::Value>(V)->getType()->print(OS);
1105 unwrap<llvm::Value>(V)->print(OS);
1110 // LLVMArrayType function does not support 64-bit ElementCount
1111 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1112 uint64_t ElementCount) {
1113 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1116 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1118 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1119 RawRustStringOstream OS(Str);
1120 unwrap(T)->print(OS);
1123 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1124 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1125 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1126 RustStringRef FilenameOut, RustStringRef MessageOut) {
1127 // Undefined to call this not on an optimization diagnostic!
1128 llvm::DiagnosticInfoOptimizationBase *Opt =
1129 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1131 RawRustStringOstream PassNameOS(PassNameOut);
1132 PassNameOS << Opt->getPassName();
1133 *FunctionOut = wrap(&Opt->getFunction());
1135 RawRustStringOstream FilenameOS(FilenameOut);
1136 DiagnosticLocation loc = Opt->getLocation();
1137 if (loc.isValid()) {
1138 *Line = loc.getLine();
1139 *Column = loc.getColumn();
1140 FilenameOS << loc.getAbsolutePath();
1143 RawRustStringOstream MessageOS(MessageOut);
1144 MessageOS << Opt->getMsg();
1147 enum class LLVMRustDiagnosticLevel {
1155 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1156 LLVMRustDiagnosticLevel *LevelOut,
1157 unsigned *CookieOut,
1158 LLVMTwineRef *MessageOut) {
1159 // Undefined to call this not on an inline assembly diagnostic!
1160 llvm::DiagnosticInfoInlineAsm *IA =
1161 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1163 *CookieOut = IA->getLocCookie();
1164 *MessageOut = wrap(&IA->getMsgStr());
1166 switch (IA->getSeverity()) {
1168 *LevelOut = LLVMRustDiagnosticLevel::Error;
1171 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1174 *LevelOut = LLVMRustDiagnosticLevel::Note;
1177 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1180 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1184 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1185 RustStringRef Str) {
1186 RawRustStringOstream OS(Str);
1187 DiagnosticPrinterRawOStream DP(OS);
1188 unwrap(DI)->print(DP);
1191 enum class LLVMRustDiagnosticKind {
1195 DebugMetadataVersion,
1198 OptimizationRemarkMissed,
1199 OptimizationRemarkAnalysis,
1200 OptimizationRemarkAnalysisFPCommute,
1201 OptimizationRemarkAnalysisAliasing,
1202 OptimizationRemarkOther,
1203 OptimizationFailure,
1210 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1213 return LLVMRustDiagnosticKind::InlineAsm;
1215 return LLVMRustDiagnosticKind::StackSize;
1216 case DK_DebugMetadataVersion:
1217 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1218 case DK_SampleProfile:
1219 return LLVMRustDiagnosticKind::SampleProfile;
1220 case DK_OptimizationRemark:
1221 case DK_MachineOptimizationRemark:
1222 return LLVMRustDiagnosticKind::OptimizationRemark;
1223 case DK_OptimizationRemarkMissed:
1224 case DK_MachineOptimizationRemarkMissed:
1225 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1226 case DK_OptimizationRemarkAnalysis:
1227 case DK_MachineOptimizationRemarkAnalysis:
1228 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1229 case DK_OptimizationRemarkAnalysisFPCommute:
1230 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1231 case DK_OptimizationRemarkAnalysisAliasing:
1232 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1234 return LLVMRustDiagnosticKind::PGOProfile;
1236 return LLVMRustDiagnosticKind::Linker;
1237 case DK_Unsupported:
1238 return LLVMRustDiagnosticKind::Unsupported;
1240 return LLVMRustDiagnosticKind::SrcMgr;
1242 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1243 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1244 : LLVMRustDiagnosticKind::Other;
1248 extern "C" LLVMRustDiagnosticKind
1249 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1250 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1253 // This is kept distinct from LLVMGetTypeKind, because when
1254 // a new type kind is added, the Rust-side enum must be
1255 // updated or UB will result.
1256 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1257 switch (unwrap(Ty)->getTypeID()) {
1258 case Type::VoidTyID:
1259 return LLVMVoidTypeKind;
1260 case Type::HalfTyID:
1261 return LLVMHalfTypeKind;
1262 case Type::FloatTyID:
1263 return LLVMFloatTypeKind;
1264 case Type::DoubleTyID:
1265 return LLVMDoubleTypeKind;
1266 case Type::X86_FP80TyID:
1267 return LLVMX86_FP80TypeKind;
1268 case Type::FP128TyID:
1269 return LLVMFP128TypeKind;
1270 case Type::PPC_FP128TyID:
1271 return LLVMPPC_FP128TypeKind;
1272 case Type::LabelTyID:
1273 return LLVMLabelTypeKind;
1274 case Type::MetadataTyID:
1275 return LLVMMetadataTypeKind;
1276 case Type::IntegerTyID:
1277 return LLVMIntegerTypeKind;
1278 case Type::FunctionTyID:
1279 return LLVMFunctionTypeKind;
1280 case Type::StructTyID:
1281 return LLVMStructTypeKind;
1282 case Type::ArrayTyID:
1283 return LLVMArrayTypeKind;
1284 case Type::PointerTyID:
1285 return LLVMPointerTypeKind;
1286 case Type::FixedVectorTyID:
1287 return LLVMVectorTypeKind;
1288 case Type::X86_MMXTyID:
1289 return LLVMX86_MMXTypeKind;
1290 case Type::TokenTyID:
1291 return LLVMTokenTypeKind;
1292 case Type::ScalableVectorTyID:
1293 return LLVMScalableVectorTypeKind;
1294 case Type::BFloatTyID:
1295 return LLVMBFloatTypeKind;
1296 case Type::X86_AMXTyID:
1297 return LLVMX86_AMXTypeKind;
1298 #if LLVM_VERSION_GE(15, 0) && LLVM_VERSION_LT(16, 0)
1299 case Type::DXILPointerTyID:
1300 report_fatal_error("Rust does not support DirectX typed pointers.");
1303 #if LLVM_VERSION_GE(16, 0)
1304 case Type::TypedPointerTyID:
1305 report_fatal_error("Rust does not support typed pointers.");
1309 report_fatal_error("Unhandled TypeID.");
1312 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1314 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1315 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1316 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1317 *Cookie = SM->getLocCookie();
1318 return wrap(&SM->getSMDiag());
1321 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1322 RustStringRef MessageOut,
1323 RustStringRef BufferOut,
1324 LLVMRustDiagnosticLevel* LevelOut,
1326 unsigned* RangesOut,
1327 size_t* NumRanges) {
1328 SMDiagnostic& D = *unwrap(DRef);
1329 RawRustStringOstream MessageOS(MessageOut);
1330 MessageOS << D.getMessage();
1332 switch (D.getKind()) {
1333 case SourceMgr::DK_Error:
1334 *LevelOut = LLVMRustDiagnosticLevel::Error;
1336 case SourceMgr::DK_Warning:
1337 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1339 case SourceMgr::DK_Note:
1340 *LevelOut = LLVMRustDiagnosticLevel::Note;
1342 case SourceMgr::DK_Remark:
1343 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1346 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1349 if (D.getLoc() == SMLoc())
1352 const SourceMgr &LSM = *D.getSourceMgr();
1353 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1354 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1356 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1358 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1359 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1360 for (size_t i = 0; i < *NumRanges; i++) {
1361 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1362 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1368 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1369 LLVMValueRef ParentPad,
1371 LLVMValueRef *LLArgs,
1373 Value **Args = unwrap(LLArgs);
1374 if (ParentPad == nullptr) {
1375 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1376 ParentPad = wrap(Constant::getNullValue(Ty));
1378 return wrap(unwrap(B)->CreateCleanupPad(
1379 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1382 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1383 LLVMValueRef CleanupPad,
1384 LLVMBasicBlockRef UnwindBB) {
1385 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1386 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1389 extern "C" LLVMValueRef
1390 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1391 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1392 Value **Args = unwrap(LLArgs);
1393 return wrap(unwrap(B)->CreateCatchPad(
1394 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1397 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1399 LLVMBasicBlockRef BB) {
1400 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1404 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1405 LLVMValueRef ParentPad,
1406 LLVMBasicBlockRef BB,
1407 unsigned NumHandlers,
1409 if (ParentPad == nullptr) {
1410 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1411 ParentPad = wrap(Constant::getNullValue(Ty));
1413 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1414 NumHandlers, Name));
1417 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1418 LLVMBasicBlockRef Handler) {
1419 Value *CatchSwitch = unwrap(CatchSwitchRef);
1420 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1423 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1424 LLVMValueRef *Inputs,
1425 unsigned NumInputs) {
1426 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1429 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1433 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1434 LLVMValueRef *Args, unsigned NumArgs,
1435 OperandBundleDef *Bundle) {
1436 Value *Callee = unwrap(Fn);
1437 FunctionType *FTy = unwrap<FunctionType>(Ty);
1438 unsigned Len = Bundle ? 1 : 0;
1439 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1440 return wrap(unwrap(B)->CreateCall(
1441 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1444 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1445 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1446 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1449 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1450 LLVMValueRef Dst, unsigned DstAlign,
1451 LLVMValueRef Src, unsigned SrcAlign,
1452 LLVMValueRef Size, bool IsVolatile) {
1453 return wrap(unwrap(B)->CreateMemCpy(
1454 unwrap(Dst), MaybeAlign(DstAlign),
1455 unwrap(Src), MaybeAlign(SrcAlign),
1456 unwrap(Size), IsVolatile));
1459 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1460 LLVMValueRef Dst, unsigned DstAlign,
1461 LLVMValueRef Src, unsigned SrcAlign,
1462 LLVMValueRef Size, bool IsVolatile) {
1463 return wrap(unwrap(B)->CreateMemMove(
1464 unwrap(Dst), MaybeAlign(DstAlign),
1465 unwrap(Src), MaybeAlign(SrcAlign),
1466 unwrap(Size), IsVolatile));
1469 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1470 LLVMValueRef Dst, unsigned DstAlign,
1472 LLVMValueRef Size, bool IsVolatile) {
1473 return wrap(unwrap(B)->CreateMemSet(
1474 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1477 extern "C" LLVMValueRef
1478 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1479 LLVMValueRef *Args, unsigned NumArgs,
1480 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1481 OperandBundleDef *Bundle, const char *Name) {
1482 Value *Callee = unwrap(Fn);
1483 FunctionType *FTy = unwrap<FunctionType>(Ty);
1484 unsigned Len = Bundle ? 1 : 0;
1485 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1486 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1487 makeArrayRef(unwrap(Args), NumArgs),
1491 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1492 LLVMBasicBlockRef BB) {
1493 auto Point = unwrap(BB)->getFirstInsertionPt();
1494 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1497 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1498 const char *Name, size_t NameLen) {
1499 Triple TargetTriple(unwrap(M)->getTargetTriple());
1500 GlobalObject *GV = unwrap<GlobalObject>(V);
1501 if (TargetTriple.supportsCOMDAT()) {
1502 StringRef NameRef(Name, NameLen);
1503 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1507 enum class LLVMRustLinkage {
1508 ExternalLinkage = 0,
1509 AvailableExternallyLinkage = 1,
1510 LinkOnceAnyLinkage = 2,
1511 LinkOnceODRLinkage = 3,
1514 AppendingLinkage = 6,
1515 InternalLinkage = 7,
1517 ExternalWeakLinkage = 9,
1521 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1523 case LLVMExternalLinkage:
1524 return LLVMRustLinkage::ExternalLinkage;
1525 case LLVMAvailableExternallyLinkage:
1526 return LLVMRustLinkage::AvailableExternallyLinkage;
1527 case LLVMLinkOnceAnyLinkage:
1528 return LLVMRustLinkage::LinkOnceAnyLinkage;
1529 case LLVMLinkOnceODRLinkage:
1530 return LLVMRustLinkage::LinkOnceODRLinkage;
1531 case LLVMWeakAnyLinkage:
1532 return LLVMRustLinkage::WeakAnyLinkage;
1533 case LLVMWeakODRLinkage:
1534 return LLVMRustLinkage::WeakODRLinkage;
1535 case LLVMAppendingLinkage:
1536 return LLVMRustLinkage::AppendingLinkage;
1537 case LLVMInternalLinkage:
1538 return LLVMRustLinkage::InternalLinkage;
1539 case LLVMPrivateLinkage:
1540 return LLVMRustLinkage::PrivateLinkage;
1541 case LLVMExternalWeakLinkage:
1542 return LLVMRustLinkage::ExternalWeakLinkage;
1543 case LLVMCommonLinkage:
1544 return LLVMRustLinkage::CommonLinkage;
1546 report_fatal_error("Invalid LLVMRustLinkage value!");
1550 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1552 case LLVMRustLinkage::ExternalLinkage:
1553 return LLVMExternalLinkage;
1554 case LLVMRustLinkage::AvailableExternallyLinkage:
1555 return LLVMAvailableExternallyLinkage;
1556 case LLVMRustLinkage::LinkOnceAnyLinkage:
1557 return LLVMLinkOnceAnyLinkage;
1558 case LLVMRustLinkage::LinkOnceODRLinkage:
1559 return LLVMLinkOnceODRLinkage;
1560 case LLVMRustLinkage::WeakAnyLinkage:
1561 return LLVMWeakAnyLinkage;
1562 case LLVMRustLinkage::WeakODRLinkage:
1563 return LLVMWeakODRLinkage;
1564 case LLVMRustLinkage::AppendingLinkage:
1565 return LLVMAppendingLinkage;
1566 case LLVMRustLinkage::InternalLinkage:
1567 return LLVMInternalLinkage;
1568 case LLVMRustLinkage::PrivateLinkage:
1569 return LLVMPrivateLinkage;
1570 case LLVMRustLinkage::ExternalWeakLinkage:
1571 return LLVMExternalWeakLinkage;
1572 case LLVMRustLinkage::CommonLinkage:
1573 return LLVMCommonLinkage;
1575 report_fatal_error("Invalid LLVMRustLinkage value!");
1578 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1579 return toRust(LLVMGetLinkage(V));
1582 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1583 LLVMRustLinkage RustLinkage) {
1584 LLVMSetLinkage(V, fromRust(RustLinkage));
1587 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1588 LLVMValueRef ConstantVal,
1589 LLVMValueRef *ConstantIndices,
1590 unsigned NumIndices) {
1591 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1593 Constant *Val = unwrap<Constant>(ConstantVal);
1594 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1597 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1598 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1599 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1601 auto C = unwrap<llvm::ConstantInt>(CV);
1602 if (C->getBitWidth() > 128) { return false; }
1604 #if LLVM_VERSION_GE(15, 0)
1606 AP = C->getValue().sext(128);
1608 AP = C->getValue().zext(128);
1612 AP = C->getValue().sextOrSelf(128);
1614 AP = C->getValue().zextOrSelf(128);
1617 *low = AP.getLoBits(64).getZExtValue();
1618 *high = AP.getHiBits(64).getZExtValue();
1622 enum class LLVMRustVisibility {
1628 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1630 case LLVMDefaultVisibility:
1631 return LLVMRustVisibility::Default;
1632 case LLVMHiddenVisibility:
1633 return LLVMRustVisibility::Hidden;
1634 case LLVMProtectedVisibility:
1635 return LLVMRustVisibility::Protected;
1637 report_fatal_error("Invalid LLVMRustVisibility value!");
1640 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1642 case LLVMRustVisibility::Default:
1643 return LLVMDefaultVisibility;
1644 case LLVMRustVisibility::Hidden:
1645 return LLVMHiddenVisibility;
1646 case LLVMRustVisibility::Protected:
1647 return LLVMProtectedVisibility;
1649 report_fatal_error("Invalid LLVMRustVisibility value!");
1652 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1653 return toRust(LLVMGetVisibility(V));
1656 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1657 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1658 LLVMTypeRef DestTy, bool isSigned) {
1659 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1662 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1663 LLVMRustVisibility RustVisibility) {
1664 LLVMSetVisibility(V, fromRust(RustVisibility));
1667 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1668 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1671 struct LLVMRustModuleBuffer {
1675 extern "C" LLVMRustModuleBuffer*
1676 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1677 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1679 raw_string_ostream OS(Ret->data);
1681 legacy::PassManager PM;
1682 PM.add(createBitcodeWriterPass(OS));
1686 return Ret.release();
1690 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1694 extern "C" const void*
1695 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1696 return Buffer->data.data();
1700 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1701 return Buffer->data.length();
1705 LLVMRustModuleCost(LLVMModuleRef M) {
1706 auto f = unwrap(M)->functions();
1707 return std::distance(std::begin(f), std::end(f));
1710 // Vector reductions:
1711 extern "C" LLVMValueRef
1712 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1713 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1715 extern "C" LLVMValueRef
1716 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1717 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1719 extern "C" LLVMValueRef
1720 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1721 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1723 extern "C" LLVMValueRef
1724 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1725 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1727 extern "C" LLVMValueRef
1728 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1729 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1731 extern "C" LLVMValueRef
1732 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1733 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1735 extern "C" LLVMValueRef
1736 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1737 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1739 extern "C" LLVMValueRef
1740 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1741 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1743 extern "C" LLVMValueRef
1744 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1745 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1747 extern "C" LLVMValueRef
1748 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1749 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1750 I->setHasNoNaNs(NoNaN);
1753 extern "C" LLVMValueRef
1754 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1755 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1756 I->setHasNoNaNs(NoNaN);
1760 extern "C" LLVMValueRef
1761 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1762 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1764 extern "C" LLVMValueRef
1765 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1766 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1769 // This struct contains all necessary info about a symbol exported from a DLL.
1770 struct LLVMRustCOFFShortExport {
1772 bool ordinal_present;
1773 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1777 // Machine must be a COFF machine type, as defined in PE specs.
1778 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1779 const char* ImportName,
1781 const LLVMRustCOFFShortExport* Exports,
1786 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1787 ConvertedExports.reserve(NumExports);
1789 for (size_t i = 0; i < NumExports; ++i) {
1790 bool ordinal_present = Exports[i].ordinal_present;
1791 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1792 ConvertedExports.push_back(llvm::object::COFFShortExport{
1793 Exports[i].name, // Name
1794 std::string{}, // ExtName
1795 std::string{}, // SymbolName
1796 std::string{}, // AliasTarget
1798 ordinal_present, // Noname
1805 auto Error = llvm::object::writeImportLibrary(
1809 static_cast<llvm::COFF::MachineTypes>(Machine),
1812 std::string errorString;
1813 llvm::raw_string_ostream stream(errorString);
1816 LLVMRustSetLastError(errorString.c_str());
1817 return LLVMRustResult::Failure;
1819 return LLVMRustResult::Success;
1823 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1824 extern "C" DiagnosticHandler *
1825 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1826 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1827 return DH.release();
1830 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1831 // handling. Ownership of the handler is moved to the LLVMContext.
1832 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1833 DiagnosticHandler *DH) {
1834 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1837 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1839 // Configures a diagnostic handler that invokes provided callback when a
1840 // backend needs to emit a diagnostic.
1842 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1843 // the RemarkPasses array specifies individual passes for which remarks will be
1845 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1846 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1847 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1848 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1850 class RustDiagnosticHandler final : public DiagnosticHandler {
1852 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1853 void *DiagnosticHandlerContext,
1854 bool RemarkAllPasses,
1855 std::vector<std::string> RemarkPasses)
1856 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1857 DiagnosticHandlerContext(DiagnosticHandlerContext),
1858 RemarkAllPasses(RemarkAllPasses),
1859 RemarkPasses(RemarkPasses) {}
1861 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1862 if (DiagnosticHandlerCallback) {
1863 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1869 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1870 return isRemarkEnabled(PassName);
1873 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1874 return isRemarkEnabled(PassName);
1877 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1878 return isRemarkEnabled(PassName);
1881 bool isAnyRemarkEnabled() const override {
1882 return RemarkAllPasses || !RemarkPasses.empty();
1886 bool isRemarkEnabled(StringRef PassName) const {
1887 if (RemarkAllPasses)
1890 for (auto &Pass : RemarkPasses)
1891 if (Pass == PassName)
1897 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1898 void *DiagnosticHandlerContext = nullptr;
1900 bool RemarkAllPasses = false;
1901 std::vector<std::string> RemarkPasses;
1904 std::vector<std::string> Passes;
1905 for (size_t I = 0; I != RemarkPassesLen; ++I)
1906 Passes.push_back(RemarkPasses[I]);
1908 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1909 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
1912 extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
1913 RawRustStringOstream OS(Str);
1914 GlobalValue *GV = unwrap<GlobalValue>(V);
1915 Mangler().getNameWithPrefix(OS, GV, true);
1918 // LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just
1919 // use its implementation.
1920 #if LLVM_VERSION_LT(15, 0)
1921 extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
1922 return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));
1926 extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
1927 #if LLVM_VERSION_GE(15, 0)
1928 auto *CB = unwrap<CallBase>(CallSite);
1929 switch (CB->getIntrinsicID()) {
1930 case Intrinsic::arm_ldrex:
1932 case Intrinsic::arm_strex: