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/Mangler.h"
10 #include "llvm/Object/Archive.h"
11 #include "llvm/Object/COFFImportFile.h"
12 #include "llvm/Object/ObjectFile.h"
13 #include "llvm/Pass.h"
14 #include "llvm/Bitcode/BitcodeWriterPass.h"
15 #include "llvm/Support/Signals.h"
16 #include "llvm/ADT/Optional.h"
20 //===----------------------------------------------------------------------===
22 // This file defines alternate interfaces to core functions that are more
23 // readily callable by Rust's FFI.
25 //===----------------------------------------------------------------------===
28 using namespace llvm::sys;
29 using namespace llvm::object;
31 // LLVMAtomicOrdering is already an enum - don't create another
33 static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
35 case LLVMAtomicOrderingNotAtomic:
36 return AtomicOrdering::NotAtomic;
37 case LLVMAtomicOrderingUnordered:
38 return AtomicOrdering::Unordered;
39 case LLVMAtomicOrderingMonotonic:
40 return AtomicOrdering::Monotonic;
41 case LLVMAtomicOrderingAcquire:
42 return AtomicOrdering::Acquire;
43 case LLVMAtomicOrderingRelease:
44 return AtomicOrdering::Release;
45 case LLVMAtomicOrderingAcquireRelease:
46 return AtomicOrdering::AcquireRelease;
47 case LLVMAtomicOrderingSequentiallyConsistent:
48 return AtomicOrdering::SequentiallyConsistent;
51 report_fatal_error("Invalid LLVMAtomicOrdering value!");
54 static LLVM_THREAD_LOCAL char *LastError;
56 // Custom error handler for fatal LLVM errors.
58 // Notably it exits the process with code 101, unlike LLVM's default of 1.
59 static void FatalErrorHandler(void *UserData,
60 #if LLVM_VERSION_LT(14, 0)
61 const std::string& Reason,
66 // Do the same thing that the default error handler does.
67 std::cerr << "LLVM ERROR: " << Reason << std::endl;
69 // Since this error handler exits the process, we have to run any cleanup that
70 // LLVM would run after handling the error. This might change with an LLVM
72 sys::RunInterruptHandlers();
77 extern "C" void LLVMRustInstallFatalErrorHandler() {
78 install_fatal_error_handler(FatalErrorHandler);
81 extern "C" void LLVMRustDisableSystemDialogsOnCrash() {
82 sys::DisableSystemDialogsOnCrash();
85 extern "C" char *LLVMRustGetLastError(void) {
86 char *Ret = LastError;
91 extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) {
92 return unwrap(M)->getInstructionCount();
95 extern "C" void LLVMRustSetLastError(const char *Err) {
96 free((void *)LastError);
97 LastError = strdup(Err);
100 extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
101 auto ctx = new LLVMContext();
102 ctx->setDiscardValueNames(shouldDiscardNames);
106 extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
107 const char *Triple) {
108 unwrap(M)->setTargetTriple(Triple::normalize(Triple));
111 extern "C" void LLVMRustPrintPassTimings() {
112 raw_fd_ostream OS(2, false); // stderr.
113 TimerGroup::printAll(OS);
116 extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
118 return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
121 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
124 LLVMTypeRef FunctionTy) {
125 return wrap(unwrap(M)
126 ->getOrInsertFunction(StringRef(Name, NameLen),
127 unwrap<FunctionType>(FunctionTy))
132 extern "C" LLVMValueRef
133 LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
134 Module *Mod = unwrap(M);
135 StringRef NameRef(Name, NameLen);
137 // We don't use Module::getOrInsertGlobal because that returns a Constant*,
138 // which may either be the real GlobalVariable*, or a constant bitcast of it
139 // if our type doesn't match the original declaration. We always want the
140 // GlobalVariable* so we can access linkage, visibility, etc.
141 GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true);
143 GV = new GlobalVariable(*Mod, unwrap(Ty), false,
144 GlobalValue::ExternalLinkage, nullptr, NameRef);
148 extern "C" LLVMValueRef
149 LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
150 return wrap(new GlobalVariable(*unwrap(M),
153 GlobalValue::PrivateLinkage,
157 extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
158 return wrap(Type::getMetadataTy(*unwrap(C)));
161 static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
164 return Attribute::AlwaysInline;
166 return Attribute::ByVal;
168 return Attribute::Cold;
170 return Attribute::InlineHint;
172 return Attribute::MinSize;
174 return Attribute::Naked;
176 return Attribute::NoAlias;
178 return Attribute::NoCapture;
180 return Attribute::NoCfCheck;
182 return Attribute::NoInline;
184 return Attribute::NonNull;
186 return Attribute::NoRedZone;
188 return Attribute::NoReturn;
190 return Attribute::NoUnwind;
191 case OptimizeForSize:
192 return Attribute::OptimizeForSize;
194 return Attribute::ReadOnly;
196 return Attribute::SExt;
198 return Attribute::StructRet;
200 return Attribute::UWTable;
202 return Attribute::ZExt;
204 return Attribute::InReg;
206 return Attribute::SanitizeThread;
207 case SanitizeAddress:
208 return Attribute::SanitizeAddress;
210 return Attribute::SanitizeMemory;
212 return Attribute::NonLazyBind;
214 return Attribute::OptimizeNone;
216 return Attribute::ReturnsTwice;
218 return Attribute::ReadNone;
219 case InaccessibleMemOnly:
220 return Attribute::InaccessibleMemOnly;
221 case SanitizeHWAddress:
222 return Attribute::SanitizeHWAddress;
224 return Attribute::WillReturn;
225 case StackProtectReq:
226 return Attribute::StackProtectReq;
227 case StackProtectStrong:
228 return Attribute::StackProtectStrong;
230 return Attribute::StackProtect;
232 return Attribute::NoUndef;
234 return Attribute::SanitizeMemTag;
236 report_fatal_error("bad AttributeKind");
239 template<typename T> static inline void AddAttributes(T *t, unsigned Index,
240 LLVMAttributeRef *Attrs, size_t AttrsLen) {
241 AttributeList PAL = t->getAttributes();
242 AttributeList PALNew;
243 #if LLVM_VERSION_LT(14, 0)
245 for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
246 B.addAttribute(unwrap(Attr));
247 PALNew = PAL.addAttributes(t->getContext(), Index, B);
249 AttrBuilder B(t->getContext());
250 for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
251 B.addAttribute(unwrap(Attr));
252 PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B);
254 t->setAttributes(PALNew);
257 extern "C" void LLVMRustAddFunctionAttributes(LLVMValueRef Fn, unsigned Index,
258 LLVMAttributeRef *Attrs, size_t AttrsLen) {
259 Function *F = unwrap<Function>(Fn);
260 AddAttributes(F, Index, Attrs, AttrsLen);
263 extern "C" void LLVMRustAddCallSiteAttributes(LLVMValueRef Instr, unsigned Index,
264 LLVMAttributeRef *Attrs, size_t AttrsLen) {
265 CallBase *Call = unwrap<CallBase>(Instr);
266 AddAttributes(Call, Index, Attrs, AttrsLen);
269 extern "C" LLVMAttributeRef LLVMRustCreateAttrNoValue(LLVMContextRef C,
270 LLVMRustAttribute RustAttr) {
271 return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr)));
274 extern "C" LLVMAttributeRef LLVMRustCreateAlignmentAttr(LLVMContextRef C,
276 return wrap(Attribute::getWithAlignment(*unwrap(C), llvm::Align(Bytes)));
279 extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableAttr(LLVMContextRef C,
281 return wrap(Attribute::getWithDereferenceableBytes(*unwrap(C), Bytes));
284 extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableOrNullAttr(LLVMContextRef C,
286 return wrap(Attribute::getWithDereferenceableOrNullBytes(*unwrap(C), Bytes));
289 extern "C" LLVMAttributeRef LLVMRustCreateByValAttr(LLVMContextRef C, LLVMTypeRef Ty) {
290 return wrap(Attribute::getWithByValType(*unwrap(C), unwrap(Ty)));
293 extern "C" LLVMAttributeRef LLVMRustCreateStructRetAttr(LLVMContextRef C, LLVMTypeRef Ty) {
294 return wrap(Attribute::getWithStructRetType(*unwrap(C), unwrap(Ty)));
297 extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Async) {
298 #if LLVM_VERSION_LT(15, 0)
299 return wrap(Attribute::get(*unwrap(C), Attribute::UWTable));
301 return wrap(Attribute::getWithUWTableKind(
302 *unwrap(C), Async ? UWTableKind::Async : UWTableKind::Sync));
306 // Enable a fast-math flag
308 // https://llvm.org/docs/LangRef.html#fast-math-flags
309 extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
310 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
315 extern "C" LLVMValueRef
316 LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
317 const char *Name, LLVMAtomicOrdering Order) {
318 Value *Ptr = unwrap(Source);
319 LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
320 LI->setAtomic(fromRust(Order));
324 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
327 LLVMAtomicOrdering Order) {
328 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
329 SI->setAtomic(fromRust(Order));
333 // FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
334 // once we raise our minimum support to LLVM 10.
335 extern "C" LLVMValueRef
336 LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
337 LLVMValueRef Old, LLVMValueRef Source,
338 LLVMAtomicOrdering Order,
339 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
340 #if LLVM_VERSION_GE(13,0)
341 // Rust probably knows the alignment of the target value and should be able to
342 // specify something more precise than MaybeAlign here. See also
343 // https://reviews.llvm.org/D97224 which may be a useful reference.
344 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
345 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
346 fromRust(FailureOrder));
348 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
349 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
350 fromRust(FailureOrder));
356 enum class LLVMRustSynchronizationScope {
361 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
363 case LLVMRustSynchronizationScope::SingleThread:
364 return SyncScope::SingleThread;
365 case LLVMRustSynchronizationScope::CrossThread:
366 return SyncScope::System;
368 report_fatal_error("bad SynchronizationScope.");
372 extern "C" LLVMValueRef
373 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
374 LLVMRustSynchronizationScope Scope) {
375 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
378 enum class LLVMRustAsmDialect {
383 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
385 case LLVMRustAsmDialect::Att:
386 return InlineAsm::AD_ATT;
387 case LLVMRustAsmDialect::Intel:
388 return InlineAsm::AD_Intel;
390 report_fatal_error("bad AsmDialect.");
394 extern "C" LLVMValueRef
395 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
396 char *Constraints, size_t ConstraintsLen,
397 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
398 LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
399 #if LLVM_VERSION_GE(13, 0)
400 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
401 StringRef(AsmString, AsmStringLen),
402 StringRef(Constraints, ConstraintsLen),
403 HasSideEffects, IsAlignStack,
404 fromRust(Dialect), CanThrow));
406 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
407 StringRef(AsmString, AsmStringLen),
408 StringRef(Constraints, ConstraintsLen),
409 HasSideEffects, IsAlignStack,
414 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
415 size_t ConstraintsLen) {
416 #if LLVM_VERSION_LT(15, 0)
417 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
418 StringRef(Constraints, ConstraintsLen));
420 // llvm::Error converts to true if it is an error.
421 return !llvm::errorToBool(InlineAsm::verify(
422 unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen)));
426 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
428 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
431 typedef DIBuilder *LLVMRustDIBuilderRef;
433 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
434 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
437 #define DIDescriptor DIScope
438 #define DIArray DINodeArray
439 #define unwrapDI unwrapDIPtr
441 // These values **must** match debuginfo::DIFlags! They also *happen*
442 // to match LLVM, but that isn't required as we do giant sets of
443 // matching below. The value shouldn't be directly passed to LLVM.
444 enum class LLVMRustDIFlags : uint32_t {
449 FlagFwdDecl = (1 << 2),
450 FlagAppleBlock = (1 << 3),
451 FlagBlockByrefStruct = (1 << 4),
452 FlagVirtual = (1 << 5),
453 FlagArtificial = (1 << 6),
454 FlagExplicit = (1 << 7),
455 FlagPrototyped = (1 << 8),
456 FlagObjcClassComplete = (1 << 9),
457 FlagObjectPointer = (1 << 10),
458 FlagVector = (1 << 11),
459 FlagStaticMember = (1 << 12),
460 FlagLValueReference = (1 << 13),
461 FlagRValueReference = (1 << 14),
462 FlagExternalTypeRef = (1 << 15),
463 FlagIntroducedVirtual = (1 << 18),
464 FlagBitField = (1 << 19),
465 FlagNoReturn = (1 << 20),
466 // Do not add values that are not supported by the minimum LLVM
467 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
470 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
471 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
472 static_cast<uint32_t>(B));
475 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
476 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
477 static_cast<uint32_t>(B));
480 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
484 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
486 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
487 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
490 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
491 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
493 switch (visibility(Flags)) {
494 case LLVMRustDIFlags::FlagPrivate:
495 Result |= DINode::DIFlags::FlagPrivate;
497 case LLVMRustDIFlags::FlagProtected:
498 Result |= DINode::DIFlags::FlagProtected;
500 case LLVMRustDIFlags::FlagPublic:
501 Result |= DINode::DIFlags::FlagPublic;
504 // The rest are handled below
508 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
509 Result |= DINode::DIFlags::FlagFwdDecl;
511 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
512 Result |= DINode::DIFlags::FlagAppleBlock;
514 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
515 Result |= DINode::DIFlags::FlagVirtual;
517 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
518 Result |= DINode::DIFlags::FlagArtificial;
520 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
521 Result |= DINode::DIFlags::FlagExplicit;
523 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
524 Result |= DINode::DIFlags::FlagPrototyped;
526 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
527 Result |= DINode::DIFlags::FlagObjcClassComplete;
529 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
530 Result |= DINode::DIFlags::FlagObjectPointer;
532 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
533 Result |= DINode::DIFlags::FlagVector;
535 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
536 Result |= DINode::DIFlags::FlagStaticMember;
538 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
539 Result |= DINode::DIFlags::FlagLValueReference;
541 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
542 Result |= DINode::DIFlags::FlagRValueReference;
544 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
545 Result |= DINode::DIFlags::FlagIntroducedVirtual;
547 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
548 Result |= DINode::DIFlags::FlagBitField;
550 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
551 Result |= DINode::DIFlags::FlagNoReturn;
557 // These values **must** match debuginfo::DISPFlags! They also *happen*
558 // to match LLVM, but that isn't required as we do giant sets of
559 // matching below. The value shouldn't be directly passed to LLVM.
560 enum class LLVMRustDISPFlags : uint32_t {
563 SPFlagPureVirtual = 2,
564 SPFlagLocalToUnit = (1 << 2),
565 SPFlagDefinition = (1 << 3),
566 SPFlagOptimized = (1 << 4),
567 SPFlagMainSubprogram = (1 << 5),
568 // Do not add values that are not supported by the minimum LLVM
569 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
570 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
573 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
574 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
575 static_cast<uint32_t>(B));
578 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
579 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
580 static_cast<uint32_t>(B));
583 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
587 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
589 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
590 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
593 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
594 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
596 switch (virtuality(SPFlags)) {
597 case LLVMRustDISPFlags::SPFlagVirtual:
598 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
600 case LLVMRustDISPFlags::SPFlagPureVirtual:
601 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
604 // The rest are handled below
608 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
609 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
611 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
612 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
614 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
615 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
617 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
618 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
624 enum class LLVMRustDebugEmissionKind {
630 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
632 case LLVMRustDebugEmissionKind::NoDebug:
633 return DICompileUnit::DebugEmissionKind::NoDebug;
634 case LLVMRustDebugEmissionKind::FullDebug:
635 return DICompileUnit::DebugEmissionKind::FullDebug;
636 case LLVMRustDebugEmissionKind::LineTablesOnly:
637 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
639 report_fatal_error("bad DebugEmissionKind.");
643 enum class LLVMRustChecksumKind {
650 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
652 case LLVMRustChecksumKind::None:
654 case LLVMRustChecksumKind::MD5:
655 return DIFile::ChecksumKind::CSK_MD5;
656 case LLVMRustChecksumKind::SHA1:
657 return DIFile::ChecksumKind::CSK_SHA1;
658 case LLVMRustChecksumKind::SHA256:
659 return DIFile::ChecksumKind::CSK_SHA256;
661 report_fatal_error("bad ChecksumKind.");
665 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
666 return DEBUG_METADATA_VERSION;
669 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
671 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
673 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
675 extern "C" void LLVMRustAddModuleFlag(
677 Module::ModFlagBehavior MergeBehavior,
680 unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
683 extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
685 return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
688 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
689 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
692 extern "C" void LLVMRustGlobalAddMetadata(
693 LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) {
694 unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
697 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
698 return new DIBuilder(*unwrap(M));
701 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
705 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
709 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
710 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
711 const char *Producer, size_t ProducerLen, bool isOptimized,
712 const char *Flags, unsigned RuntimeVer,
713 const char *SplitName, size_t SplitNameLen,
714 LLVMRustDebugEmissionKind Kind,
715 uint64_t DWOId, bool SplitDebugInlining) {
716 auto *File = unwrapDI<DIFile>(FileRef);
718 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
719 isOptimized, Flags, RuntimeVer,
720 StringRef(SplitName, SplitNameLen),
721 fromRust(Kind), DWOId, SplitDebugInlining));
724 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
725 LLVMRustDIBuilderRef Builder,
726 const char *Filename, size_t FilenameLen,
727 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
728 const char *Checksum, size_t ChecksumLen) {
729 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
730 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
732 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
733 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
734 StringRef(Directory, DirectoryLen),
738 extern "C" LLVMMetadataRef
739 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
740 LLVMMetadataRef ParameterTypes) {
741 return wrap(Builder->createSubroutineType(
742 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
745 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
746 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
747 const char *Name, size_t NameLen,
748 const char *LinkageName, size_t LinkageNameLen,
749 LLVMMetadataRef File, unsigned LineNo,
750 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
751 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
752 LLVMMetadataRef Decl) {
753 DITemplateParameterArray TParams =
754 DITemplateParameterArray(unwrap<MDTuple>(TParam));
755 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
756 DINode::DIFlags llvmFlags = fromRust(Flags);
757 DISubprogram *Sub = Builder->createFunction(
758 unwrapDI<DIScope>(Scope),
759 StringRef(Name, NameLen),
760 StringRef(LinkageName, LinkageNameLen),
761 unwrapDI<DIFile>(File), LineNo,
762 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
763 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
765 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
769 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
770 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
771 uint64_t SizeInBits, unsigned Encoding) {
772 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
775 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
776 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
777 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
778 return wrap(Builder->createTypedef(
779 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
780 LineNo, unwrapDIPtr<DIScope>(Scope)));
783 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
784 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
785 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
786 const char *Name, size_t NameLen) {
787 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
788 SizeInBits, AlignInBits,
790 StringRef(Name, NameLen)));
793 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
794 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
795 const char *Name, size_t NameLen,
796 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
797 uint32_t AlignInBits, LLVMRustDIFlags Flags,
798 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
799 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
800 const char *UniqueId, size_t UniqueIdLen) {
801 return wrap(Builder->createStructType(
802 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
803 unwrapDI<DIFile>(File), LineNumber,
804 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
805 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
806 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
809 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
810 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
811 const char *Name, size_t NameLen,
812 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
813 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
814 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
815 return wrap(Builder->createVariantPart(
816 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
817 unwrapDI<DIFile>(File), LineNumber,
818 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
819 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
822 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
823 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
824 const char *Name, size_t NameLen,
825 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
826 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
827 LLVMMetadataRef Ty) {
828 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
829 StringRef(Name, NameLen),
830 unwrapDI<DIFile>(File), LineNo,
831 SizeInBits, AlignInBits, OffsetInBits,
832 fromRust(Flags), unwrapDI<DIType>(Ty)));
835 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
836 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
837 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
838 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
839 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
840 llvm::ConstantInt* D = nullptr;
842 D = unwrap<llvm::ConstantInt>(Discriminant);
844 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
845 StringRef(Name, NameLen),
846 unwrapDI<DIFile>(File), LineNo,
847 SizeInBits, AlignInBits, OffsetInBits, D,
848 fromRust(Flags), unwrapDI<DIType>(Ty)));
851 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
852 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
853 LLVMMetadataRef File, unsigned Line, unsigned Col) {
854 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
855 unwrapDI<DIFile>(File), Line, Col));
858 extern "C" LLVMMetadataRef
859 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
860 LLVMMetadataRef Scope,
861 LLVMMetadataRef File) {
862 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
863 unwrapDI<DIFile>(File)));
866 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
867 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
868 const char *Name, size_t NameLen,
869 const char *LinkageName, size_t LinkageNameLen,
870 LLVMMetadataRef File, unsigned LineNo,
871 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
872 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
873 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
875 llvm::DIExpression *InitExpr = nullptr;
876 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
877 InitExpr = Builder->createConstantValueExpression(
878 IntVal->getValue().getSExtValue());
879 } else if (llvm::ConstantFP *FPVal =
880 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
881 InitExpr = Builder->createConstantValueExpression(
882 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
885 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
886 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
887 StringRef(LinkageName, LinkageNameLen),
888 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
889 /* isDefined */ true,
890 InitExpr, unwrapDIPtr<MDNode>(Decl),
891 /* templateParams */ nullptr,
894 InitVal->setMetadata("dbg", VarExpr);
896 return wrap(VarExpr);
899 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
900 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
901 const char *Name, size_t NameLen,
902 LLVMMetadataRef File, unsigned LineNo,
903 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
904 unsigned ArgNo, uint32_t AlignInBits) {
905 if (Tag == 0x100) { // DW_TAG_auto_variable
906 return wrap(Builder->createAutoVariable(
907 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
908 unwrapDI<DIFile>(File), LineNo,
909 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
911 return wrap(Builder->createParameterVariable(
912 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
913 unwrapDI<DIFile>(File), LineNo,
914 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
918 extern "C" LLVMMetadataRef
919 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
920 uint32_t AlignInBits, LLVMMetadataRef Ty,
921 LLVMMetadataRef Subscripts) {
923 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
924 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
927 extern "C" LLVMMetadataRef
928 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
930 return wrap(Builder->getOrCreateSubrange(Lo, Count));
933 extern "C" LLVMMetadataRef
934 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
935 LLVMMetadataRef *Ptr, unsigned Count) {
936 Metadata **DataValue = unwrap(Ptr);
938 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
941 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
942 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
943 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
944 LLVMBasicBlockRef InsertAtEnd) {
945 return wrap(Builder->insertDeclare(
946 unwrap(V), unwrap<DILocalVariable>(VarInfo),
947 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
948 DebugLoc(cast<MDNode>(unwrap(DL))),
949 unwrap(InsertAtEnd)));
952 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
953 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
954 int64_t Value, bool IsUnsigned) {
955 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
958 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
959 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
960 const char *Name, size_t NameLen,
961 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
962 uint32_t AlignInBits, LLVMMetadataRef Elements,
963 LLVMMetadataRef ClassTy, bool IsScoped) {
964 return wrap(Builder->createEnumerationType(
965 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
966 unwrapDI<DIFile>(File), LineNumber,
967 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
968 unwrapDI<DIType>(ClassTy), "", IsScoped));
971 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
972 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
973 const char *Name, size_t NameLen,
974 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
975 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
976 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
977 return wrap(Builder->createUnionType(
978 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
979 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
980 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
981 StringRef(UniqueId, UniqueIdLen)));
984 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
985 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
986 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
987 bool IsDefault = false; // FIXME: should we ever set this true?
988 return wrap(Builder->createTemplateTypeParameter(
989 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
992 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
993 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
994 const char *Name, size_t NameLen, bool ExportSymbols) {
995 return wrap(Builder->createNameSpace(
996 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1001 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1002 LLVMMetadataRef CompositeTy,
1003 LLVMMetadataRef Elements,
1004 LLVMMetadataRef Params) {
1005 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1006 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1007 DINodeArray(unwrap<MDTuple>(Params)));
1010 extern "C" LLVMMetadataRef
1011 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1012 LLVMMetadataRef ScopeRef,
1013 LLVMMetadataRef InlinedAt) {
1014 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1015 DILocation *Loc = DILocation::get(
1016 Scope->getContext(), Line, Column, Scope,
1017 unwrapDIPtr<MDNode>(InlinedAt));
1021 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1022 return dwarf::DW_OP_deref;
1025 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1026 return dwarf::DW_OP_plus_uconst;
1029 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1030 RawRustStringOstream OS(Str);
1031 unwrap<llvm::Type>(Ty)->print(OS);
1034 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1035 RustStringRef Str) {
1036 RawRustStringOstream OS(Str);
1041 unwrap<llvm::Value>(V)->getType()->print(OS);
1043 unwrap<llvm::Value>(V)->print(OS);
1048 // LLVMArrayType function does not support 64-bit ElementCount
1049 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1050 uint64_t ElementCount) {
1051 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1054 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1056 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1057 RawRustStringOstream OS(Str);
1058 unwrap(T)->print(OS);
1061 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1062 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1063 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1064 RustStringRef FilenameOut, RustStringRef MessageOut) {
1065 // Undefined to call this not on an optimization diagnostic!
1066 llvm::DiagnosticInfoOptimizationBase *Opt =
1067 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1069 RawRustStringOstream PassNameOS(PassNameOut);
1070 PassNameOS << Opt->getPassName();
1071 *FunctionOut = wrap(&Opt->getFunction());
1073 RawRustStringOstream FilenameOS(FilenameOut);
1074 DiagnosticLocation loc = Opt->getLocation();
1075 if (loc.isValid()) {
1076 *Line = loc.getLine();
1077 *Column = loc.getColumn();
1078 FilenameOS << loc.getAbsolutePath();
1081 RawRustStringOstream MessageOS(MessageOut);
1082 MessageOS << Opt->getMsg();
1085 enum class LLVMRustDiagnosticLevel {
1093 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1094 LLVMRustDiagnosticLevel *LevelOut,
1095 unsigned *CookieOut,
1096 LLVMTwineRef *MessageOut) {
1097 // Undefined to call this not on an inline assembly diagnostic!
1098 llvm::DiagnosticInfoInlineAsm *IA =
1099 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1101 *CookieOut = IA->getLocCookie();
1102 *MessageOut = wrap(&IA->getMsgStr());
1104 switch (IA->getSeverity()) {
1106 *LevelOut = LLVMRustDiagnosticLevel::Error;
1109 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1112 *LevelOut = LLVMRustDiagnosticLevel::Note;
1115 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1118 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1122 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1123 RustStringRef Str) {
1124 RawRustStringOstream OS(Str);
1125 DiagnosticPrinterRawOStream DP(OS);
1126 unwrap(DI)->print(DP);
1129 enum class LLVMRustDiagnosticKind {
1133 DebugMetadataVersion,
1136 OptimizationRemarkMissed,
1137 OptimizationRemarkAnalysis,
1138 OptimizationRemarkAnalysisFPCommute,
1139 OptimizationRemarkAnalysisAliasing,
1140 OptimizationRemarkOther,
1141 OptimizationFailure,
1148 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1151 return LLVMRustDiagnosticKind::InlineAsm;
1153 return LLVMRustDiagnosticKind::StackSize;
1154 case DK_DebugMetadataVersion:
1155 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1156 case DK_SampleProfile:
1157 return LLVMRustDiagnosticKind::SampleProfile;
1158 case DK_OptimizationRemark:
1159 case DK_MachineOptimizationRemark:
1160 return LLVMRustDiagnosticKind::OptimizationRemark;
1161 case DK_OptimizationRemarkMissed:
1162 case DK_MachineOptimizationRemarkMissed:
1163 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1164 case DK_OptimizationRemarkAnalysis:
1165 case DK_MachineOptimizationRemarkAnalysis:
1166 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1167 case DK_OptimizationRemarkAnalysisFPCommute:
1168 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1169 case DK_OptimizationRemarkAnalysisAliasing:
1170 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1172 return LLVMRustDiagnosticKind::PGOProfile;
1174 return LLVMRustDiagnosticKind::Linker;
1175 case DK_Unsupported:
1176 return LLVMRustDiagnosticKind::Unsupported;
1177 #if LLVM_VERSION_GE(13, 0)
1179 return LLVMRustDiagnosticKind::SrcMgr;
1182 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1183 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1184 : LLVMRustDiagnosticKind::Other;
1188 extern "C" LLVMRustDiagnosticKind
1189 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1190 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1193 // This is kept distinct from LLVMGetTypeKind, because when
1194 // a new type kind is added, the Rust-side enum must be
1195 // updated or UB will result.
1196 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1197 switch (unwrap(Ty)->getTypeID()) {
1198 case Type::VoidTyID:
1199 return LLVMVoidTypeKind;
1200 case Type::HalfTyID:
1201 return LLVMHalfTypeKind;
1202 case Type::FloatTyID:
1203 return LLVMFloatTypeKind;
1204 case Type::DoubleTyID:
1205 return LLVMDoubleTypeKind;
1206 case Type::X86_FP80TyID:
1207 return LLVMX86_FP80TypeKind;
1208 case Type::FP128TyID:
1209 return LLVMFP128TypeKind;
1210 case Type::PPC_FP128TyID:
1211 return LLVMPPC_FP128TypeKind;
1212 case Type::LabelTyID:
1213 return LLVMLabelTypeKind;
1214 case Type::MetadataTyID:
1215 return LLVMMetadataTypeKind;
1216 case Type::IntegerTyID:
1217 return LLVMIntegerTypeKind;
1218 case Type::FunctionTyID:
1219 return LLVMFunctionTypeKind;
1220 case Type::StructTyID:
1221 return LLVMStructTypeKind;
1222 case Type::ArrayTyID:
1223 return LLVMArrayTypeKind;
1224 case Type::PointerTyID:
1225 return LLVMPointerTypeKind;
1226 case Type::FixedVectorTyID:
1227 return LLVMVectorTypeKind;
1228 case Type::X86_MMXTyID:
1229 return LLVMX86_MMXTypeKind;
1230 case Type::TokenTyID:
1231 return LLVMTokenTypeKind;
1232 case Type::ScalableVectorTyID:
1233 return LLVMScalableVectorTypeKind;
1234 case Type::BFloatTyID:
1235 return LLVMBFloatTypeKind;
1236 case Type::X86_AMXTyID:
1237 return LLVMX86_AMXTypeKind;
1238 #if LLVM_VERSION_GE(15, 0)
1239 case Type::DXILPointerTyID:
1240 report_fatal_error("Rust does not support DirectX typed pointers.");
1244 report_fatal_error("Unhandled TypeID.");
1247 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1249 #if LLVM_VERSION_LT(13, 0)
1250 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1252 using LLVMInlineAsmDiagHandlerTy = void*;
1255 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1256 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1257 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1258 // with LLVM 13 this function is gone.
1259 #if LLVM_VERSION_LT(13, 0)
1260 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1264 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1265 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1266 #if LLVM_VERSION_GE(13, 0)
1267 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1268 *Cookie = SM->getLocCookie();
1269 return wrap(&SM->getSMDiag());
1271 report_fatal_error("Shouldn't get called on older versions");
1275 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1276 RustStringRef MessageOut,
1277 RustStringRef BufferOut,
1278 LLVMRustDiagnosticLevel* LevelOut,
1280 unsigned* RangesOut,
1281 size_t* NumRanges) {
1282 SMDiagnostic& D = *unwrap(DRef);
1283 RawRustStringOstream MessageOS(MessageOut);
1284 MessageOS << D.getMessage();
1286 switch (D.getKind()) {
1287 case SourceMgr::DK_Error:
1288 *LevelOut = LLVMRustDiagnosticLevel::Error;
1290 case SourceMgr::DK_Warning:
1291 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1293 case SourceMgr::DK_Note:
1294 *LevelOut = LLVMRustDiagnosticLevel::Note;
1296 case SourceMgr::DK_Remark:
1297 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1300 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1303 if (D.getLoc() == SMLoc())
1306 const SourceMgr &LSM = *D.getSourceMgr();
1307 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1308 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1310 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1312 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1313 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1314 for (size_t i = 0; i < *NumRanges; i++) {
1315 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1316 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1322 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1323 LLVMValueRef ParentPad,
1325 LLVMValueRef *LLArgs,
1327 Value **Args = unwrap(LLArgs);
1328 if (ParentPad == nullptr) {
1329 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1330 ParentPad = wrap(Constant::getNullValue(Ty));
1332 return wrap(unwrap(B)->CreateCleanupPad(
1333 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1336 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1337 LLVMValueRef CleanupPad,
1338 LLVMBasicBlockRef UnwindBB) {
1339 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1340 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1343 extern "C" LLVMValueRef
1344 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1345 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1346 Value **Args = unwrap(LLArgs);
1347 return wrap(unwrap(B)->CreateCatchPad(
1348 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1351 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1353 LLVMBasicBlockRef BB) {
1354 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1358 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1359 LLVMValueRef ParentPad,
1360 LLVMBasicBlockRef BB,
1361 unsigned NumHandlers,
1363 if (ParentPad == nullptr) {
1364 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1365 ParentPad = wrap(Constant::getNullValue(Ty));
1367 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1368 NumHandlers, Name));
1371 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1372 LLVMBasicBlockRef Handler) {
1373 Value *CatchSwitch = unwrap(CatchSwitchRef);
1374 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1377 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1378 LLVMValueRef *Inputs,
1379 unsigned NumInputs) {
1380 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1383 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1387 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1388 LLVMValueRef *Args, unsigned NumArgs,
1389 OperandBundleDef *Bundle) {
1390 Value *Callee = unwrap(Fn);
1391 FunctionType *FTy = unwrap<FunctionType>(Ty);
1392 unsigned Len = Bundle ? 1 : 0;
1393 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1394 return wrap(unwrap(B)->CreateCall(
1395 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1398 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1399 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1400 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1403 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1404 LLVMValueRef Dst, unsigned DstAlign,
1405 LLVMValueRef Src, unsigned SrcAlign,
1406 LLVMValueRef Size, bool IsVolatile) {
1407 return wrap(unwrap(B)->CreateMemCpy(
1408 unwrap(Dst), MaybeAlign(DstAlign),
1409 unwrap(Src), MaybeAlign(SrcAlign),
1410 unwrap(Size), IsVolatile));
1413 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1414 LLVMValueRef Dst, unsigned DstAlign,
1415 LLVMValueRef Src, unsigned SrcAlign,
1416 LLVMValueRef Size, bool IsVolatile) {
1417 return wrap(unwrap(B)->CreateMemMove(
1418 unwrap(Dst), MaybeAlign(DstAlign),
1419 unwrap(Src), MaybeAlign(SrcAlign),
1420 unwrap(Size), IsVolatile));
1423 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1424 LLVMValueRef Dst, unsigned DstAlign,
1426 LLVMValueRef Size, bool IsVolatile) {
1427 return wrap(unwrap(B)->CreateMemSet(
1428 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1431 extern "C" LLVMValueRef
1432 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1433 LLVMValueRef *Args, unsigned NumArgs,
1434 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1435 OperandBundleDef *Bundle, const char *Name) {
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)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1441 makeArrayRef(unwrap(Args), NumArgs),
1445 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1446 LLVMBasicBlockRef BB) {
1447 auto Point = unwrap(BB)->getFirstInsertionPt();
1448 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1451 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1452 const char *Name, size_t NameLen) {
1453 Triple TargetTriple(unwrap(M)->getTargetTriple());
1454 GlobalObject *GV = unwrap<GlobalObject>(V);
1455 if (TargetTriple.supportsCOMDAT()) {
1456 StringRef NameRef(Name, NameLen);
1457 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1461 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1462 GlobalObject *GV = unwrap<GlobalObject>(V);
1463 GV->setComdat(nullptr);
1466 enum class LLVMRustLinkage {
1467 ExternalLinkage = 0,
1468 AvailableExternallyLinkage = 1,
1469 LinkOnceAnyLinkage = 2,
1470 LinkOnceODRLinkage = 3,
1473 AppendingLinkage = 6,
1474 InternalLinkage = 7,
1476 ExternalWeakLinkage = 9,
1480 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1482 case LLVMExternalLinkage:
1483 return LLVMRustLinkage::ExternalLinkage;
1484 case LLVMAvailableExternallyLinkage:
1485 return LLVMRustLinkage::AvailableExternallyLinkage;
1486 case LLVMLinkOnceAnyLinkage:
1487 return LLVMRustLinkage::LinkOnceAnyLinkage;
1488 case LLVMLinkOnceODRLinkage:
1489 return LLVMRustLinkage::LinkOnceODRLinkage;
1490 case LLVMWeakAnyLinkage:
1491 return LLVMRustLinkage::WeakAnyLinkage;
1492 case LLVMWeakODRLinkage:
1493 return LLVMRustLinkage::WeakODRLinkage;
1494 case LLVMAppendingLinkage:
1495 return LLVMRustLinkage::AppendingLinkage;
1496 case LLVMInternalLinkage:
1497 return LLVMRustLinkage::InternalLinkage;
1498 case LLVMPrivateLinkage:
1499 return LLVMRustLinkage::PrivateLinkage;
1500 case LLVMExternalWeakLinkage:
1501 return LLVMRustLinkage::ExternalWeakLinkage;
1502 case LLVMCommonLinkage:
1503 return LLVMRustLinkage::CommonLinkage;
1505 report_fatal_error("Invalid LLVMRustLinkage value!");
1509 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1511 case LLVMRustLinkage::ExternalLinkage:
1512 return LLVMExternalLinkage;
1513 case LLVMRustLinkage::AvailableExternallyLinkage:
1514 return LLVMAvailableExternallyLinkage;
1515 case LLVMRustLinkage::LinkOnceAnyLinkage:
1516 return LLVMLinkOnceAnyLinkage;
1517 case LLVMRustLinkage::LinkOnceODRLinkage:
1518 return LLVMLinkOnceODRLinkage;
1519 case LLVMRustLinkage::WeakAnyLinkage:
1520 return LLVMWeakAnyLinkage;
1521 case LLVMRustLinkage::WeakODRLinkage:
1522 return LLVMWeakODRLinkage;
1523 case LLVMRustLinkage::AppendingLinkage:
1524 return LLVMAppendingLinkage;
1525 case LLVMRustLinkage::InternalLinkage:
1526 return LLVMInternalLinkage;
1527 case LLVMRustLinkage::PrivateLinkage:
1528 return LLVMPrivateLinkage;
1529 case LLVMRustLinkage::ExternalWeakLinkage:
1530 return LLVMExternalWeakLinkage;
1531 case LLVMRustLinkage::CommonLinkage:
1532 return LLVMCommonLinkage;
1534 report_fatal_error("Invalid LLVMRustLinkage value!");
1537 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1538 return toRust(LLVMGetLinkage(V));
1541 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1542 LLVMRustLinkage RustLinkage) {
1543 LLVMSetLinkage(V, fromRust(RustLinkage));
1546 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1547 LLVMValueRef ConstantVal,
1548 LLVMValueRef *ConstantIndices,
1549 unsigned NumIndices) {
1550 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1552 Constant *Val = unwrap<Constant>(ConstantVal);
1553 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1556 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1557 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1558 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1560 auto C = unwrap<llvm::ConstantInt>(CV);
1561 if (C->getBitWidth() > 128) { return false; }
1563 #if LLVM_VERSION_GE(15, 0)
1565 AP = C->getValue().sext(128);
1567 AP = C->getValue().zext(128);
1571 AP = C->getValue().sextOrSelf(128);
1573 AP = C->getValue().zextOrSelf(128);
1576 *low = AP.getLoBits(64).getZExtValue();
1577 *high = AP.getHiBits(64).getZExtValue();
1581 enum class LLVMRustVisibility {
1587 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1589 case LLVMDefaultVisibility:
1590 return LLVMRustVisibility::Default;
1591 case LLVMHiddenVisibility:
1592 return LLVMRustVisibility::Hidden;
1593 case LLVMProtectedVisibility:
1594 return LLVMRustVisibility::Protected;
1596 report_fatal_error("Invalid LLVMRustVisibility value!");
1599 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1601 case LLVMRustVisibility::Default:
1602 return LLVMDefaultVisibility;
1603 case LLVMRustVisibility::Hidden:
1604 return LLVMHiddenVisibility;
1605 case LLVMRustVisibility::Protected:
1606 return LLVMProtectedVisibility;
1608 report_fatal_error("Invalid LLVMRustVisibility value!");
1611 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1612 return toRust(LLVMGetVisibility(V));
1615 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1616 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1617 LLVMTypeRef DestTy, bool isSigned) {
1618 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1621 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1622 LLVMRustVisibility RustVisibility) {
1623 LLVMSetVisibility(V, fromRust(RustVisibility));
1626 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1627 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1630 struct LLVMRustModuleBuffer {
1634 extern "C" LLVMRustModuleBuffer*
1635 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1636 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1638 raw_string_ostream OS(Ret->data);
1640 legacy::PassManager PM;
1641 PM.add(createBitcodeWriterPass(OS));
1645 return Ret.release();
1649 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1653 extern "C" const void*
1654 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1655 return Buffer->data.data();
1659 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1660 return Buffer->data.length();
1664 LLVMRustModuleCost(LLVMModuleRef M) {
1665 auto f = unwrap(M)->functions();
1666 return std::distance(std::begin(f), std::end(f));
1669 // Vector reductions:
1670 extern "C" LLVMValueRef
1671 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1672 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1674 extern "C" LLVMValueRef
1675 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1676 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1678 extern "C" LLVMValueRef
1679 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1680 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1682 extern "C" LLVMValueRef
1683 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1684 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1686 extern "C" LLVMValueRef
1687 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1688 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1690 extern "C" LLVMValueRef
1691 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1692 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1694 extern "C" LLVMValueRef
1695 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1696 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1698 extern "C" LLVMValueRef
1699 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1700 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1702 extern "C" LLVMValueRef
1703 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1704 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1706 extern "C" LLVMValueRef
1707 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1708 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1709 I->setHasNoNaNs(NoNaN);
1712 extern "C" LLVMValueRef
1713 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1714 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1715 I->setHasNoNaNs(NoNaN);
1719 extern "C" LLVMValueRef
1720 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1721 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1723 extern "C" LLVMValueRef
1724 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1725 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1728 // This struct contains all necessary info about a symbol exported from a DLL.
1729 struct LLVMRustCOFFShortExport {
1731 bool ordinal_present;
1732 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1736 // Machine must be a COFF machine type, as defined in PE specs.
1737 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1738 const char* ImportName,
1740 const LLVMRustCOFFShortExport* Exports,
1745 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1746 ConvertedExports.reserve(NumExports);
1748 for (size_t i = 0; i < NumExports; ++i) {
1749 bool ordinal_present = Exports[i].ordinal_present;
1750 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1751 ConvertedExports.push_back(llvm::object::COFFShortExport{
1752 Exports[i].name, // Name
1753 std::string{}, // ExtName
1754 std::string{}, // SymbolName
1755 std::string{}, // AliasTarget
1757 ordinal_present, // Noname
1764 auto Error = llvm::object::writeImportLibrary(
1768 static_cast<llvm::COFF::MachineTypes>(Machine),
1771 std::string errorString;
1772 llvm::raw_string_ostream stream(errorString);
1775 LLVMRustSetLastError(errorString.c_str());
1776 return LLVMRustResult::Failure;
1778 return LLVMRustResult::Success;
1782 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1783 extern "C" DiagnosticHandler *
1784 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1785 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1786 return DH.release();
1789 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1790 // handling. Ownership of the handler is moved to the LLVMContext.
1791 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1792 DiagnosticHandler *DH) {
1793 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1796 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1798 // Configures a diagnostic handler that invokes provided callback when a
1799 // backend needs to emit a diagnostic.
1801 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1802 // the RemarkPasses array specifies individual passes for which remarks will be
1804 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1805 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1806 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1807 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1809 class RustDiagnosticHandler final : public DiagnosticHandler {
1811 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1812 void *DiagnosticHandlerContext,
1813 bool RemarkAllPasses,
1814 std::vector<std::string> RemarkPasses)
1815 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1816 DiagnosticHandlerContext(DiagnosticHandlerContext),
1817 RemarkAllPasses(RemarkAllPasses),
1818 RemarkPasses(RemarkPasses) {}
1820 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1821 if (DiagnosticHandlerCallback) {
1822 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1828 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1829 return isRemarkEnabled(PassName);
1832 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1833 return isRemarkEnabled(PassName);
1836 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1837 return isRemarkEnabled(PassName);
1840 bool isAnyRemarkEnabled() const override {
1841 return RemarkAllPasses || !RemarkPasses.empty();
1845 bool isRemarkEnabled(StringRef PassName) const {
1846 if (RemarkAllPasses)
1849 for (auto &Pass : RemarkPasses)
1850 if (Pass == PassName)
1856 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1857 void *DiagnosticHandlerContext = nullptr;
1859 bool RemarkAllPasses = false;
1860 std::vector<std::string> RemarkPasses;
1863 std::vector<std::string> Passes;
1864 for (size_t I = 0; I != RemarkPassesLen; ++I)
1865 Passes.push_back(RemarkPasses[I]);
1867 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1868 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
1871 extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
1872 RawRustStringOstream OS(Str);
1873 GlobalValue *GV = unwrap<GlobalValue>(V);
1874 Mangler().getNameWithPrefix(OS, GV, true);
1877 // LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just
1878 // use its implementation.
1879 #if LLVM_VERSION_LT(15, 0)
1880 extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
1881 return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));