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 #if LLVM_VERSION_LT(15, 0)
415 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
416 StringRef(Constraints, ConstraintsLen));
418 // llvm::Error converts to true if it is an error.
419 return !llvm::errorToBool(InlineAsm::verify(
420 unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen)));
424 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
426 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
429 typedef DIBuilder *LLVMRustDIBuilderRef;
431 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
432 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
435 #define DIDescriptor DIScope
436 #define DIArray DINodeArray
437 #define unwrapDI unwrapDIPtr
439 // These values **must** match debuginfo::DIFlags! They also *happen*
440 // to match LLVM, but that isn't required as we do giant sets of
441 // matching below. The value shouldn't be directly passed to LLVM.
442 enum class LLVMRustDIFlags : uint32_t {
447 FlagFwdDecl = (1 << 2),
448 FlagAppleBlock = (1 << 3),
449 FlagBlockByrefStruct = (1 << 4),
450 FlagVirtual = (1 << 5),
451 FlagArtificial = (1 << 6),
452 FlagExplicit = (1 << 7),
453 FlagPrototyped = (1 << 8),
454 FlagObjcClassComplete = (1 << 9),
455 FlagObjectPointer = (1 << 10),
456 FlagVector = (1 << 11),
457 FlagStaticMember = (1 << 12),
458 FlagLValueReference = (1 << 13),
459 FlagRValueReference = (1 << 14),
460 FlagExternalTypeRef = (1 << 15),
461 FlagIntroducedVirtual = (1 << 18),
462 FlagBitField = (1 << 19),
463 FlagNoReturn = (1 << 20),
464 // Do not add values that are not supported by the minimum LLVM
465 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
468 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
469 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
470 static_cast<uint32_t>(B));
473 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
474 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
475 static_cast<uint32_t>(B));
478 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
482 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
484 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
485 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
488 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
489 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
491 switch (visibility(Flags)) {
492 case LLVMRustDIFlags::FlagPrivate:
493 Result |= DINode::DIFlags::FlagPrivate;
495 case LLVMRustDIFlags::FlagProtected:
496 Result |= DINode::DIFlags::FlagProtected;
498 case LLVMRustDIFlags::FlagPublic:
499 Result |= DINode::DIFlags::FlagPublic;
502 // The rest are handled below
506 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
507 Result |= DINode::DIFlags::FlagFwdDecl;
509 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
510 Result |= DINode::DIFlags::FlagAppleBlock;
512 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
513 Result |= DINode::DIFlags::FlagVirtual;
515 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
516 Result |= DINode::DIFlags::FlagArtificial;
518 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
519 Result |= DINode::DIFlags::FlagExplicit;
521 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
522 Result |= DINode::DIFlags::FlagPrototyped;
524 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
525 Result |= DINode::DIFlags::FlagObjcClassComplete;
527 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
528 Result |= DINode::DIFlags::FlagObjectPointer;
530 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
531 Result |= DINode::DIFlags::FlagVector;
533 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
534 Result |= DINode::DIFlags::FlagStaticMember;
536 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
537 Result |= DINode::DIFlags::FlagLValueReference;
539 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
540 Result |= DINode::DIFlags::FlagRValueReference;
542 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
543 Result |= DINode::DIFlags::FlagIntroducedVirtual;
545 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
546 Result |= DINode::DIFlags::FlagBitField;
548 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
549 Result |= DINode::DIFlags::FlagNoReturn;
555 // These values **must** match debuginfo::DISPFlags! They also *happen*
556 // to match LLVM, but that isn't required as we do giant sets of
557 // matching below. The value shouldn't be directly passed to LLVM.
558 enum class LLVMRustDISPFlags : uint32_t {
561 SPFlagPureVirtual = 2,
562 SPFlagLocalToUnit = (1 << 2),
563 SPFlagDefinition = (1 << 3),
564 SPFlagOptimized = (1 << 4),
565 SPFlagMainSubprogram = (1 << 5),
566 // Do not add values that are not supported by the minimum LLVM
567 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
568 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
571 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
572 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
573 static_cast<uint32_t>(B));
576 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
577 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
578 static_cast<uint32_t>(B));
581 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
585 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
587 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
588 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
591 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
592 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
594 switch (virtuality(SPFlags)) {
595 case LLVMRustDISPFlags::SPFlagVirtual:
596 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
598 case LLVMRustDISPFlags::SPFlagPureVirtual:
599 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
602 // The rest are handled below
606 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
607 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
609 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
610 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
612 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
613 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
615 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
616 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
622 enum class LLVMRustDebugEmissionKind {
628 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
630 case LLVMRustDebugEmissionKind::NoDebug:
631 return DICompileUnit::DebugEmissionKind::NoDebug;
632 case LLVMRustDebugEmissionKind::FullDebug:
633 return DICompileUnit::DebugEmissionKind::FullDebug;
634 case LLVMRustDebugEmissionKind::LineTablesOnly:
635 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
637 report_fatal_error("bad DebugEmissionKind.");
641 enum class LLVMRustChecksumKind {
648 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
650 case LLVMRustChecksumKind::None:
652 case LLVMRustChecksumKind::MD5:
653 return DIFile::ChecksumKind::CSK_MD5;
654 case LLVMRustChecksumKind::SHA1:
655 return DIFile::ChecksumKind::CSK_SHA1;
656 case LLVMRustChecksumKind::SHA256:
657 return DIFile::ChecksumKind::CSK_SHA256;
659 report_fatal_error("bad ChecksumKind.");
663 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
664 return DEBUG_METADATA_VERSION;
667 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
669 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
671 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
673 extern "C" void LLVMRustAddModuleFlag(
675 Module::ModFlagBehavior MergeBehavior,
678 unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
681 extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
683 return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
686 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
687 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
690 extern "C" void LLVMRustGlobalAddMetadata(
691 LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) {
692 unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
695 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
696 return new DIBuilder(*unwrap(M));
699 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
703 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
707 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
708 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
709 const char *Producer, size_t ProducerLen, bool isOptimized,
710 const char *Flags, unsigned RuntimeVer,
711 const char *SplitName, size_t SplitNameLen,
712 LLVMRustDebugEmissionKind Kind,
713 uint64_t DWOId, bool SplitDebugInlining) {
714 auto *File = unwrapDI<DIFile>(FileRef);
716 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
717 isOptimized, Flags, RuntimeVer,
718 StringRef(SplitName, SplitNameLen),
719 fromRust(Kind), DWOId, SplitDebugInlining));
722 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
723 LLVMRustDIBuilderRef Builder,
724 const char *Filename, size_t FilenameLen,
725 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
726 const char *Checksum, size_t ChecksumLen) {
727 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
728 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
730 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
731 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
732 StringRef(Directory, DirectoryLen),
736 extern "C" LLVMMetadataRef
737 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
738 LLVMMetadataRef ParameterTypes) {
739 return wrap(Builder->createSubroutineType(
740 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
743 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
744 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
745 const char *Name, size_t NameLen,
746 const char *LinkageName, size_t LinkageNameLen,
747 LLVMMetadataRef File, unsigned LineNo,
748 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
749 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
750 LLVMMetadataRef Decl) {
751 DITemplateParameterArray TParams =
752 DITemplateParameterArray(unwrap<MDTuple>(TParam));
753 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
754 DINode::DIFlags llvmFlags = fromRust(Flags);
755 DISubprogram *Sub = Builder->createFunction(
756 unwrapDI<DIScope>(Scope),
757 StringRef(Name, NameLen),
758 StringRef(LinkageName, LinkageNameLen),
759 unwrapDI<DIFile>(File), LineNo,
760 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
761 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
763 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
767 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
768 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
769 uint64_t SizeInBits, unsigned Encoding) {
770 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
773 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
774 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
775 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
776 return wrap(Builder->createTypedef(
777 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
778 LineNo, unwrapDIPtr<DIScope>(Scope)));
781 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
782 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
783 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
784 const char *Name, size_t NameLen) {
785 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
786 SizeInBits, AlignInBits,
788 StringRef(Name, NameLen)));
791 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
792 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
793 const char *Name, size_t NameLen,
794 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
795 uint32_t AlignInBits, LLVMRustDIFlags Flags,
796 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
797 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
798 const char *UniqueId, size_t UniqueIdLen) {
799 return wrap(Builder->createStructType(
800 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
801 unwrapDI<DIFile>(File), LineNumber,
802 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
803 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
804 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
807 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
808 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
809 const char *Name, size_t NameLen,
810 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
811 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
812 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
813 return wrap(Builder->createVariantPart(
814 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
815 unwrapDI<DIFile>(File), LineNumber,
816 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
817 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
820 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
821 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
822 const char *Name, size_t NameLen,
823 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
824 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
825 LLVMMetadataRef Ty) {
826 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
827 StringRef(Name, NameLen),
828 unwrapDI<DIFile>(File), LineNo,
829 SizeInBits, AlignInBits, OffsetInBits,
830 fromRust(Flags), unwrapDI<DIType>(Ty)));
833 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
834 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
835 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
836 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
837 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
838 llvm::ConstantInt* D = nullptr;
840 D = unwrap<llvm::ConstantInt>(Discriminant);
842 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
843 StringRef(Name, NameLen),
844 unwrapDI<DIFile>(File), LineNo,
845 SizeInBits, AlignInBits, OffsetInBits, D,
846 fromRust(Flags), unwrapDI<DIType>(Ty)));
849 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
850 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
851 LLVMMetadataRef File, unsigned Line, unsigned Col) {
852 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
853 unwrapDI<DIFile>(File), Line, Col));
856 extern "C" LLVMMetadataRef
857 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
858 LLVMMetadataRef Scope,
859 LLVMMetadataRef File) {
860 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
861 unwrapDI<DIFile>(File)));
864 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
865 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
866 const char *Name, size_t NameLen,
867 const char *LinkageName, size_t LinkageNameLen,
868 LLVMMetadataRef File, unsigned LineNo,
869 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
870 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
871 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
873 llvm::DIExpression *InitExpr = nullptr;
874 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
875 InitExpr = Builder->createConstantValueExpression(
876 IntVal->getValue().getSExtValue());
877 } else if (llvm::ConstantFP *FPVal =
878 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
879 InitExpr = Builder->createConstantValueExpression(
880 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
883 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
884 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
885 StringRef(LinkageName, LinkageNameLen),
886 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
887 /* isDefined */ true,
888 InitExpr, unwrapDIPtr<MDNode>(Decl),
889 /* templateParams */ nullptr,
892 InitVal->setMetadata("dbg", VarExpr);
894 return wrap(VarExpr);
897 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
898 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
899 const char *Name, size_t NameLen,
900 LLVMMetadataRef File, unsigned LineNo,
901 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
902 unsigned ArgNo, uint32_t AlignInBits) {
903 if (Tag == 0x100) { // DW_TAG_auto_variable
904 return wrap(Builder->createAutoVariable(
905 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
906 unwrapDI<DIFile>(File), LineNo,
907 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
909 return wrap(Builder->createParameterVariable(
910 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
911 unwrapDI<DIFile>(File), LineNo,
912 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
916 extern "C" LLVMMetadataRef
917 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
918 uint32_t AlignInBits, LLVMMetadataRef Ty,
919 LLVMMetadataRef Subscripts) {
921 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
922 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
925 extern "C" LLVMMetadataRef
926 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
928 return wrap(Builder->getOrCreateSubrange(Lo, Count));
931 extern "C" LLVMMetadataRef
932 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
933 LLVMMetadataRef *Ptr, unsigned Count) {
934 Metadata **DataValue = unwrap(Ptr);
936 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
939 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
940 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
941 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
942 LLVMBasicBlockRef InsertAtEnd) {
943 return wrap(Builder->insertDeclare(
944 unwrap(V), unwrap<DILocalVariable>(VarInfo),
945 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
946 DebugLoc(cast<MDNode>(unwrap(DL))),
947 unwrap(InsertAtEnd)));
950 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
951 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
952 int64_t Value, bool IsUnsigned) {
953 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
956 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
957 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
958 const char *Name, size_t NameLen,
959 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
960 uint32_t AlignInBits, LLVMMetadataRef Elements,
961 LLVMMetadataRef ClassTy, bool IsScoped) {
962 return wrap(Builder->createEnumerationType(
963 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
964 unwrapDI<DIFile>(File), LineNumber,
965 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
966 unwrapDI<DIType>(ClassTy), "", IsScoped));
969 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
970 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
971 const char *Name, size_t NameLen,
972 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
973 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
974 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
975 return wrap(Builder->createUnionType(
976 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
977 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
978 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
979 StringRef(UniqueId, UniqueIdLen)));
982 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
983 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
984 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
985 bool IsDefault = false; // FIXME: should we ever set this true?
986 return wrap(Builder->createTemplateTypeParameter(
987 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
990 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
991 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
992 const char *Name, size_t NameLen, bool ExportSymbols) {
993 return wrap(Builder->createNameSpace(
994 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
999 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1000 LLVMMetadataRef CompositeTy,
1001 LLVMMetadataRef Elements,
1002 LLVMMetadataRef Params) {
1003 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1004 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1005 DINodeArray(unwrap<MDTuple>(Params)));
1008 extern "C" LLVMMetadataRef
1009 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1010 LLVMMetadataRef ScopeRef,
1011 LLVMMetadataRef InlinedAt) {
1012 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1013 DILocation *Loc = DILocation::get(
1014 Scope->getContext(), Line, Column, Scope,
1015 unwrapDIPtr<MDNode>(InlinedAt));
1019 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1020 return dwarf::DW_OP_deref;
1023 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1024 return dwarf::DW_OP_plus_uconst;
1027 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1028 RawRustStringOstream OS(Str);
1029 unwrap<llvm::Type>(Ty)->print(OS);
1032 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1033 RustStringRef Str) {
1034 RawRustStringOstream OS(Str);
1039 unwrap<llvm::Value>(V)->getType()->print(OS);
1041 unwrap<llvm::Value>(V)->print(OS);
1046 // LLVMArrayType function does not support 64-bit ElementCount
1047 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1048 uint64_t ElementCount) {
1049 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1052 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1054 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1055 RawRustStringOstream OS(Str);
1056 unwrap(T)->print(OS);
1059 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1060 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1061 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1062 RustStringRef FilenameOut, RustStringRef MessageOut) {
1063 // Undefined to call this not on an optimization diagnostic!
1064 llvm::DiagnosticInfoOptimizationBase *Opt =
1065 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1067 RawRustStringOstream PassNameOS(PassNameOut);
1068 PassNameOS << Opt->getPassName();
1069 *FunctionOut = wrap(&Opt->getFunction());
1071 RawRustStringOstream FilenameOS(FilenameOut);
1072 DiagnosticLocation loc = Opt->getLocation();
1073 if (loc.isValid()) {
1074 *Line = loc.getLine();
1075 *Column = loc.getColumn();
1076 FilenameOS << loc.getAbsolutePath();
1079 RawRustStringOstream MessageOS(MessageOut);
1080 MessageOS << Opt->getMsg();
1083 enum class LLVMRustDiagnosticLevel {
1091 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1092 LLVMRustDiagnosticLevel *LevelOut,
1093 unsigned *CookieOut,
1094 LLVMTwineRef *MessageOut) {
1095 // Undefined to call this not on an inline assembly diagnostic!
1096 llvm::DiagnosticInfoInlineAsm *IA =
1097 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1099 *CookieOut = IA->getLocCookie();
1100 *MessageOut = wrap(&IA->getMsgStr());
1102 switch (IA->getSeverity()) {
1104 *LevelOut = LLVMRustDiagnosticLevel::Error;
1107 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1110 *LevelOut = LLVMRustDiagnosticLevel::Note;
1113 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1116 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1120 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1121 RustStringRef Str) {
1122 RawRustStringOstream OS(Str);
1123 DiagnosticPrinterRawOStream DP(OS);
1124 unwrap(DI)->print(DP);
1127 enum class LLVMRustDiagnosticKind {
1131 DebugMetadataVersion,
1134 OptimizationRemarkMissed,
1135 OptimizationRemarkAnalysis,
1136 OptimizationRemarkAnalysisFPCommute,
1137 OptimizationRemarkAnalysisAliasing,
1138 OptimizationRemarkOther,
1139 OptimizationFailure,
1146 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1149 return LLVMRustDiagnosticKind::InlineAsm;
1151 return LLVMRustDiagnosticKind::StackSize;
1152 case DK_DebugMetadataVersion:
1153 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1154 case DK_SampleProfile:
1155 return LLVMRustDiagnosticKind::SampleProfile;
1156 case DK_OptimizationRemark:
1157 case DK_MachineOptimizationRemark:
1158 return LLVMRustDiagnosticKind::OptimizationRemark;
1159 case DK_OptimizationRemarkMissed:
1160 case DK_MachineOptimizationRemarkMissed:
1161 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1162 case DK_OptimizationRemarkAnalysis:
1163 case DK_MachineOptimizationRemarkAnalysis:
1164 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1165 case DK_OptimizationRemarkAnalysisFPCommute:
1166 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1167 case DK_OptimizationRemarkAnalysisAliasing:
1168 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1170 return LLVMRustDiagnosticKind::PGOProfile;
1172 return LLVMRustDiagnosticKind::Linker;
1173 case DK_Unsupported:
1174 return LLVMRustDiagnosticKind::Unsupported;
1175 #if LLVM_VERSION_GE(13, 0)
1177 return LLVMRustDiagnosticKind::SrcMgr;
1180 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1181 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1182 : LLVMRustDiagnosticKind::Other;
1186 extern "C" LLVMRustDiagnosticKind
1187 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1188 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1191 // This is kept distinct from LLVMGetTypeKind, because when
1192 // a new type kind is added, the Rust-side enum must be
1193 // updated or UB will result.
1194 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1195 switch (unwrap(Ty)->getTypeID()) {
1196 case Type::VoidTyID:
1197 return LLVMVoidTypeKind;
1198 case Type::HalfTyID:
1199 return LLVMHalfTypeKind;
1200 case Type::FloatTyID:
1201 return LLVMFloatTypeKind;
1202 case Type::DoubleTyID:
1203 return LLVMDoubleTypeKind;
1204 case Type::X86_FP80TyID:
1205 return LLVMX86_FP80TypeKind;
1206 case Type::FP128TyID:
1207 return LLVMFP128TypeKind;
1208 case Type::PPC_FP128TyID:
1209 return LLVMPPC_FP128TypeKind;
1210 case Type::LabelTyID:
1211 return LLVMLabelTypeKind;
1212 case Type::MetadataTyID:
1213 return LLVMMetadataTypeKind;
1214 case Type::IntegerTyID:
1215 return LLVMIntegerTypeKind;
1216 case Type::FunctionTyID:
1217 return LLVMFunctionTypeKind;
1218 case Type::StructTyID:
1219 return LLVMStructTypeKind;
1220 case Type::ArrayTyID:
1221 return LLVMArrayTypeKind;
1222 case Type::PointerTyID:
1223 return LLVMPointerTypeKind;
1224 case Type::FixedVectorTyID:
1225 return LLVMVectorTypeKind;
1226 case Type::X86_MMXTyID:
1227 return LLVMX86_MMXTypeKind;
1228 case Type::TokenTyID:
1229 return LLVMTokenTypeKind;
1230 case Type::ScalableVectorTyID:
1231 return LLVMScalableVectorTypeKind;
1232 case Type::BFloatTyID:
1233 return LLVMBFloatTypeKind;
1234 case Type::X86_AMXTyID:
1235 return LLVMX86_AMXTypeKind;
1236 #if LLVM_VERSION_GE(15, 0)
1237 case Type::DXILPointerTyID:
1238 report_fatal_error("Rust does not support DirectX typed pointers.");
1242 report_fatal_error("Unhandled TypeID.");
1245 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1247 #if LLVM_VERSION_LT(13, 0)
1248 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1250 using LLVMInlineAsmDiagHandlerTy = void*;
1253 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1254 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1255 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1256 // with LLVM 13 this function is gone.
1257 #if LLVM_VERSION_LT(13, 0)
1258 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1262 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1263 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1264 #if LLVM_VERSION_GE(13, 0)
1265 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1266 *Cookie = SM->getLocCookie();
1267 return wrap(&SM->getSMDiag());
1269 report_fatal_error("Shouldn't get called on older versions");
1273 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1274 RustStringRef MessageOut,
1275 RustStringRef BufferOut,
1276 LLVMRustDiagnosticLevel* LevelOut,
1278 unsigned* RangesOut,
1279 size_t* NumRanges) {
1280 SMDiagnostic& D = *unwrap(DRef);
1281 RawRustStringOstream MessageOS(MessageOut);
1282 MessageOS << D.getMessage();
1284 switch (D.getKind()) {
1285 case SourceMgr::DK_Error:
1286 *LevelOut = LLVMRustDiagnosticLevel::Error;
1288 case SourceMgr::DK_Warning:
1289 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1291 case SourceMgr::DK_Note:
1292 *LevelOut = LLVMRustDiagnosticLevel::Note;
1294 case SourceMgr::DK_Remark:
1295 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1298 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1301 if (D.getLoc() == SMLoc())
1304 const SourceMgr &LSM = *D.getSourceMgr();
1305 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1306 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1308 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1310 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1311 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1312 for (size_t i = 0; i < *NumRanges; i++) {
1313 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1314 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1320 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1321 LLVMValueRef ParentPad,
1323 LLVMValueRef *LLArgs,
1325 Value **Args = unwrap(LLArgs);
1326 if (ParentPad == nullptr) {
1327 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1328 ParentPad = wrap(Constant::getNullValue(Ty));
1330 return wrap(unwrap(B)->CreateCleanupPad(
1331 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1334 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1335 LLVMValueRef CleanupPad,
1336 LLVMBasicBlockRef UnwindBB) {
1337 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1338 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1341 extern "C" LLVMValueRef
1342 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1343 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1344 Value **Args = unwrap(LLArgs);
1345 return wrap(unwrap(B)->CreateCatchPad(
1346 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1349 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1351 LLVMBasicBlockRef BB) {
1352 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1356 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1357 LLVMValueRef ParentPad,
1358 LLVMBasicBlockRef BB,
1359 unsigned NumHandlers,
1361 if (ParentPad == nullptr) {
1362 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1363 ParentPad = wrap(Constant::getNullValue(Ty));
1365 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1366 NumHandlers, Name));
1369 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1370 LLVMBasicBlockRef Handler) {
1371 Value *CatchSwitch = unwrap(CatchSwitchRef);
1372 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1375 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1376 LLVMValueRef *Inputs,
1377 unsigned NumInputs) {
1378 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1381 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1385 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1386 LLVMValueRef *Args, unsigned NumArgs,
1387 OperandBundleDef *Bundle) {
1388 Value *Callee = unwrap(Fn);
1389 FunctionType *FTy = unwrap<FunctionType>(Ty);
1390 unsigned Len = Bundle ? 1 : 0;
1391 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1392 return wrap(unwrap(B)->CreateCall(
1393 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1396 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1397 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1398 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1401 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1402 LLVMValueRef Dst, unsigned DstAlign,
1403 LLVMValueRef Src, unsigned SrcAlign,
1404 LLVMValueRef Size, bool IsVolatile) {
1405 return wrap(unwrap(B)->CreateMemCpy(
1406 unwrap(Dst), MaybeAlign(DstAlign),
1407 unwrap(Src), MaybeAlign(SrcAlign),
1408 unwrap(Size), IsVolatile));
1411 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1412 LLVMValueRef Dst, unsigned DstAlign,
1413 LLVMValueRef Src, unsigned SrcAlign,
1414 LLVMValueRef Size, bool IsVolatile) {
1415 return wrap(unwrap(B)->CreateMemMove(
1416 unwrap(Dst), MaybeAlign(DstAlign),
1417 unwrap(Src), MaybeAlign(SrcAlign),
1418 unwrap(Size), IsVolatile));
1421 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1422 LLVMValueRef Dst, unsigned DstAlign,
1424 LLVMValueRef Size, bool IsVolatile) {
1425 return wrap(unwrap(B)->CreateMemSet(
1426 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1429 extern "C" LLVMValueRef
1430 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1431 LLVMValueRef *Args, unsigned NumArgs,
1432 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1433 OperandBundleDef *Bundle, const char *Name) {
1434 Value *Callee = unwrap(Fn);
1435 FunctionType *FTy = unwrap<FunctionType>(Ty);
1436 unsigned Len = Bundle ? 1 : 0;
1437 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1438 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1439 makeArrayRef(unwrap(Args), NumArgs),
1443 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1444 LLVMBasicBlockRef BB) {
1445 auto Point = unwrap(BB)->getFirstInsertionPt();
1446 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1449 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1450 const char *Name, size_t NameLen) {
1451 Triple TargetTriple(unwrap(M)->getTargetTriple());
1452 GlobalObject *GV = unwrap<GlobalObject>(V);
1453 if (TargetTriple.supportsCOMDAT()) {
1454 StringRef NameRef(Name, NameLen);
1455 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1459 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1460 GlobalObject *GV = unwrap<GlobalObject>(V);
1461 GV->setComdat(nullptr);
1464 enum class LLVMRustLinkage {
1465 ExternalLinkage = 0,
1466 AvailableExternallyLinkage = 1,
1467 LinkOnceAnyLinkage = 2,
1468 LinkOnceODRLinkage = 3,
1471 AppendingLinkage = 6,
1472 InternalLinkage = 7,
1474 ExternalWeakLinkage = 9,
1478 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1480 case LLVMExternalLinkage:
1481 return LLVMRustLinkage::ExternalLinkage;
1482 case LLVMAvailableExternallyLinkage:
1483 return LLVMRustLinkage::AvailableExternallyLinkage;
1484 case LLVMLinkOnceAnyLinkage:
1485 return LLVMRustLinkage::LinkOnceAnyLinkage;
1486 case LLVMLinkOnceODRLinkage:
1487 return LLVMRustLinkage::LinkOnceODRLinkage;
1488 case LLVMWeakAnyLinkage:
1489 return LLVMRustLinkage::WeakAnyLinkage;
1490 case LLVMWeakODRLinkage:
1491 return LLVMRustLinkage::WeakODRLinkage;
1492 case LLVMAppendingLinkage:
1493 return LLVMRustLinkage::AppendingLinkage;
1494 case LLVMInternalLinkage:
1495 return LLVMRustLinkage::InternalLinkage;
1496 case LLVMPrivateLinkage:
1497 return LLVMRustLinkage::PrivateLinkage;
1498 case LLVMExternalWeakLinkage:
1499 return LLVMRustLinkage::ExternalWeakLinkage;
1500 case LLVMCommonLinkage:
1501 return LLVMRustLinkage::CommonLinkage;
1503 report_fatal_error("Invalid LLVMRustLinkage value!");
1507 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1509 case LLVMRustLinkage::ExternalLinkage:
1510 return LLVMExternalLinkage;
1511 case LLVMRustLinkage::AvailableExternallyLinkage:
1512 return LLVMAvailableExternallyLinkage;
1513 case LLVMRustLinkage::LinkOnceAnyLinkage:
1514 return LLVMLinkOnceAnyLinkage;
1515 case LLVMRustLinkage::LinkOnceODRLinkage:
1516 return LLVMLinkOnceODRLinkage;
1517 case LLVMRustLinkage::WeakAnyLinkage:
1518 return LLVMWeakAnyLinkage;
1519 case LLVMRustLinkage::WeakODRLinkage:
1520 return LLVMWeakODRLinkage;
1521 case LLVMRustLinkage::AppendingLinkage:
1522 return LLVMAppendingLinkage;
1523 case LLVMRustLinkage::InternalLinkage:
1524 return LLVMInternalLinkage;
1525 case LLVMRustLinkage::PrivateLinkage:
1526 return LLVMPrivateLinkage;
1527 case LLVMRustLinkage::ExternalWeakLinkage:
1528 return LLVMExternalWeakLinkage;
1529 case LLVMRustLinkage::CommonLinkage:
1530 return LLVMCommonLinkage;
1532 report_fatal_error("Invalid LLVMRustLinkage value!");
1535 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1536 return toRust(LLVMGetLinkage(V));
1539 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1540 LLVMRustLinkage RustLinkage) {
1541 LLVMSetLinkage(V, fromRust(RustLinkage));
1544 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1545 LLVMValueRef ConstantVal,
1546 LLVMValueRef *ConstantIndices,
1547 unsigned NumIndices) {
1548 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1550 Constant *Val = unwrap<Constant>(ConstantVal);
1551 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1554 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1555 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1556 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1558 auto C = unwrap<llvm::ConstantInt>(CV);
1559 if (C->getBitWidth() > 128) { return false; }
1561 #if LLVM_VERSION_GE(15, 0)
1563 AP = C->getValue().sext(128);
1565 AP = C->getValue().zext(128);
1569 AP = C->getValue().sextOrSelf(128);
1571 AP = C->getValue().zextOrSelf(128);
1574 *low = AP.getLoBits(64).getZExtValue();
1575 *high = AP.getHiBits(64).getZExtValue();
1579 enum class LLVMRustVisibility {
1585 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1587 case LLVMDefaultVisibility:
1588 return LLVMRustVisibility::Default;
1589 case LLVMHiddenVisibility:
1590 return LLVMRustVisibility::Hidden;
1591 case LLVMProtectedVisibility:
1592 return LLVMRustVisibility::Protected;
1594 report_fatal_error("Invalid LLVMRustVisibility value!");
1597 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1599 case LLVMRustVisibility::Default:
1600 return LLVMDefaultVisibility;
1601 case LLVMRustVisibility::Hidden:
1602 return LLVMHiddenVisibility;
1603 case LLVMRustVisibility::Protected:
1604 return LLVMProtectedVisibility;
1606 report_fatal_error("Invalid LLVMRustVisibility value!");
1609 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1610 return toRust(LLVMGetVisibility(V));
1613 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1614 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1615 LLVMTypeRef DestTy, bool isSigned) {
1616 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1619 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1620 LLVMRustVisibility RustVisibility) {
1621 LLVMSetVisibility(V, fromRust(RustVisibility));
1624 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1625 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1628 struct LLVMRustModuleBuffer {
1632 extern "C" LLVMRustModuleBuffer*
1633 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1634 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1636 raw_string_ostream OS(Ret->data);
1638 legacy::PassManager PM;
1639 PM.add(createBitcodeWriterPass(OS));
1643 return Ret.release();
1647 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1651 extern "C" const void*
1652 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1653 return Buffer->data.data();
1657 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1658 return Buffer->data.length();
1662 LLVMRustModuleCost(LLVMModuleRef M) {
1663 auto f = unwrap(M)->functions();
1664 return std::distance(std::begin(f), std::end(f));
1667 // Vector reductions:
1668 extern "C" LLVMValueRef
1669 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1670 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1672 extern "C" LLVMValueRef
1673 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1674 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1676 extern "C" LLVMValueRef
1677 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1678 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1680 extern "C" LLVMValueRef
1681 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1682 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1684 extern "C" LLVMValueRef
1685 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1686 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1688 extern "C" LLVMValueRef
1689 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1690 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1692 extern "C" LLVMValueRef
1693 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1694 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1696 extern "C" LLVMValueRef
1697 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1698 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1700 extern "C" LLVMValueRef
1701 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1702 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1704 extern "C" LLVMValueRef
1705 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1706 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1707 I->setHasNoNaNs(NoNaN);
1710 extern "C" LLVMValueRef
1711 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1712 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1713 I->setHasNoNaNs(NoNaN);
1717 extern "C" LLVMValueRef
1718 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1719 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1721 extern "C" LLVMValueRef
1722 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1723 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1726 // This struct contains all necessary info about a symbol exported from a DLL.
1727 struct LLVMRustCOFFShortExport {
1729 bool ordinal_present;
1730 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1734 // Machine must be a COFF machine type, as defined in PE specs.
1735 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1736 const char* ImportName,
1738 const LLVMRustCOFFShortExport* Exports,
1743 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1744 ConvertedExports.reserve(NumExports);
1746 for (size_t i = 0; i < NumExports; ++i) {
1747 bool ordinal_present = Exports[i].ordinal_present;
1748 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1749 ConvertedExports.push_back(llvm::object::COFFShortExport{
1750 Exports[i].name, // Name
1751 std::string{}, // ExtName
1752 std::string{}, // SymbolName
1753 std::string{}, // AliasTarget
1755 ordinal_present, // Noname
1762 auto Error = llvm::object::writeImportLibrary(
1766 static_cast<llvm::COFF::MachineTypes>(Machine),
1769 std::string errorString;
1770 llvm::raw_string_ostream stream(errorString);
1773 LLVMRustSetLastError(errorString.c_str());
1774 return LLVMRustResult::Failure;
1776 return LLVMRustResult::Success;
1780 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1781 extern "C" DiagnosticHandler *
1782 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1783 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1784 return DH.release();
1787 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1788 // handling. Ownership of the handler is moved to the LLVMContext.
1789 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1790 DiagnosticHandler *DH) {
1791 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1794 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1796 // Configures a diagnostic handler that invokes provided callback when a
1797 // backend needs to emit a diagnostic.
1799 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1800 // the RemarkPasses array specifies individual passes for which remarks will be
1802 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1803 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1804 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1805 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1807 class RustDiagnosticHandler final : public DiagnosticHandler {
1809 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1810 void *DiagnosticHandlerContext,
1811 bool RemarkAllPasses,
1812 std::vector<std::string> RemarkPasses)
1813 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1814 DiagnosticHandlerContext(DiagnosticHandlerContext),
1815 RemarkAllPasses(RemarkAllPasses),
1816 RemarkPasses(RemarkPasses) {}
1818 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1819 if (DiagnosticHandlerCallback) {
1820 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1826 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1827 return isRemarkEnabled(PassName);
1830 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1831 return isRemarkEnabled(PassName);
1834 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1835 return isRemarkEnabled(PassName);
1838 bool isAnyRemarkEnabled() const override {
1839 return RemarkAllPasses || !RemarkPasses.empty();
1843 bool isRemarkEnabled(StringRef PassName) const {
1844 if (RemarkAllPasses)
1847 for (auto &Pass : RemarkPasses)
1848 if (Pass == PassName)
1854 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1855 void *DiagnosticHandlerContext = nullptr;
1857 bool RemarkAllPasses = false;
1858 std::vector<std::string> RemarkPasses;
1861 std::vector<std::string> Passes;
1862 for (size_t I = 0; I != RemarkPassesLen; ++I)
1863 Passes.push_back(RemarkPasses[I]);
1865 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1866 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
1869 extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
1870 RawRustStringOstream OS(Str);
1871 GlobalValue *GV = unwrap<GlobalValue>(V);
1872 Mangler().getNameWithPrefix(OS, GV, true);
1875 // LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just
1876 // use its implementation.
1877 #if LLVM_VERSION_LT(15, 0)
1878 extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
1879 return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));