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 LLVMRustDIBuilderCreateStaticMemberType(
914 LLVMRustDIBuilderRef Builder,
915 LLVMMetadataRef Scope,
918 LLVMMetadataRef File,
921 LLVMRustDIFlags Flags,
925 return wrap(Builder->createStaticMemberType(
926 unwrapDI<DIDescriptor>(Scope),
927 StringRef(Name, NameLen),
928 unwrapDI<DIFile>(File),
930 unwrapDI<DIType>(Ty),
932 unwrap<llvm::ConstantInt>(val),
937 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
938 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
939 LLVMMetadataRef File, unsigned Line, unsigned Col) {
940 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
941 unwrapDI<DIFile>(File), Line, Col));
944 extern "C" LLVMMetadataRef
945 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
946 LLVMMetadataRef Scope,
947 LLVMMetadataRef File) {
948 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
949 unwrapDI<DIFile>(File)));
952 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
953 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
954 const char *Name, size_t NameLen,
955 const char *LinkageName, size_t LinkageNameLen,
956 LLVMMetadataRef File, unsigned LineNo,
957 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
958 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
959 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
961 llvm::DIExpression *InitExpr = nullptr;
962 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
963 InitExpr = Builder->createConstantValueExpression(
964 IntVal->getValue().getSExtValue());
965 } else if (llvm::ConstantFP *FPVal =
966 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
967 InitExpr = Builder->createConstantValueExpression(
968 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
971 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
972 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
973 StringRef(LinkageName, LinkageNameLen),
974 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
975 /* isDefined */ true,
976 InitExpr, unwrapDIPtr<MDNode>(Decl),
977 /* templateParams */ nullptr,
980 InitVal->setMetadata("dbg", VarExpr);
982 return wrap(VarExpr);
985 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
986 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
987 const char *Name, size_t NameLen,
988 LLVMMetadataRef File, unsigned LineNo,
989 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
990 unsigned ArgNo, uint32_t AlignInBits) {
991 if (Tag == 0x100) { // DW_TAG_auto_variable
992 return wrap(Builder->createAutoVariable(
993 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
994 unwrapDI<DIFile>(File), LineNo,
995 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
997 return wrap(Builder->createParameterVariable(
998 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
999 unwrapDI<DIFile>(File), LineNo,
1000 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
1004 extern "C" LLVMMetadataRef
1005 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
1006 uint32_t AlignInBits, LLVMMetadataRef Ty,
1007 LLVMMetadataRef Subscripts) {
1009 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
1010 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
1013 extern "C" LLVMMetadataRef
1014 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
1016 return wrap(Builder->getOrCreateSubrange(Lo, Count));
1019 extern "C" LLVMMetadataRef
1020 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
1021 LLVMMetadataRef *Ptr, unsigned Count) {
1022 Metadata **DataValue = unwrap(Ptr);
1024 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
1027 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
1028 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
1029 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
1030 LLVMBasicBlockRef InsertAtEnd) {
1031 return wrap(Builder->insertDeclare(
1032 unwrap(V), unwrap<DILocalVariable>(VarInfo),
1033 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
1034 DebugLoc(cast<MDNode>(unwrap(DL))),
1035 unwrap(InsertAtEnd)));
1038 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
1039 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
1040 int64_t Value, bool IsUnsigned) {
1041 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
1044 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
1045 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1046 const char *Name, size_t NameLen,
1047 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1048 uint32_t AlignInBits, LLVMMetadataRef Elements,
1049 LLVMMetadataRef ClassTy, bool IsScoped) {
1050 return wrap(Builder->createEnumerationType(
1051 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
1052 unwrapDI<DIFile>(File), LineNumber,
1053 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
1054 unwrapDI<DIType>(ClassTy), "", IsScoped));
1057 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
1058 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1059 const char *Name, size_t NameLen,
1060 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1061 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
1062 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
1063 return wrap(Builder->createUnionType(
1064 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1065 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1066 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1067 StringRef(UniqueId, UniqueIdLen)));
1070 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1071 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1072 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1073 bool IsDefault = false; // FIXME: should we ever set this true?
1074 return wrap(Builder->createTemplateTypeParameter(
1075 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1078 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1079 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1080 const char *Name, size_t NameLen, bool ExportSymbols) {
1081 return wrap(Builder->createNameSpace(
1082 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1087 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1088 LLVMMetadataRef CompositeTy,
1089 LLVMMetadataRef Elements,
1090 LLVMMetadataRef Params) {
1091 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1092 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1093 DINodeArray(unwrap<MDTuple>(Params)));
1096 extern "C" LLVMMetadataRef
1097 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1098 LLVMMetadataRef ScopeRef,
1099 LLVMMetadataRef InlinedAt) {
1100 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1101 DILocation *Loc = DILocation::get(
1102 Scope->getContext(), Line, Column, Scope,
1103 unwrapDIPtr<MDNode>(InlinedAt));
1107 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1108 return dwarf::DW_OP_deref;
1111 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1112 return dwarf::DW_OP_plus_uconst;
1115 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1116 RawRustStringOstream OS(Str);
1117 unwrap<llvm::Type>(Ty)->print(OS);
1120 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1121 RustStringRef Str) {
1122 RawRustStringOstream OS(Str);
1127 unwrap<llvm::Value>(V)->getType()->print(OS);
1129 unwrap<llvm::Value>(V)->print(OS);
1134 // LLVMArrayType function does not support 64-bit ElementCount
1135 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1136 uint64_t ElementCount) {
1137 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1140 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1142 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1143 RawRustStringOstream OS(Str);
1144 unwrap(T)->print(OS);
1147 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1148 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1149 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1150 RustStringRef FilenameOut, RustStringRef MessageOut) {
1151 // Undefined to call this not on an optimization diagnostic!
1152 llvm::DiagnosticInfoOptimizationBase *Opt =
1153 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1155 RawRustStringOstream PassNameOS(PassNameOut);
1156 PassNameOS << Opt->getPassName();
1157 *FunctionOut = wrap(&Opt->getFunction());
1159 RawRustStringOstream FilenameOS(FilenameOut);
1160 DiagnosticLocation loc = Opt->getLocation();
1161 if (loc.isValid()) {
1162 *Line = loc.getLine();
1163 *Column = loc.getColumn();
1164 FilenameOS << loc.getAbsolutePath();
1167 RawRustStringOstream MessageOS(MessageOut);
1168 MessageOS << Opt->getMsg();
1171 enum class LLVMRustDiagnosticLevel {
1179 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1180 LLVMRustDiagnosticLevel *LevelOut,
1181 unsigned *CookieOut,
1182 LLVMTwineRef *MessageOut) {
1183 // Undefined to call this not on an inline assembly diagnostic!
1184 llvm::DiagnosticInfoInlineAsm *IA =
1185 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1187 *CookieOut = IA->getLocCookie();
1188 *MessageOut = wrap(&IA->getMsgStr());
1190 switch (IA->getSeverity()) {
1192 *LevelOut = LLVMRustDiagnosticLevel::Error;
1195 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1198 *LevelOut = LLVMRustDiagnosticLevel::Note;
1201 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1204 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1208 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1209 RustStringRef Str) {
1210 RawRustStringOstream OS(Str);
1211 DiagnosticPrinterRawOStream DP(OS);
1212 unwrap(DI)->print(DP);
1215 enum class LLVMRustDiagnosticKind {
1219 DebugMetadataVersion,
1222 OptimizationRemarkMissed,
1223 OptimizationRemarkAnalysis,
1224 OptimizationRemarkAnalysisFPCommute,
1225 OptimizationRemarkAnalysisAliasing,
1226 OptimizationRemarkOther,
1227 OptimizationFailure,
1234 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1237 return LLVMRustDiagnosticKind::InlineAsm;
1239 return LLVMRustDiagnosticKind::StackSize;
1240 case DK_DebugMetadataVersion:
1241 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1242 case DK_SampleProfile:
1243 return LLVMRustDiagnosticKind::SampleProfile;
1244 case DK_OptimizationRemark:
1245 case DK_MachineOptimizationRemark:
1246 return LLVMRustDiagnosticKind::OptimizationRemark;
1247 case DK_OptimizationRemarkMissed:
1248 case DK_MachineOptimizationRemarkMissed:
1249 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1250 case DK_OptimizationRemarkAnalysis:
1251 case DK_MachineOptimizationRemarkAnalysis:
1252 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1253 case DK_OptimizationRemarkAnalysisFPCommute:
1254 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1255 case DK_OptimizationRemarkAnalysisAliasing:
1256 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1258 return LLVMRustDiagnosticKind::PGOProfile;
1260 return LLVMRustDiagnosticKind::Linker;
1261 case DK_Unsupported:
1262 return LLVMRustDiagnosticKind::Unsupported;
1264 return LLVMRustDiagnosticKind::SrcMgr;
1266 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1267 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1268 : LLVMRustDiagnosticKind::Other;
1272 extern "C" LLVMRustDiagnosticKind
1273 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1274 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1277 // This is kept distinct from LLVMGetTypeKind, because when
1278 // a new type kind is added, the Rust-side enum must be
1279 // updated or UB will result.
1280 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1281 switch (unwrap(Ty)->getTypeID()) {
1282 case Type::VoidTyID:
1283 return LLVMVoidTypeKind;
1284 case Type::HalfTyID:
1285 return LLVMHalfTypeKind;
1286 case Type::FloatTyID:
1287 return LLVMFloatTypeKind;
1288 case Type::DoubleTyID:
1289 return LLVMDoubleTypeKind;
1290 case Type::X86_FP80TyID:
1291 return LLVMX86_FP80TypeKind;
1292 case Type::FP128TyID:
1293 return LLVMFP128TypeKind;
1294 case Type::PPC_FP128TyID:
1295 return LLVMPPC_FP128TypeKind;
1296 case Type::LabelTyID:
1297 return LLVMLabelTypeKind;
1298 case Type::MetadataTyID:
1299 return LLVMMetadataTypeKind;
1300 case Type::IntegerTyID:
1301 return LLVMIntegerTypeKind;
1302 case Type::FunctionTyID:
1303 return LLVMFunctionTypeKind;
1304 case Type::StructTyID:
1305 return LLVMStructTypeKind;
1306 case Type::ArrayTyID:
1307 return LLVMArrayTypeKind;
1308 case Type::PointerTyID:
1309 return LLVMPointerTypeKind;
1310 case Type::FixedVectorTyID:
1311 return LLVMVectorTypeKind;
1312 case Type::X86_MMXTyID:
1313 return LLVMX86_MMXTypeKind;
1314 case Type::TokenTyID:
1315 return LLVMTokenTypeKind;
1316 case Type::ScalableVectorTyID:
1317 return LLVMScalableVectorTypeKind;
1318 case Type::BFloatTyID:
1319 return LLVMBFloatTypeKind;
1320 case Type::X86_AMXTyID:
1321 return LLVMX86_AMXTypeKind;
1322 #if LLVM_VERSION_GE(15, 0) && LLVM_VERSION_LT(16, 0)
1323 case Type::DXILPointerTyID:
1324 report_fatal_error("Rust does not support DirectX typed pointers.");
1327 #if LLVM_VERSION_GE(16, 0)
1328 case Type::TypedPointerTyID:
1329 report_fatal_error("Rust does not support typed pointers.");
1333 report_fatal_error("Unhandled TypeID.");
1336 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1338 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1339 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1340 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1341 *Cookie = SM->getLocCookie();
1342 return wrap(&SM->getSMDiag());
1345 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1346 RustStringRef MessageOut,
1347 RustStringRef BufferOut,
1348 LLVMRustDiagnosticLevel* LevelOut,
1350 unsigned* RangesOut,
1351 size_t* NumRanges) {
1352 SMDiagnostic& D = *unwrap(DRef);
1353 RawRustStringOstream MessageOS(MessageOut);
1354 MessageOS << D.getMessage();
1356 switch (D.getKind()) {
1357 case SourceMgr::DK_Error:
1358 *LevelOut = LLVMRustDiagnosticLevel::Error;
1360 case SourceMgr::DK_Warning:
1361 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1363 case SourceMgr::DK_Note:
1364 *LevelOut = LLVMRustDiagnosticLevel::Note;
1366 case SourceMgr::DK_Remark:
1367 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1370 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1373 if (D.getLoc() == SMLoc())
1376 const SourceMgr &LSM = *D.getSourceMgr();
1377 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1378 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1380 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1382 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1383 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1384 for (size_t i = 0; i < *NumRanges; i++) {
1385 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1386 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1392 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1393 LLVMValueRef ParentPad,
1395 LLVMValueRef *LLArgs,
1397 Value **Args = unwrap(LLArgs);
1398 if (ParentPad == nullptr) {
1399 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1400 ParentPad = wrap(Constant::getNullValue(Ty));
1402 return wrap(unwrap(B)->CreateCleanupPad(
1403 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1406 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1407 LLVMValueRef CleanupPad,
1408 LLVMBasicBlockRef UnwindBB) {
1409 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1410 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1413 extern "C" LLVMValueRef
1414 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1415 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1416 Value **Args = unwrap(LLArgs);
1417 return wrap(unwrap(B)->CreateCatchPad(
1418 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1421 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1423 LLVMBasicBlockRef BB) {
1424 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1428 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1429 LLVMValueRef ParentPad,
1430 LLVMBasicBlockRef BB,
1431 unsigned NumHandlers,
1433 if (ParentPad == nullptr) {
1434 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1435 ParentPad = wrap(Constant::getNullValue(Ty));
1437 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1438 NumHandlers, Name));
1441 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1442 LLVMBasicBlockRef Handler) {
1443 Value *CatchSwitch = unwrap(CatchSwitchRef);
1444 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1447 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1448 LLVMValueRef *Inputs,
1449 unsigned NumInputs) {
1450 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1453 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1457 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1458 LLVMValueRef *Args, unsigned NumArgs,
1459 OperandBundleDef *Bundle) {
1460 Value *Callee = unwrap(Fn);
1461 FunctionType *FTy = unwrap<FunctionType>(Ty);
1462 unsigned Len = Bundle ? 1 : 0;
1463 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1464 return wrap(unwrap(B)->CreateCall(
1465 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1468 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1469 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1470 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1473 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1474 LLVMValueRef Dst, unsigned DstAlign,
1475 LLVMValueRef Src, unsigned SrcAlign,
1476 LLVMValueRef Size, bool IsVolatile) {
1477 return wrap(unwrap(B)->CreateMemCpy(
1478 unwrap(Dst), MaybeAlign(DstAlign),
1479 unwrap(Src), MaybeAlign(SrcAlign),
1480 unwrap(Size), IsVolatile));
1483 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1484 LLVMValueRef Dst, unsigned DstAlign,
1485 LLVMValueRef Src, unsigned SrcAlign,
1486 LLVMValueRef Size, bool IsVolatile) {
1487 return wrap(unwrap(B)->CreateMemMove(
1488 unwrap(Dst), MaybeAlign(DstAlign),
1489 unwrap(Src), MaybeAlign(SrcAlign),
1490 unwrap(Size), IsVolatile));
1493 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1494 LLVMValueRef Dst, unsigned DstAlign,
1496 LLVMValueRef Size, bool IsVolatile) {
1497 return wrap(unwrap(B)->CreateMemSet(
1498 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1501 extern "C" LLVMValueRef
1502 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1503 LLVMValueRef *Args, unsigned NumArgs,
1504 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1505 OperandBundleDef *Bundle, const char *Name) {
1506 Value *Callee = unwrap(Fn);
1507 FunctionType *FTy = unwrap<FunctionType>(Ty);
1508 unsigned Len = Bundle ? 1 : 0;
1509 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1510 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1511 makeArrayRef(unwrap(Args), NumArgs),
1515 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1516 LLVMBasicBlockRef BB) {
1517 auto Point = unwrap(BB)->getFirstInsertionPt();
1518 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1521 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1522 const char *Name, size_t NameLen) {
1523 Triple TargetTriple(unwrap(M)->getTargetTriple());
1524 GlobalObject *GV = unwrap<GlobalObject>(V);
1525 if (TargetTriple.supportsCOMDAT()) {
1526 StringRef NameRef(Name, NameLen);
1527 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1531 enum class LLVMRustLinkage {
1532 ExternalLinkage = 0,
1533 AvailableExternallyLinkage = 1,
1534 LinkOnceAnyLinkage = 2,
1535 LinkOnceODRLinkage = 3,
1538 AppendingLinkage = 6,
1539 InternalLinkage = 7,
1541 ExternalWeakLinkage = 9,
1545 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1547 case LLVMExternalLinkage:
1548 return LLVMRustLinkage::ExternalLinkage;
1549 case LLVMAvailableExternallyLinkage:
1550 return LLVMRustLinkage::AvailableExternallyLinkage;
1551 case LLVMLinkOnceAnyLinkage:
1552 return LLVMRustLinkage::LinkOnceAnyLinkage;
1553 case LLVMLinkOnceODRLinkage:
1554 return LLVMRustLinkage::LinkOnceODRLinkage;
1555 case LLVMWeakAnyLinkage:
1556 return LLVMRustLinkage::WeakAnyLinkage;
1557 case LLVMWeakODRLinkage:
1558 return LLVMRustLinkage::WeakODRLinkage;
1559 case LLVMAppendingLinkage:
1560 return LLVMRustLinkage::AppendingLinkage;
1561 case LLVMInternalLinkage:
1562 return LLVMRustLinkage::InternalLinkage;
1563 case LLVMPrivateLinkage:
1564 return LLVMRustLinkage::PrivateLinkage;
1565 case LLVMExternalWeakLinkage:
1566 return LLVMRustLinkage::ExternalWeakLinkage;
1567 case LLVMCommonLinkage:
1568 return LLVMRustLinkage::CommonLinkage;
1570 report_fatal_error("Invalid LLVMRustLinkage value!");
1574 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1576 case LLVMRustLinkage::ExternalLinkage:
1577 return LLVMExternalLinkage;
1578 case LLVMRustLinkage::AvailableExternallyLinkage:
1579 return LLVMAvailableExternallyLinkage;
1580 case LLVMRustLinkage::LinkOnceAnyLinkage:
1581 return LLVMLinkOnceAnyLinkage;
1582 case LLVMRustLinkage::LinkOnceODRLinkage:
1583 return LLVMLinkOnceODRLinkage;
1584 case LLVMRustLinkage::WeakAnyLinkage:
1585 return LLVMWeakAnyLinkage;
1586 case LLVMRustLinkage::WeakODRLinkage:
1587 return LLVMWeakODRLinkage;
1588 case LLVMRustLinkage::AppendingLinkage:
1589 return LLVMAppendingLinkage;
1590 case LLVMRustLinkage::InternalLinkage:
1591 return LLVMInternalLinkage;
1592 case LLVMRustLinkage::PrivateLinkage:
1593 return LLVMPrivateLinkage;
1594 case LLVMRustLinkage::ExternalWeakLinkage:
1595 return LLVMExternalWeakLinkage;
1596 case LLVMRustLinkage::CommonLinkage:
1597 return LLVMCommonLinkage;
1599 report_fatal_error("Invalid LLVMRustLinkage value!");
1602 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1603 return toRust(LLVMGetLinkage(V));
1606 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1607 LLVMRustLinkage RustLinkage) {
1608 LLVMSetLinkage(V, fromRust(RustLinkage));
1611 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1612 LLVMValueRef ConstantVal,
1613 LLVMValueRef *ConstantIndices,
1614 unsigned NumIndices) {
1615 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1617 Constant *Val = unwrap<Constant>(ConstantVal);
1618 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1621 extern "C" bool LLVMRustConstIntGetZExtValue(LLVMValueRef CV, uint64_t *value) {
1622 auto C = unwrap<llvm::ConstantInt>(CV);
1623 if (C->getBitWidth() > 64)
1625 *value = C->getZExtValue();
1629 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1630 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1631 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1633 auto C = unwrap<llvm::ConstantInt>(CV);
1634 if (C->getBitWidth() > 128) { return false; }
1636 #if LLVM_VERSION_GE(15, 0)
1638 AP = C->getValue().sext(128);
1640 AP = C->getValue().zext(128);
1644 AP = C->getValue().sextOrSelf(128);
1646 AP = C->getValue().zextOrSelf(128);
1649 *low = AP.getLoBits(64).getZExtValue();
1650 *high = AP.getHiBits(64).getZExtValue();
1654 enum class LLVMRustVisibility {
1660 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1662 case LLVMDefaultVisibility:
1663 return LLVMRustVisibility::Default;
1664 case LLVMHiddenVisibility:
1665 return LLVMRustVisibility::Hidden;
1666 case LLVMProtectedVisibility:
1667 return LLVMRustVisibility::Protected;
1669 report_fatal_error("Invalid LLVMRustVisibility value!");
1672 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1674 case LLVMRustVisibility::Default:
1675 return LLVMDefaultVisibility;
1676 case LLVMRustVisibility::Hidden:
1677 return LLVMHiddenVisibility;
1678 case LLVMRustVisibility::Protected:
1679 return LLVMProtectedVisibility;
1681 report_fatal_error("Invalid LLVMRustVisibility value!");
1684 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1685 return toRust(LLVMGetVisibility(V));
1688 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1689 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1690 LLVMTypeRef DestTy, bool isSigned) {
1691 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1694 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1695 LLVMRustVisibility RustVisibility) {
1696 LLVMSetVisibility(V, fromRust(RustVisibility));
1699 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1700 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1703 struct LLVMRustModuleBuffer {
1707 extern "C" LLVMRustModuleBuffer*
1708 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1709 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1711 raw_string_ostream OS(Ret->data);
1713 legacy::PassManager PM;
1714 PM.add(createBitcodeWriterPass(OS));
1718 return Ret.release();
1722 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1726 extern "C" const void*
1727 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1728 return Buffer->data.data();
1732 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1733 return Buffer->data.length();
1737 LLVMRustModuleCost(LLVMModuleRef M) {
1738 auto f = unwrap(M)->functions();
1739 return std::distance(std::begin(f), std::end(f));
1742 // Vector reductions:
1743 extern "C" LLVMValueRef
1744 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1745 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1747 extern "C" LLVMValueRef
1748 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1749 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1751 extern "C" LLVMValueRef
1752 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1753 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1755 extern "C" LLVMValueRef
1756 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1757 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1759 extern "C" LLVMValueRef
1760 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1761 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1763 extern "C" LLVMValueRef
1764 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1765 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1767 extern "C" LLVMValueRef
1768 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1769 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1771 extern "C" LLVMValueRef
1772 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1773 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1775 extern "C" LLVMValueRef
1776 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1777 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1779 extern "C" LLVMValueRef
1780 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1781 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1782 I->setHasNoNaNs(NoNaN);
1785 extern "C" LLVMValueRef
1786 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1787 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1788 I->setHasNoNaNs(NoNaN);
1792 extern "C" LLVMValueRef
1793 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1794 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1796 extern "C" LLVMValueRef
1797 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1798 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1801 // This struct contains all necessary info about a symbol exported from a DLL.
1802 struct LLVMRustCOFFShortExport {
1804 bool ordinal_present;
1805 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1809 // Machine must be a COFF machine type, as defined in PE specs.
1810 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1811 const char* ImportName,
1813 const LLVMRustCOFFShortExport* Exports,
1818 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1819 ConvertedExports.reserve(NumExports);
1821 for (size_t i = 0; i < NumExports; ++i) {
1822 bool ordinal_present = Exports[i].ordinal_present;
1823 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1824 ConvertedExports.push_back(llvm::object::COFFShortExport{
1825 Exports[i].name, // Name
1826 std::string{}, // ExtName
1827 std::string{}, // SymbolName
1828 std::string{}, // AliasTarget
1830 ordinal_present, // Noname
1837 auto Error = llvm::object::writeImportLibrary(
1841 static_cast<llvm::COFF::MachineTypes>(Machine),
1844 std::string errorString;
1845 llvm::raw_string_ostream stream(errorString);
1848 LLVMRustSetLastError(errorString.c_str());
1849 return LLVMRustResult::Failure;
1851 return LLVMRustResult::Success;
1855 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1856 extern "C" DiagnosticHandler *
1857 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1858 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1859 return DH.release();
1862 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1863 // handling. Ownership of the handler is moved to the LLVMContext.
1864 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1865 DiagnosticHandler *DH) {
1866 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1869 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1871 // Configures a diagnostic handler that invokes provided callback when a
1872 // backend needs to emit a diagnostic.
1874 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1875 // the RemarkPasses array specifies individual passes for which remarks will be
1877 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1878 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1879 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1880 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1882 class RustDiagnosticHandler final : public DiagnosticHandler {
1884 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1885 void *DiagnosticHandlerContext,
1886 bool RemarkAllPasses,
1887 std::vector<std::string> RemarkPasses)
1888 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1889 DiagnosticHandlerContext(DiagnosticHandlerContext),
1890 RemarkAllPasses(RemarkAllPasses),
1891 RemarkPasses(RemarkPasses) {}
1893 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1894 if (DiagnosticHandlerCallback) {
1895 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1901 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1902 return isRemarkEnabled(PassName);
1905 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1906 return isRemarkEnabled(PassName);
1909 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1910 return isRemarkEnabled(PassName);
1913 bool isAnyRemarkEnabled() const override {
1914 return RemarkAllPasses || !RemarkPasses.empty();
1918 bool isRemarkEnabled(StringRef PassName) const {
1919 if (RemarkAllPasses)
1922 for (auto &Pass : RemarkPasses)
1923 if (Pass == PassName)
1929 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1930 void *DiagnosticHandlerContext = nullptr;
1932 bool RemarkAllPasses = false;
1933 std::vector<std::string> RemarkPasses;
1936 std::vector<std::string> Passes;
1937 for (size_t I = 0; I != RemarkPassesLen; ++I)
1938 Passes.push_back(RemarkPasses[I]);
1940 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1941 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
1944 extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
1945 RawRustStringOstream OS(Str);
1946 GlobalValue *GV = unwrap<GlobalValue>(V);
1947 Mangler().getNameWithPrefix(OS, GV, true);
1950 // LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just
1951 // use its implementation.
1952 #if LLVM_VERSION_LT(15, 0)
1953 extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
1954 return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));
1958 extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
1959 #if LLVM_VERSION_GE(15, 0)
1960 auto *CB = unwrap<CallBase>(CallSite);
1961 switch (CB->getIntrinsicID()) {
1962 case Intrinsic::arm_ldrex:
1964 case Intrinsic::arm_strex: