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::NoInline;
182 return Attribute::NonNull;
184 return Attribute::NoRedZone;
186 return Attribute::NoReturn;
188 return Attribute::NoUnwind;
189 case OptimizeForSize:
190 return Attribute::OptimizeForSize;
192 return Attribute::ReadOnly;
194 return Attribute::SExt;
196 return Attribute::StructRet;
198 return Attribute::UWTable;
200 return Attribute::ZExt;
202 return Attribute::InReg;
204 return Attribute::SanitizeThread;
205 case SanitizeAddress:
206 return Attribute::SanitizeAddress;
208 return Attribute::SanitizeMemory;
210 return Attribute::NonLazyBind;
212 return Attribute::OptimizeNone;
214 return Attribute::ReturnsTwice;
216 return Attribute::ReadNone;
217 case InaccessibleMemOnly:
218 return Attribute::InaccessibleMemOnly;
219 case SanitizeHWAddress:
220 return Attribute::SanitizeHWAddress;
222 return Attribute::WillReturn;
223 case StackProtectReq:
224 return Attribute::StackProtectReq;
225 case StackProtectStrong:
226 return Attribute::StackProtectStrong;
228 return Attribute::StackProtect;
230 return Attribute::NoUndef;
232 return Attribute::SanitizeMemTag;
234 report_fatal_error("bad AttributeKind");
237 template<typename T> static inline void AddAttributes(T *t, unsigned Index,
238 LLVMAttributeRef *Attrs, size_t AttrsLen) {
239 AttributeList PAL = t->getAttributes();
240 AttributeList PALNew;
241 #if LLVM_VERSION_LT(14, 0)
243 for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
244 B.addAttribute(unwrap(Attr));
245 PALNew = PAL.addAttributes(t->getContext(), Index, B);
247 AttrBuilder B(t->getContext());
248 for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
249 B.addAttribute(unwrap(Attr));
250 PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B);
252 t->setAttributes(PALNew);
255 extern "C" void LLVMRustAddFunctionAttributes(LLVMValueRef Fn, unsigned Index,
256 LLVMAttributeRef *Attrs, size_t AttrsLen) {
257 Function *F = unwrap<Function>(Fn);
258 AddAttributes(F, Index, Attrs, AttrsLen);
261 extern "C" void LLVMRustAddCallSiteAttributes(LLVMValueRef Instr, unsigned Index,
262 LLVMAttributeRef *Attrs, size_t AttrsLen) {
263 CallBase *Call = unwrap<CallBase>(Instr);
264 AddAttributes(Call, Index, Attrs, AttrsLen);
267 extern "C" LLVMAttributeRef LLVMRustCreateAttrNoValue(LLVMContextRef C,
268 LLVMRustAttribute RustAttr) {
269 return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr)));
272 extern "C" LLVMAttributeRef LLVMRustCreateAlignmentAttr(LLVMContextRef C,
274 return wrap(Attribute::getWithAlignment(*unwrap(C), llvm::Align(Bytes)));
277 extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableAttr(LLVMContextRef C,
279 return wrap(Attribute::getWithDereferenceableBytes(*unwrap(C), Bytes));
282 extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableOrNullAttr(LLVMContextRef C,
284 return wrap(Attribute::getWithDereferenceableOrNullBytes(*unwrap(C), Bytes));
287 extern "C" LLVMAttributeRef LLVMRustCreateByValAttr(LLVMContextRef C, LLVMTypeRef Ty) {
288 return wrap(Attribute::getWithByValType(*unwrap(C), unwrap(Ty)));
291 extern "C" LLVMAttributeRef LLVMRustCreateStructRetAttr(LLVMContextRef C, LLVMTypeRef Ty) {
292 return wrap(Attribute::getWithStructRetType(*unwrap(C), unwrap(Ty)));
295 extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Async) {
296 #if LLVM_VERSION_LT(15, 0)
297 return wrap(Attribute::get(*unwrap(C), Attribute::UWTable));
299 return wrap(Attribute::getWithUWTableKind(
300 *unwrap(C), Async ? UWTableKind::Async : UWTableKind::Sync));
304 // Enable a fast-math flag
306 // https://llvm.org/docs/LangRef.html#fast-math-flags
307 extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
308 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
313 extern "C" LLVMValueRef
314 LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
315 const char *Name, LLVMAtomicOrdering Order) {
316 Value *Ptr = unwrap(Source);
317 LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
318 LI->setAtomic(fromRust(Order));
322 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
325 LLVMAtomicOrdering Order) {
326 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
327 SI->setAtomic(fromRust(Order));
331 // FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
332 // once we raise our minimum support to LLVM 10.
333 extern "C" LLVMValueRef
334 LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
335 LLVMValueRef Old, LLVMValueRef Source,
336 LLVMAtomicOrdering Order,
337 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
338 #if LLVM_VERSION_GE(13,0)
339 // Rust probably knows the alignment of the target value and should be able to
340 // specify something more precise than MaybeAlign here. See also
341 // https://reviews.llvm.org/D97224 which may be a useful reference.
342 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
343 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
344 fromRust(FailureOrder));
346 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
347 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
348 fromRust(FailureOrder));
354 enum class LLVMRustSynchronizationScope {
359 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
361 case LLVMRustSynchronizationScope::SingleThread:
362 return SyncScope::SingleThread;
363 case LLVMRustSynchronizationScope::CrossThread:
364 return SyncScope::System;
366 report_fatal_error("bad SynchronizationScope.");
370 extern "C" LLVMValueRef
371 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
372 LLVMRustSynchronizationScope Scope) {
373 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
376 enum class LLVMRustAsmDialect {
381 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
383 case LLVMRustAsmDialect::Att:
384 return InlineAsm::AD_ATT;
385 case LLVMRustAsmDialect::Intel:
386 return InlineAsm::AD_Intel;
388 report_fatal_error("bad AsmDialect.");
392 extern "C" LLVMValueRef
393 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
394 char *Constraints, size_t ConstraintsLen,
395 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
396 LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
397 #if LLVM_VERSION_GE(13, 0)
398 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
399 StringRef(AsmString, AsmStringLen),
400 StringRef(Constraints, ConstraintsLen),
401 HasSideEffects, IsAlignStack,
402 fromRust(Dialect), CanThrow));
404 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
405 StringRef(AsmString, AsmStringLen),
406 StringRef(Constraints, ConstraintsLen),
407 HasSideEffects, IsAlignStack,
412 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
413 size_t ConstraintsLen) {
414 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
415 StringRef(Constraints, ConstraintsLen));
418 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
420 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
423 typedef DIBuilder *LLVMRustDIBuilderRef;
425 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
426 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
429 #define DIDescriptor DIScope
430 #define DIArray DINodeArray
431 #define unwrapDI unwrapDIPtr
433 // These values **must** match debuginfo::DIFlags! They also *happen*
434 // to match LLVM, but that isn't required as we do giant sets of
435 // matching below. The value shouldn't be directly passed to LLVM.
436 enum class LLVMRustDIFlags : uint32_t {
441 FlagFwdDecl = (1 << 2),
442 FlagAppleBlock = (1 << 3),
443 FlagBlockByrefStruct = (1 << 4),
444 FlagVirtual = (1 << 5),
445 FlagArtificial = (1 << 6),
446 FlagExplicit = (1 << 7),
447 FlagPrototyped = (1 << 8),
448 FlagObjcClassComplete = (1 << 9),
449 FlagObjectPointer = (1 << 10),
450 FlagVector = (1 << 11),
451 FlagStaticMember = (1 << 12),
452 FlagLValueReference = (1 << 13),
453 FlagRValueReference = (1 << 14),
454 FlagExternalTypeRef = (1 << 15),
455 FlagIntroducedVirtual = (1 << 18),
456 FlagBitField = (1 << 19),
457 FlagNoReturn = (1 << 20),
458 // Do not add values that are not supported by the minimum LLVM
459 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
462 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
463 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
464 static_cast<uint32_t>(B));
467 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
468 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
469 static_cast<uint32_t>(B));
472 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
476 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
478 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
479 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
482 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
483 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
485 switch (visibility(Flags)) {
486 case LLVMRustDIFlags::FlagPrivate:
487 Result |= DINode::DIFlags::FlagPrivate;
489 case LLVMRustDIFlags::FlagProtected:
490 Result |= DINode::DIFlags::FlagProtected;
492 case LLVMRustDIFlags::FlagPublic:
493 Result |= DINode::DIFlags::FlagPublic;
496 // The rest are handled below
500 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
501 Result |= DINode::DIFlags::FlagFwdDecl;
503 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
504 Result |= DINode::DIFlags::FlagAppleBlock;
506 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
507 Result |= DINode::DIFlags::FlagVirtual;
509 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
510 Result |= DINode::DIFlags::FlagArtificial;
512 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
513 Result |= DINode::DIFlags::FlagExplicit;
515 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
516 Result |= DINode::DIFlags::FlagPrototyped;
518 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
519 Result |= DINode::DIFlags::FlagObjcClassComplete;
521 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
522 Result |= DINode::DIFlags::FlagObjectPointer;
524 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
525 Result |= DINode::DIFlags::FlagVector;
527 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
528 Result |= DINode::DIFlags::FlagStaticMember;
530 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
531 Result |= DINode::DIFlags::FlagLValueReference;
533 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
534 Result |= DINode::DIFlags::FlagRValueReference;
536 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
537 Result |= DINode::DIFlags::FlagIntroducedVirtual;
539 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
540 Result |= DINode::DIFlags::FlagBitField;
542 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
543 Result |= DINode::DIFlags::FlagNoReturn;
549 // These values **must** match debuginfo::DISPFlags! They also *happen*
550 // to match LLVM, but that isn't required as we do giant sets of
551 // matching below. The value shouldn't be directly passed to LLVM.
552 enum class LLVMRustDISPFlags : uint32_t {
555 SPFlagPureVirtual = 2,
556 SPFlagLocalToUnit = (1 << 2),
557 SPFlagDefinition = (1 << 3),
558 SPFlagOptimized = (1 << 4),
559 SPFlagMainSubprogram = (1 << 5),
560 // Do not add values that are not supported by the minimum LLVM
561 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
562 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
565 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
566 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
567 static_cast<uint32_t>(B));
570 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
571 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
572 static_cast<uint32_t>(B));
575 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
579 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
581 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
582 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
585 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
586 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
588 switch (virtuality(SPFlags)) {
589 case LLVMRustDISPFlags::SPFlagVirtual:
590 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
592 case LLVMRustDISPFlags::SPFlagPureVirtual:
593 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
596 // The rest are handled below
600 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
601 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
603 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
604 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
606 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
607 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
609 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
610 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
616 enum class LLVMRustDebugEmissionKind {
622 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
624 case LLVMRustDebugEmissionKind::NoDebug:
625 return DICompileUnit::DebugEmissionKind::NoDebug;
626 case LLVMRustDebugEmissionKind::FullDebug:
627 return DICompileUnit::DebugEmissionKind::FullDebug;
628 case LLVMRustDebugEmissionKind::LineTablesOnly:
629 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
631 report_fatal_error("bad DebugEmissionKind.");
635 enum class LLVMRustChecksumKind {
642 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
644 case LLVMRustChecksumKind::None:
646 case LLVMRustChecksumKind::MD5:
647 return DIFile::ChecksumKind::CSK_MD5;
648 case LLVMRustChecksumKind::SHA1:
649 return DIFile::ChecksumKind::CSK_SHA1;
650 case LLVMRustChecksumKind::SHA256:
651 return DIFile::ChecksumKind::CSK_SHA256;
653 report_fatal_error("bad ChecksumKind.");
657 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
658 return DEBUG_METADATA_VERSION;
661 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
663 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
665 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
667 extern "C" void LLVMRustAddModuleFlag(
669 Module::ModFlagBehavior MergeBehavior,
672 unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
675 extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
677 return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
680 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
681 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
684 extern "C" void LLVMRustGlobalAddMetadata(
685 LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) {
686 unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
689 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
690 return new DIBuilder(*unwrap(M));
693 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
697 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
701 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
702 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
703 const char *Producer, size_t ProducerLen, bool isOptimized,
704 const char *Flags, unsigned RuntimeVer,
705 const char *SplitName, size_t SplitNameLen,
706 LLVMRustDebugEmissionKind Kind,
707 uint64_t DWOId, bool SplitDebugInlining) {
708 auto *File = unwrapDI<DIFile>(FileRef);
710 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
711 isOptimized, Flags, RuntimeVer,
712 StringRef(SplitName, SplitNameLen),
713 fromRust(Kind), DWOId, SplitDebugInlining));
716 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
717 LLVMRustDIBuilderRef Builder,
718 const char *Filename, size_t FilenameLen,
719 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
720 const char *Checksum, size_t ChecksumLen) {
721 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
722 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
724 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
725 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
726 StringRef(Directory, DirectoryLen),
730 extern "C" LLVMMetadataRef
731 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
732 LLVMMetadataRef ParameterTypes) {
733 return wrap(Builder->createSubroutineType(
734 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
737 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
738 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
739 const char *Name, size_t NameLen,
740 const char *LinkageName, size_t LinkageNameLen,
741 LLVMMetadataRef File, unsigned LineNo,
742 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
743 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
744 LLVMMetadataRef Decl) {
745 DITemplateParameterArray TParams =
746 DITemplateParameterArray(unwrap<MDTuple>(TParam));
747 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
748 DINode::DIFlags llvmFlags = fromRust(Flags);
749 DISubprogram *Sub = Builder->createFunction(
750 unwrapDI<DIScope>(Scope),
751 StringRef(Name, NameLen),
752 StringRef(LinkageName, LinkageNameLen),
753 unwrapDI<DIFile>(File), LineNo,
754 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
755 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
757 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
761 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
762 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
763 uint64_t SizeInBits, unsigned Encoding) {
764 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
767 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
768 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
769 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
770 return wrap(Builder->createTypedef(
771 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
772 LineNo, unwrapDIPtr<DIScope>(Scope)));
775 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
776 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
777 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
778 const char *Name, size_t NameLen) {
779 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
780 SizeInBits, AlignInBits,
782 StringRef(Name, NameLen)));
785 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
786 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
787 const char *Name, size_t NameLen,
788 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
789 uint32_t AlignInBits, LLVMRustDIFlags Flags,
790 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
791 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
792 const char *UniqueId, size_t UniqueIdLen) {
793 return wrap(Builder->createStructType(
794 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
795 unwrapDI<DIFile>(File), LineNumber,
796 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
797 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
798 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
801 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
802 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
803 const char *Name, size_t NameLen,
804 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
805 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
806 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
807 return wrap(Builder->createVariantPart(
808 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
809 unwrapDI<DIFile>(File), LineNumber,
810 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
811 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
814 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
815 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
816 const char *Name, size_t NameLen,
817 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
818 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
819 LLVMMetadataRef Ty) {
820 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
821 StringRef(Name, NameLen),
822 unwrapDI<DIFile>(File), LineNo,
823 SizeInBits, AlignInBits, OffsetInBits,
824 fromRust(Flags), unwrapDI<DIType>(Ty)));
827 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
828 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
829 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
830 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
831 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
832 llvm::ConstantInt* D = nullptr;
834 D = unwrap<llvm::ConstantInt>(Discriminant);
836 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
837 StringRef(Name, NameLen),
838 unwrapDI<DIFile>(File), LineNo,
839 SizeInBits, AlignInBits, OffsetInBits, D,
840 fromRust(Flags), unwrapDI<DIType>(Ty)));
843 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
844 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
845 LLVMMetadataRef File, unsigned Line, unsigned Col) {
846 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
847 unwrapDI<DIFile>(File), Line, Col));
850 extern "C" LLVMMetadataRef
851 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
852 LLVMMetadataRef Scope,
853 LLVMMetadataRef File) {
854 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
855 unwrapDI<DIFile>(File)));
858 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
859 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
860 const char *Name, size_t NameLen,
861 const char *LinkageName, size_t LinkageNameLen,
862 LLVMMetadataRef File, unsigned LineNo,
863 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
864 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
865 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
867 llvm::DIExpression *InitExpr = nullptr;
868 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
869 InitExpr = Builder->createConstantValueExpression(
870 IntVal->getValue().getSExtValue());
871 } else if (llvm::ConstantFP *FPVal =
872 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
873 InitExpr = Builder->createConstantValueExpression(
874 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
877 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
878 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
879 StringRef(LinkageName, LinkageNameLen),
880 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
881 /* isDefined */ true,
882 InitExpr, unwrapDIPtr<MDNode>(Decl),
883 /* templateParams */ nullptr,
886 InitVal->setMetadata("dbg", VarExpr);
888 return wrap(VarExpr);
891 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
892 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
893 const char *Name, size_t NameLen,
894 LLVMMetadataRef File, unsigned LineNo,
895 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
896 unsigned ArgNo, uint32_t AlignInBits) {
897 if (Tag == 0x100) { // DW_TAG_auto_variable
898 return wrap(Builder->createAutoVariable(
899 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
900 unwrapDI<DIFile>(File), LineNo,
901 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
903 return wrap(Builder->createParameterVariable(
904 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
905 unwrapDI<DIFile>(File), LineNo,
906 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
910 extern "C" LLVMMetadataRef
911 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
912 uint32_t AlignInBits, LLVMMetadataRef Ty,
913 LLVMMetadataRef Subscripts) {
915 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
916 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
919 extern "C" LLVMMetadataRef
920 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
922 return wrap(Builder->getOrCreateSubrange(Lo, Count));
925 extern "C" LLVMMetadataRef
926 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
927 LLVMMetadataRef *Ptr, unsigned Count) {
928 Metadata **DataValue = unwrap(Ptr);
930 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
933 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
934 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
935 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
936 LLVMBasicBlockRef InsertAtEnd) {
937 return wrap(Builder->insertDeclare(
938 unwrap(V), unwrap<DILocalVariable>(VarInfo),
939 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
940 DebugLoc(cast<MDNode>(unwrap(DL))),
941 unwrap(InsertAtEnd)));
944 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
945 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
946 int64_t Value, bool IsUnsigned) {
947 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
950 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
951 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
952 const char *Name, size_t NameLen,
953 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
954 uint32_t AlignInBits, LLVMMetadataRef Elements,
955 LLVMMetadataRef ClassTy, bool IsScoped) {
956 return wrap(Builder->createEnumerationType(
957 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
958 unwrapDI<DIFile>(File), LineNumber,
959 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
960 unwrapDI<DIType>(ClassTy), "", IsScoped));
963 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
964 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
965 const char *Name, size_t NameLen,
966 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
967 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
968 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
969 return wrap(Builder->createUnionType(
970 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
971 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
972 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
973 StringRef(UniqueId, UniqueIdLen)));
976 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
977 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
978 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
979 bool IsDefault = false; // FIXME: should we ever set this true?
980 return wrap(Builder->createTemplateTypeParameter(
981 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
984 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
985 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
986 const char *Name, size_t NameLen, bool ExportSymbols) {
987 return wrap(Builder->createNameSpace(
988 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
993 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
994 LLVMMetadataRef CompositeTy,
995 LLVMMetadataRef Elements,
996 LLVMMetadataRef Params) {
997 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
998 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
999 DINodeArray(unwrap<MDTuple>(Params)));
1002 extern "C" LLVMMetadataRef
1003 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1004 LLVMMetadataRef ScopeRef,
1005 LLVMMetadataRef InlinedAt) {
1006 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1007 DILocation *Loc = DILocation::get(
1008 Scope->getContext(), Line, Column, Scope,
1009 unwrapDIPtr<MDNode>(InlinedAt));
1013 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1014 return dwarf::DW_OP_deref;
1017 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1018 return dwarf::DW_OP_plus_uconst;
1021 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1022 RawRustStringOstream OS(Str);
1023 unwrap<llvm::Type>(Ty)->print(OS);
1026 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1027 RustStringRef Str) {
1028 RawRustStringOstream OS(Str);
1033 unwrap<llvm::Value>(V)->getType()->print(OS);
1035 unwrap<llvm::Value>(V)->print(OS);
1040 // LLVMArrayType function does not support 64-bit ElementCount
1041 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1042 uint64_t ElementCount) {
1043 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1046 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1048 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1049 RawRustStringOstream OS(Str);
1050 unwrap(T)->print(OS);
1053 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1054 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1055 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1056 RustStringRef FilenameOut, RustStringRef MessageOut) {
1057 // Undefined to call this not on an optimization diagnostic!
1058 llvm::DiagnosticInfoOptimizationBase *Opt =
1059 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1061 RawRustStringOstream PassNameOS(PassNameOut);
1062 PassNameOS << Opt->getPassName();
1063 *FunctionOut = wrap(&Opt->getFunction());
1065 RawRustStringOstream FilenameOS(FilenameOut);
1066 DiagnosticLocation loc = Opt->getLocation();
1067 if (loc.isValid()) {
1068 *Line = loc.getLine();
1069 *Column = loc.getColumn();
1070 FilenameOS << loc.getAbsolutePath();
1073 RawRustStringOstream MessageOS(MessageOut);
1074 MessageOS << Opt->getMsg();
1077 enum class LLVMRustDiagnosticLevel {
1085 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1086 LLVMRustDiagnosticLevel *LevelOut,
1087 unsigned *CookieOut,
1088 LLVMTwineRef *MessageOut) {
1089 // Undefined to call this not on an inline assembly diagnostic!
1090 llvm::DiagnosticInfoInlineAsm *IA =
1091 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1093 *CookieOut = IA->getLocCookie();
1094 *MessageOut = wrap(&IA->getMsgStr());
1096 switch (IA->getSeverity()) {
1098 *LevelOut = LLVMRustDiagnosticLevel::Error;
1101 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1104 *LevelOut = LLVMRustDiagnosticLevel::Note;
1107 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1110 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1114 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1115 RustStringRef Str) {
1116 RawRustStringOstream OS(Str);
1117 DiagnosticPrinterRawOStream DP(OS);
1118 unwrap(DI)->print(DP);
1121 enum class LLVMRustDiagnosticKind {
1125 DebugMetadataVersion,
1128 OptimizationRemarkMissed,
1129 OptimizationRemarkAnalysis,
1130 OptimizationRemarkAnalysisFPCommute,
1131 OptimizationRemarkAnalysisAliasing,
1132 OptimizationRemarkOther,
1133 OptimizationFailure,
1140 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1143 return LLVMRustDiagnosticKind::InlineAsm;
1145 return LLVMRustDiagnosticKind::StackSize;
1146 case DK_DebugMetadataVersion:
1147 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1148 case DK_SampleProfile:
1149 return LLVMRustDiagnosticKind::SampleProfile;
1150 case DK_OptimizationRemark:
1151 case DK_MachineOptimizationRemark:
1152 return LLVMRustDiagnosticKind::OptimizationRemark;
1153 case DK_OptimizationRemarkMissed:
1154 case DK_MachineOptimizationRemarkMissed:
1155 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1156 case DK_OptimizationRemarkAnalysis:
1157 case DK_MachineOptimizationRemarkAnalysis:
1158 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1159 case DK_OptimizationRemarkAnalysisFPCommute:
1160 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1161 case DK_OptimizationRemarkAnalysisAliasing:
1162 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1164 return LLVMRustDiagnosticKind::PGOProfile;
1166 return LLVMRustDiagnosticKind::Linker;
1167 case DK_Unsupported:
1168 return LLVMRustDiagnosticKind::Unsupported;
1169 #if LLVM_VERSION_GE(13, 0)
1171 return LLVMRustDiagnosticKind::SrcMgr;
1174 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1175 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1176 : LLVMRustDiagnosticKind::Other;
1180 extern "C" LLVMRustDiagnosticKind
1181 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1182 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1185 // This is kept distinct from LLVMGetTypeKind, because when
1186 // a new type kind is added, the Rust-side enum must be
1187 // updated or UB will result.
1188 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1189 switch (unwrap(Ty)->getTypeID()) {
1190 case Type::VoidTyID:
1191 return LLVMVoidTypeKind;
1192 case Type::HalfTyID:
1193 return LLVMHalfTypeKind;
1194 case Type::FloatTyID:
1195 return LLVMFloatTypeKind;
1196 case Type::DoubleTyID:
1197 return LLVMDoubleTypeKind;
1198 case Type::X86_FP80TyID:
1199 return LLVMX86_FP80TypeKind;
1200 case Type::FP128TyID:
1201 return LLVMFP128TypeKind;
1202 case Type::PPC_FP128TyID:
1203 return LLVMPPC_FP128TypeKind;
1204 case Type::LabelTyID:
1205 return LLVMLabelTypeKind;
1206 case Type::MetadataTyID:
1207 return LLVMMetadataTypeKind;
1208 case Type::IntegerTyID:
1209 return LLVMIntegerTypeKind;
1210 case Type::FunctionTyID:
1211 return LLVMFunctionTypeKind;
1212 case Type::StructTyID:
1213 return LLVMStructTypeKind;
1214 case Type::ArrayTyID:
1215 return LLVMArrayTypeKind;
1216 case Type::PointerTyID:
1217 return LLVMPointerTypeKind;
1218 case Type::FixedVectorTyID:
1219 return LLVMVectorTypeKind;
1220 case Type::X86_MMXTyID:
1221 return LLVMX86_MMXTypeKind;
1222 case Type::TokenTyID:
1223 return LLVMTokenTypeKind;
1224 case Type::ScalableVectorTyID:
1225 return LLVMScalableVectorTypeKind;
1226 case Type::BFloatTyID:
1227 return LLVMBFloatTypeKind;
1228 case Type::X86_AMXTyID:
1229 return LLVMX86_AMXTypeKind;
1230 #if LLVM_VERSION_GE(15, 0)
1231 case Type::DXILPointerTyID:
1232 report_fatal_error("Rust does not support DirectX typed pointers.");
1236 report_fatal_error("Unhandled TypeID.");
1239 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1241 #if LLVM_VERSION_LT(13, 0)
1242 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1244 using LLVMInlineAsmDiagHandlerTy = void*;
1247 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1248 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1249 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1250 // with LLVM 13 this function is gone.
1251 #if LLVM_VERSION_LT(13, 0)
1252 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1256 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1257 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1258 #if LLVM_VERSION_GE(13, 0)
1259 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1260 *Cookie = SM->getLocCookie();
1261 return wrap(&SM->getSMDiag());
1263 report_fatal_error("Shouldn't get called on older versions");
1267 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1268 RustStringRef MessageOut,
1269 RustStringRef BufferOut,
1270 LLVMRustDiagnosticLevel* LevelOut,
1272 unsigned* RangesOut,
1273 size_t* NumRanges) {
1274 SMDiagnostic& D = *unwrap(DRef);
1275 RawRustStringOstream MessageOS(MessageOut);
1276 MessageOS << D.getMessage();
1278 switch (D.getKind()) {
1279 case SourceMgr::DK_Error:
1280 *LevelOut = LLVMRustDiagnosticLevel::Error;
1282 case SourceMgr::DK_Warning:
1283 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1285 case SourceMgr::DK_Note:
1286 *LevelOut = LLVMRustDiagnosticLevel::Note;
1288 case SourceMgr::DK_Remark:
1289 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1292 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1295 if (D.getLoc() == SMLoc())
1298 const SourceMgr &LSM = *D.getSourceMgr();
1299 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1300 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1302 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1304 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1305 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1306 for (size_t i = 0; i < *NumRanges; i++) {
1307 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1308 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1314 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1315 LLVMValueRef ParentPad,
1317 LLVMValueRef *LLArgs,
1319 Value **Args = unwrap(LLArgs);
1320 if (ParentPad == nullptr) {
1321 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1322 ParentPad = wrap(Constant::getNullValue(Ty));
1324 return wrap(unwrap(B)->CreateCleanupPad(
1325 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1328 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1329 LLVMValueRef CleanupPad,
1330 LLVMBasicBlockRef UnwindBB) {
1331 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1332 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1335 extern "C" LLVMValueRef
1336 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1337 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1338 Value **Args = unwrap(LLArgs);
1339 return wrap(unwrap(B)->CreateCatchPad(
1340 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1343 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1345 LLVMBasicBlockRef BB) {
1346 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1350 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1351 LLVMValueRef ParentPad,
1352 LLVMBasicBlockRef BB,
1353 unsigned NumHandlers,
1355 if (ParentPad == nullptr) {
1356 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1357 ParentPad = wrap(Constant::getNullValue(Ty));
1359 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1360 NumHandlers, Name));
1363 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1364 LLVMBasicBlockRef Handler) {
1365 Value *CatchSwitch = unwrap(CatchSwitchRef);
1366 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1369 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1370 LLVMValueRef *Inputs,
1371 unsigned NumInputs) {
1372 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1375 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1379 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1380 LLVMValueRef *Args, unsigned NumArgs,
1381 OperandBundleDef *Bundle) {
1382 Value *Callee = unwrap(Fn);
1383 FunctionType *FTy = unwrap<FunctionType>(Ty);
1384 unsigned Len = Bundle ? 1 : 0;
1385 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1386 return wrap(unwrap(B)->CreateCall(
1387 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1390 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1391 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1392 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1395 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1396 LLVMValueRef Dst, unsigned DstAlign,
1397 LLVMValueRef Src, unsigned SrcAlign,
1398 LLVMValueRef Size, bool IsVolatile) {
1399 return wrap(unwrap(B)->CreateMemCpy(
1400 unwrap(Dst), MaybeAlign(DstAlign),
1401 unwrap(Src), MaybeAlign(SrcAlign),
1402 unwrap(Size), IsVolatile));
1405 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1406 LLVMValueRef Dst, unsigned DstAlign,
1407 LLVMValueRef Src, unsigned SrcAlign,
1408 LLVMValueRef Size, bool IsVolatile) {
1409 return wrap(unwrap(B)->CreateMemMove(
1410 unwrap(Dst), MaybeAlign(DstAlign),
1411 unwrap(Src), MaybeAlign(SrcAlign),
1412 unwrap(Size), IsVolatile));
1415 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1416 LLVMValueRef Dst, unsigned DstAlign,
1418 LLVMValueRef Size, bool IsVolatile) {
1419 return wrap(unwrap(B)->CreateMemSet(
1420 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1423 extern "C" LLVMValueRef
1424 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1425 LLVMValueRef *Args, unsigned NumArgs,
1426 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1427 OperandBundleDef *Bundle, const char *Name) {
1428 Value *Callee = unwrap(Fn);
1429 FunctionType *FTy = unwrap<FunctionType>(Ty);
1430 unsigned Len = Bundle ? 1 : 0;
1431 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1432 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1433 makeArrayRef(unwrap(Args), NumArgs),
1437 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1438 LLVMBasicBlockRef BB) {
1439 auto Point = unwrap(BB)->getFirstInsertionPt();
1440 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1443 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1444 const char *Name, size_t NameLen) {
1445 Triple TargetTriple(unwrap(M)->getTargetTriple());
1446 GlobalObject *GV = unwrap<GlobalObject>(V);
1447 if (TargetTriple.supportsCOMDAT()) {
1448 StringRef NameRef(Name, NameLen);
1449 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1453 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1454 GlobalObject *GV = unwrap<GlobalObject>(V);
1455 GV->setComdat(nullptr);
1458 enum class LLVMRustLinkage {
1459 ExternalLinkage = 0,
1460 AvailableExternallyLinkage = 1,
1461 LinkOnceAnyLinkage = 2,
1462 LinkOnceODRLinkage = 3,
1465 AppendingLinkage = 6,
1466 InternalLinkage = 7,
1468 ExternalWeakLinkage = 9,
1472 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1474 case LLVMExternalLinkage:
1475 return LLVMRustLinkage::ExternalLinkage;
1476 case LLVMAvailableExternallyLinkage:
1477 return LLVMRustLinkage::AvailableExternallyLinkage;
1478 case LLVMLinkOnceAnyLinkage:
1479 return LLVMRustLinkage::LinkOnceAnyLinkage;
1480 case LLVMLinkOnceODRLinkage:
1481 return LLVMRustLinkage::LinkOnceODRLinkage;
1482 case LLVMWeakAnyLinkage:
1483 return LLVMRustLinkage::WeakAnyLinkage;
1484 case LLVMWeakODRLinkage:
1485 return LLVMRustLinkage::WeakODRLinkage;
1486 case LLVMAppendingLinkage:
1487 return LLVMRustLinkage::AppendingLinkage;
1488 case LLVMInternalLinkage:
1489 return LLVMRustLinkage::InternalLinkage;
1490 case LLVMPrivateLinkage:
1491 return LLVMRustLinkage::PrivateLinkage;
1492 case LLVMExternalWeakLinkage:
1493 return LLVMRustLinkage::ExternalWeakLinkage;
1494 case LLVMCommonLinkage:
1495 return LLVMRustLinkage::CommonLinkage;
1497 report_fatal_error("Invalid LLVMRustLinkage value!");
1501 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1503 case LLVMRustLinkage::ExternalLinkage:
1504 return LLVMExternalLinkage;
1505 case LLVMRustLinkage::AvailableExternallyLinkage:
1506 return LLVMAvailableExternallyLinkage;
1507 case LLVMRustLinkage::LinkOnceAnyLinkage:
1508 return LLVMLinkOnceAnyLinkage;
1509 case LLVMRustLinkage::LinkOnceODRLinkage:
1510 return LLVMLinkOnceODRLinkage;
1511 case LLVMRustLinkage::WeakAnyLinkage:
1512 return LLVMWeakAnyLinkage;
1513 case LLVMRustLinkage::WeakODRLinkage:
1514 return LLVMWeakODRLinkage;
1515 case LLVMRustLinkage::AppendingLinkage:
1516 return LLVMAppendingLinkage;
1517 case LLVMRustLinkage::InternalLinkage:
1518 return LLVMInternalLinkage;
1519 case LLVMRustLinkage::PrivateLinkage:
1520 return LLVMPrivateLinkage;
1521 case LLVMRustLinkage::ExternalWeakLinkage:
1522 return LLVMExternalWeakLinkage;
1523 case LLVMRustLinkage::CommonLinkage:
1524 return LLVMCommonLinkage;
1526 report_fatal_error("Invalid LLVMRustLinkage value!");
1529 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1530 return toRust(LLVMGetLinkage(V));
1533 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1534 LLVMRustLinkage RustLinkage) {
1535 LLVMSetLinkage(V, fromRust(RustLinkage));
1538 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1539 LLVMValueRef ConstantVal,
1540 LLVMValueRef *ConstantIndices,
1541 unsigned NumIndices) {
1542 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1544 Constant *Val = unwrap<Constant>(ConstantVal);
1545 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1548 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1549 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1550 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1552 auto C = unwrap<llvm::ConstantInt>(CV);
1553 if (C->getBitWidth() > 128) { return false; }
1555 #if LLVM_VERSION_GE(15, 0)
1557 AP = C->getValue().sext(128);
1559 AP = C->getValue().zext(128);
1563 AP = C->getValue().sextOrSelf(128);
1565 AP = C->getValue().zextOrSelf(128);
1568 *low = AP.getLoBits(64).getZExtValue();
1569 *high = AP.getHiBits(64).getZExtValue();
1573 enum class LLVMRustVisibility {
1579 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1581 case LLVMDefaultVisibility:
1582 return LLVMRustVisibility::Default;
1583 case LLVMHiddenVisibility:
1584 return LLVMRustVisibility::Hidden;
1585 case LLVMProtectedVisibility:
1586 return LLVMRustVisibility::Protected;
1588 report_fatal_error("Invalid LLVMRustVisibility value!");
1591 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1593 case LLVMRustVisibility::Default:
1594 return LLVMDefaultVisibility;
1595 case LLVMRustVisibility::Hidden:
1596 return LLVMHiddenVisibility;
1597 case LLVMRustVisibility::Protected:
1598 return LLVMProtectedVisibility;
1600 report_fatal_error("Invalid LLVMRustVisibility value!");
1603 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1604 return toRust(LLVMGetVisibility(V));
1607 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1608 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1609 LLVMTypeRef DestTy, bool isSigned) {
1610 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1613 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1614 LLVMRustVisibility RustVisibility) {
1615 LLVMSetVisibility(V, fromRust(RustVisibility));
1618 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1619 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1622 struct LLVMRustModuleBuffer {
1626 extern "C" LLVMRustModuleBuffer*
1627 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1628 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1630 raw_string_ostream OS(Ret->data);
1632 legacy::PassManager PM;
1633 PM.add(createBitcodeWriterPass(OS));
1637 return Ret.release();
1641 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1645 extern "C" const void*
1646 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1647 return Buffer->data.data();
1651 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1652 return Buffer->data.length();
1656 LLVMRustModuleCost(LLVMModuleRef M) {
1657 auto f = unwrap(M)->functions();
1658 return std::distance(std::begin(f), std::end(f));
1661 // Vector reductions:
1662 extern "C" LLVMValueRef
1663 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1664 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1666 extern "C" LLVMValueRef
1667 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1668 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1670 extern "C" LLVMValueRef
1671 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1672 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1674 extern "C" LLVMValueRef
1675 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1676 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1678 extern "C" LLVMValueRef
1679 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1680 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1682 extern "C" LLVMValueRef
1683 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1684 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1686 extern "C" LLVMValueRef
1687 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1688 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1690 extern "C" LLVMValueRef
1691 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1692 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1694 extern "C" LLVMValueRef
1695 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1696 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1698 extern "C" LLVMValueRef
1699 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1700 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1701 I->setHasNoNaNs(NoNaN);
1704 extern "C" LLVMValueRef
1705 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1706 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1707 I->setHasNoNaNs(NoNaN);
1711 extern "C" LLVMValueRef
1712 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1713 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1715 extern "C" LLVMValueRef
1716 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1717 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1720 // This struct contains all necessary info about a symbol exported from a DLL.
1721 struct LLVMRustCOFFShortExport {
1723 bool ordinal_present;
1724 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1728 // Machine must be a COFF machine type, as defined in PE specs.
1729 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1730 const char* ImportName,
1732 const LLVMRustCOFFShortExport* Exports,
1737 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1738 ConvertedExports.reserve(NumExports);
1740 for (size_t i = 0; i < NumExports; ++i) {
1741 bool ordinal_present = Exports[i].ordinal_present;
1742 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1743 ConvertedExports.push_back(llvm::object::COFFShortExport{
1744 Exports[i].name, // Name
1745 std::string{}, // ExtName
1746 std::string{}, // SymbolName
1747 std::string{}, // AliasTarget
1749 ordinal_present, // Noname
1756 auto Error = llvm::object::writeImportLibrary(
1760 static_cast<llvm::COFF::MachineTypes>(Machine),
1763 std::string errorString;
1764 llvm::raw_string_ostream stream(errorString);
1767 LLVMRustSetLastError(errorString.c_str());
1768 return LLVMRustResult::Failure;
1770 return LLVMRustResult::Success;
1774 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1775 extern "C" DiagnosticHandler *
1776 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1777 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1778 return DH.release();
1781 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1782 // handling. Ownership of the handler is moved to the LLVMContext.
1783 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1784 DiagnosticHandler *DH) {
1785 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1788 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1790 // Configures a diagnostic handler that invokes provided callback when a
1791 // backend needs to emit a diagnostic.
1793 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1794 // the RemarkPasses array specifies individual passes for which remarks will be
1796 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1797 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1798 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1799 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1801 class RustDiagnosticHandler final : public DiagnosticHandler {
1803 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1804 void *DiagnosticHandlerContext,
1805 bool RemarkAllPasses,
1806 std::vector<std::string> RemarkPasses)
1807 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1808 DiagnosticHandlerContext(DiagnosticHandlerContext),
1809 RemarkAllPasses(RemarkAllPasses),
1810 RemarkPasses(RemarkPasses) {}
1812 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1813 if (DiagnosticHandlerCallback) {
1814 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1820 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1821 return isRemarkEnabled(PassName);
1824 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1825 return isRemarkEnabled(PassName);
1828 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1829 return isRemarkEnabled(PassName);
1832 bool isAnyRemarkEnabled() const override {
1833 return RemarkAllPasses || !RemarkPasses.empty();
1837 bool isRemarkEnabled(StringRef PassName) const {
1838 if (RemarkAllPasses)
1841 for (auto &Pass : RemarkPasses)
1842 if (Pass == PassName)
1848 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1849 void *DiagnosticHandlerContext = nullptr;
1851 bool RemarkAllPasses = false;
1852 std::vector<std::string> RemarkPasses;
1855 std::vector<std::string> Passes;
1856 for (size_t I = 0; I != RemarkPassesLen; ++I)
1857 Passes.push_back(RemarkPasses[I]);
1859 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1860 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
1863 extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
1864 RawRustStringOstream OS(Str);
1865 GlobalValue *GV = unwrap<GlobalValue>(V);
1866 Mangler().getNameWithPrefix(OS, GV, true);
1869 // LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just
1870 // use its implementation.
1871 #if LLVM_VERSION_LT(15, 0)
1872 extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
1873 return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));