1 #include "LLVMWrapper.h"
2 #include "llvm/IR/DebugInfoMetadata.h"
3 #include "llvm/IR/DiagnosticHandler.h"
4 #include "llvm/IR/DiagnosticInfo.h"
5 #include "llvm/IR/DiagnosticPrinter.h"
6 #include "llvm/IR/GlobalVariable.h"
7 #include "llvm/IR/Instructions.h"
8 #include "llvm/IR/Intrinsics.h"
9 #include "llvm/IR/Mangler.h"
10 #include "llvm/Object/Archive.h"
11 #include "llvm/Object/COFFImportFile.h"
12 #include "llvm/Object/ObjectFile.h"
13 #include "llvm/Pass.h"
14 #include "llvm/Bitcode/BitcodeWriterPass.h"
15 #include "llvm/Support/Signals.h"
16 #include "llvm/ADT/Optional.h"
20 //===----------------------------------------------------------------------===
22 // This file defines alternate interfaces to core functions that are more
23 // readily callable by Rust's FFI.
25 //===----------------------------------------------------------------------===
28 using namespace llvm::sys;
29 using namespace llvm::object;
31 // LLVMAtomicOrdering is already an enum - don't create another
33 static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
35 case LLVMAtomicOrderingNotAtomic:
36 return AtomicOrdering::NotAtomic;
37 case LLVMAtomicOrderingUnordered:
38 return AtomicOrdering::Unordered;
39 case LLVMAtomicOrderingMonotonic:
40 return AtomicOrdering::Monotonic;
41 case LLVMAtomicOrderingAcquire:
42 return AtomicOrdering::Acquire;
43 case LLVMAtomicOrderingRelease:
44 return AtomicOrdering::Release;
45 case LLVMAtomicOrderingAcquireRelease:
46 return AtomicOrdering::AcquireRelease;
47 case LLVMAtomicOrderingSequentiallyConsistent:
48 return AtomicOrdering::SequentiallyConsistent;
51 report_fatal_error("Invalid LLVMAtomicOrdering value!");
54 static LLVM_THREAD_LOCAL char *LastError;
56 // Custom error handler for fatal LLVM errors.
58 // Notably it exits the process with code 101, unlike LLVM's default of 1.
59 static void FatalErrorHandler(void *UserData,
60 #if LLVM_VERSION_LT(14, 0)
61 const std::string& Reason,
66 // Do the same thing that the default error handler does.
67 std::cerr << "LLVM ERROR: " << Reason << std::endl;
69 // Since this error handler exits the process, we have to run any cleanup that
70 // LLVM would run after handling the error. This might change with an LLVM
72 sys::RunInterruptHandlers();
77 extern "C" void LLVMRustInstallFatalErrorHandler() {
78 install_fatal_error_handler(FatalErrorHandler);
81 extern "C" void LLVMRustDisableSystemDialogsOnCrash() {
82 sys::DisableSystemDialogsOnCrash();
85 extern "C" char *LLVMRustGetLastError(void) {
86 char *Ret = LastError;
91 extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) {
92 return unwrap(M)->getInstructionCount();
95 extern "C" void LLVMRustSetLastError(const char *Err) {
96 free((void *)LastError);
97 LastError = strdup(Err);
100 extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
101 auto ctx = new LLVMContext();
102 ctx->setDiscardValueNames(shouldDiscardNames);
106 extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
107 const char *Triple) {
108 unwrap(M)->setTargetTriple(Triple::normalize(Triple));
111 extern "C" void LLVMRustPrintPassTimings() {
112 raw_fd_ostream OS(2, false); // stderr.
113 TimerGroup::printAll(OS);
116 extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
118 return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
121 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
124 LLVMTypeRef FunctionTy) {
125 return wrap(unwrap(M)
126 ->getOrInsertFunction(StringRef(Name, NameLen),
127 unwrap<FunctionType>(FunctionTy))
132 extern "C" LLVMValueRef
133 LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
134 Module *Mod = unwrap(M);
135 StringRef NameRef(Name, NameLen);
137 // We don't use Module::getOrInsertGlobal because that returns a Constant*,
138 // which may either be the real GlobalVariable*, or a constant bitcast of it
139 // if our type doesn't match the original declaration. We always want the
140 // GlobalVariable* so we can access linkage, visibility, etc.
141 GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true);
143 GV = new GlobalVariable(*Mod, unwrap(Ty), false,
144 GlobalValue::ExternalLinkage, nullptr, NameRef);
148 extern "C" LLVMValueRef
149 LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
150 return wrap(new GlobalVariable(*unwrap(M),
153 GlobalValue::PrivateLinkage,
157 extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
158 return wrap(Type::getMetadataTy(*unwrap(C)));
161 static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
164 return Attribute::AlwaysInline;
166 return Attribute::ByVal;
168 return Attribute::Cold;
170 return Attribute::InlineHint;
172 return Attribute::MinSize;
174 return Attribute::Naked;
176 return Attribute::NoAlias;
178 return Attribute::NoCapture;
180 return Attribute::NoCfCheck;
182 return Attribute::NoInline;
184 return Attribute::NonNull;
186 return Attribute::NoRedZone;
188 return Attribute::NoReturn;
190 return Attribute::NoUnwind;
191 case OptimizeForSize:
192 return Attribute::OptimizeForSize;
194 return Attribute::ReadOnly;
196 return Attribute::SExt;
198 return Attribute::StructRet;
200 return Attribute::UWTable;
202 return Attribute::ZExt;
204 return Attribute::InReg;
206 return Attribute::SanitizeThread;
207 case SanitizeAddress:
208 return Attribute::SanitizeAddress;
210 return Attribute::SanitizeMemory;
212 return Attribute::NonLazyBind;
214 return Attribute::OptimizeNone;
216 return Attribute::ReturnsTwice;
218 return Attribute::ReadNone;
219 case InaccessibleMemOnly:
220 return Attribute::InaccessibleMemOnly;
221 case SanitizeHWAddress:
222 return Attribute::SanitizeHWAddress;
224 return Attribute::WillReturn;
225 case StackProtectReq:
226 return Attribute::StackProtectReq;
227 case StackProtectStrong:
228 return Attribute::StackProtectStrong;
230 return Attribute::StackProtect;
232 return Attribute::NoUndef;
234 return Attribute::SanitizeMemTag;
235 case ShadowCallStack:
236 return Attribute::ShadowCallStack;
238 report_fatal_error("bad AttributeKind");
241 template<typename T> static inline void AddAttributes(T *t, unsigned Index,
242 LLVMAttributeRef *Attrs, size_t AttrsLen) {
243 AttributeList PAL = t->getAttributes();
244 AttributeList PALNew;
245 #if LLVM_VERSION_LT(14, 0)
247 for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
248 B.addAttribute(unwrap(Attr));
249 PALNew = PAL.addAttributes(t->getContext(), Index, B);
251 AttrBuilder B(t->getContext());
252 for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
253 B.addAttribute(unwrap(Attr));
254 PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B);
256 t->setAttributes(PALNew);
259 extern "C" void LLVMRustAddFunctionAttributes(LLVMValueRef Fn, unsigned Index,
260 LLVMAttributeRef *Attrs, size_t AttrsLen) {
261 Function *F = unwrap<Function>(Fn);
262 AddAttributes(F, Index, Attrs, AttrsLen);
265 extern "C" void LLVMRustAddCallSiteAttributes(LLVMValueRef Instr, unsigned Index,
266 LLVMAttributeRef *Attrs, size_t AttrsLen) {
267 CallBase *Call = unwrap<CallBase>(Instr);
268 AddAttributes(Call, Index, Attrs, AttrsLen);
271 extern "C" LLVMAttributeRef LLVMRustCreateAttrNoValue(LLVMContextRef C,
272 LLVMRustAttribute RustAttr) {
273 return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr)));
276 extern "C" LLVMAttributeRef LLVMRustCreateAlignmentAttr(LLVMContextRef C,
278 return wrap(Attribute::getWithAlignment(*unwrap(C), llvm::Align(Bytes)));
281 extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableAttr(LLVMContextRef C,
283 return wrap(Attribute::getWithDereferenceableBytes(*unwrap(C), Bytes));
286 extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableOrNullAttr(LLVMContextRef C,
288 return wrap(Attribute::getWithDereferenceableOrNullBytes(*unwrap(C), Bytes));
291 extern "C" LLVMAttributeRef LLVMRustCreateByValAttr(LLVMContextRef C, LLVMTypeRef Ty) {
292 return wrap(Attribute::getWithByValType(*unwrap(C), unwrap(Ty)));
295 extern "C" LLVMAttributeRef LLVMRustCreateStructRetAttr(LLVMContextRef C, LLVMTypeRef Ty) {
296 return wrap(Attribute::getWithStructRetType(*unwrap(C), unwrap(Ty)));
299 extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Async) {
300 #if LLVM_VERSION_LT(15, 0)
301 return wrap(Attribute::get(*unwrap(C), Attribute::UWTable));
303 return wrap(Attribute::getWithUWTableKind(
304 *unwrap(C), Async ? UWTableKind::Async : UWTableKind::Sync));
308 // Enable a fast-math flag
310 // https://llvm.org/docs/LangRef.html#fast-math-flags
311 extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
312 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
317 extern "C" LLVMValueRef
318 LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
319 const char *Name, LLVMAtomicOrdering Order) {
320 Value *Ptr = unwrap(Source);
321 LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
322 LI->setAtomic(fromRust(Order));
326 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
329 LLVMAtomicOrdering Order) {
330 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
331 SI->setAtomic(fromRust(Order));
335 // FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
336 // once we raise our minimum support to LLVM 10.
337 extern "C" LLVMValueRef
338 LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
339 LLVMValueRef Old, LLVMValueRef Source,
340 LLVMAtomicOrdering Order,
341 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
342 #if LLVM_VERSION_GE(13,0)
343 // Rust probably knows the alignment of the target value and should be able to
344 // specify something more precise than MaybeAlign here. See also
345 // https://reviews.llvm.org/D97224 which may be a useful reference.
346 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
347 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
348 fromRust(FailureOrder));
350 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
351 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
352 fromRust(FailureOrder));
358 enum class LLVMRustSynchronizationScope {
363 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
365 case LLVMRustSynchronizationScope::SingleThread:
366 return SyncScope::SingleThread;
367 case LLVMRustSynchronizationScope::CrossThread:
368 return SyncScope::System;
370 report_fatal_error("bad SynchronizationScope.");
374 extern "C" LLVMValueRef
375 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
376 LLVMRustSynchronizationScope Scope) {
377 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
380 enum class LLVMRustAsmDialect {
385 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
387 case LLVMRustAsmDialect::Att:
388 return InlineAsm::AD_ATT;
389 case LLVMRustAsmDialect::Intel:
390 return InlineAsm::AD_Intel;
392 report_fatal_error("bad AsmDialect.");
396 extern "C" LLVMValueRef
397 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
398 char *Constraints, size_t ConstraintsLen,
399 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
400 LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
401 #if LLVM_VERSION_GE(13, 0)
402 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
403 StringRef(AsmString, AsmStringLen),
404 StringRef(Constraints, ConstraintsLen),
405 HasSideEffects, IsAlignStack,
406 fromRust(Dialect), CanThrow));
408 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
409 StringRef(AsmString, AsmStringLen),
410 StringRef(Constraints, ConstraintsLen),
411 HasSideEffects, IsAlignStack,
416 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
417 size_t ConstraintsLen) {
418 #if LLVM_VERSION_LT(15, 0)
419 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
420 StringRef(Constraints, ConstraintsLen));
422 // llvm::Error converts to true if it is an error.
423 return !llvm::errorToBool(InlineAsm::verify(
424 unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen)));
428 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
430 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
433 typedef DIBuilder *LLVMRustDIBuilderRef;
435 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
436 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
439 #define DIDescriptor DIScope
440 #define DIArray DINodeArray
441 #define unwrapDI unwrapDIPtr
443 // These values **must** match debuginfo::DIFlags! They also *happen*
444 // to match LLVM, but that isn't required as we do giant sets of
445 // matching below. The value shouldn't be directly passed to LLVM.
446 enum class LLVMRustDIFlags : uint32_t {
451 FlagFwdDecl = (1 << 2),
452 FlagAppleBlock = (1 << 3),
453 FlagBlockByrefStruct = (1 << 4),
454 FlagVirtual = (1 << 5),
455 FlagArtificial = (1 << 6),
456 FlagExplicit = (1 << 7),
457 FlagPrototyped = (1 << 8),
458 FlagObjcClassComplete = (1 << 9),
459 FlagObjectPointer = (1 << 10),
460 FlagVector = (1 << 11),
461 FlagStaticMember = (1 << 12),
462 FlagLValueReference = (1 << 13),
463 FlagRValueReference = (1 << 14),
464 FlagExternalTypeRef = (1 << 15),
465 FlagIntroducedVirtual = (1 << 18),
466 FlagBitField = (1 << 19),
467 FlagNoReturn = (1 << 20),
468 // Do not add values that are not supported by the minimum LLVM
469 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
472 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
473 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
474 static_cast<uint32_t>(B));
477 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
478 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
479 static_cast<uint32_t>(B));
482 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
486 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
488 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
489 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
492 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
493 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
495 switch (visibility(Flags)) {
496 case LLVMRustDIFlags::FlagPrivate:
497 Result |= DINode::DIFlags::FlagPrivate;
499 case LLVMRustDIFlags::FlagProtected:
500 Result |= DINode::DIFlags::FlagProtected;
502 case LLVMRustDIFlags::FlagPublic:
503 Result |= DINode::DIFlags::FlagPublic;
506 // The rest are handled below
510 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
511 Result |= DINode::DIFlags::FlagFwdDecl;
513 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
514 Result |= DINode::DIFlags::FlagAppleBlock;
516 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
517 Result |= DINode::DIFlags::FlagVirtual;
519 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
520 Result |= DINode::DIFlags::FlagArtificial;
522 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
523 Result |= DINode::DIFlags::FlagExplicit;
525 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
526 Result |= DINode::DIFlags::FlagPrototyped;
528 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
529 Result |= DINode::DIFlags::FlagObjcClassComplete;
531 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
532 Result |= DINode::DIFlags::FlagObjectPointer;
534 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
535 Result |= DINode::DIFlags::FlagVector;
537 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
538 Result |= DINode::DIFlags::FlagStaticMember;
540 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
541 Result |= DINode::DIFlags::FlagLValueReference;
543 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
544 Result |= DINode::DIFlags::FlagRValueReference;
546 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
547 Result |= DINode::DIFlags::FlagIntroducedVirtual;
549 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
550 Result |= DINode::DIFlags::FlagBitField;
552 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
553 Result |= DINode::DIFlags::FlagNoReturn;
559 // These values **must** match debuginfo::DISPFlags! They also *happen*
560 // to match LLVM, but that isn't required as we do giant sets of
561 // matching below. The value shouldn't be directly passed to LLVM.
562 enum class LLVMRustDISPFlags : uint32_t {
565 SPFlagPureVirtual = 2,
566 SPFlagLocalToUnit = (1 << 2),
567 SPFlagDefinition = (1 << 3),
568 SPFlagOptimized = (1 << 4),
569 SPFlagMainSubprogram = (1 << 5),
570 // Do not add values that are not supported by the minimum LLVM
571 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
572 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
575 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
576 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
577 static_cast<uint32_t>(B));
580 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
581 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
582 static_cast<uint32_t>(B));
585 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
589 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
591 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
592 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
595 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
596 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
598 switch (virtuality(SPFlags)) {
599 case LLVMRustDISPFlags::SPFlagVirtual:
600 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
602 case LLVMRustDISPFlags::SPFlagPureVirtual:
603 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
606 // The rest are handled below
610 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
611 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
613 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
614 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
616 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
617 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
619 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
620 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
626 enum class LLVMRustDebugEmissionKind {
632 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
634 case LLVMRustDebugEmissionKind::NoDebug:
635 return DICompileUnit::DebugEmissionKind::NoDebug;
636 case LLVMRustDebugEmissionKind::FullDebug:
637 return DICompileUnit::DebugEmissionKind::FullDebug;
638 case LLVMRustDebugEmissionKind::LineTablesOnly:
639 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
641 report_fatal_error("bad DebugEmissionKind.");
645 enum class LLVMRustChecksumKind {
652 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
654 case LLVMRustChecksumKind::None:
656 case LLVMRustChecksumKind::MD5:
657 return DIFile::ChecksumKind::CSK_MD5;
658 case LLVMRustChecksumKind::SHA1:
659 return DIFile::ChecksumKind::CSK_SHA1;
660 case LLVMRustChecksumKind::SHA256:
661 return DIFile::ChecksumKind::CSK_SHA256;
663 report_fatal_error("bad ChecksumKind.");
667 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
668 return DEBUG_METADATA_VERSION;
671 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
673 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
675 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
677 extern "C" void LLVMRustAddModuleFlag(
679 Module::ModFlagBehavior MergeBehavior,
682 unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
685 extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
687 return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
690 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
691 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
694 extern "C" void LLVMRustGlobalAddMetadata(
695 LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) {
696 unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
699 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
700 return new DIBuilder(*unwrap(M));
703 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
707 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
711 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
712 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
713 const char *Producer, size_t ProducerLen, bool isOptimized,
714 const char *Flags, unsigned RuntimeVer,
715 const char *SplitName, size_t SplitNameLen,
716 LLVMRustDebugEmissionKind Kind,
717 uint64_t DWOId, bool SplitDebugInlining) {
718 auto *File = unwrapDI<DIFile>(FileRef);
720 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
721 isOptimized, Flags, RuntimeVer,
722 StringRef(SplitName, SplitNameLen),
723 fromRust(Kind), DWOId, SplitDebugInlining));
726 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
727 LLVMRustDIBuilderRef Builder,
728 const char *Filename, size_t FilenameLen,
729 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
730 const char *Checksum, size_t ChecksumLen) {
731 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
732 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
734 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
735 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
736 StringRef(Directory, DirectoryLen),
740 extern "C" LLVMMetadataRef
741 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
742 LLVMMetadataRef ParameterTypes) {
743 return wrap(Builder->createSubroutineType(
744 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
747 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
748 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
749 const char *Name, size_t NameLen,
750 const char *LinkageName, size_t LinkageNameLen,
751 LLVMMetadataRef File, unsigned LineNo,
752 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
753 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
754 LLVMMetadataRef Decl) {
755 DITemplateParameterArray TParams =
756 DITemplateParameterArray(unwrap<MDTuple>(TParam));
757 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
758 DINode::DIFlags llvmFlags = fromRust(Flags);
759 DISubprogram *Sub = Builder->createFunction(
760 unwrapDI<DIScope>(Scope),
761 StringRef(Name, NameLen),
762 StringRef(LinkageName, LinkageNameLen),
763 unwrapDI<DIFile>(File), LineNo,
764 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
765 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
767 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
771 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
772 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
773 uint64_t SizeInBits, unsigned Encoding) {
774 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
777 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
778 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
779 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
780 return wrap(Builder->createTypedef(
781 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
782 LineNo, unwrapDIPtr<DIScope>(Scope)));
785 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
786 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
787 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
788 const char *Name, size_t NameLen) {
789 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
790 SizeInBits, AlignInBits,
792 StringRef(Name, NameLen)));
795 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
796 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
797 const char *Name, size_t NameLen,
798 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
799 uint32_t AlignInBits, LLVMRustDIFlags Flags,
800 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
801 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
802 const char *UniqueId, size_t UniqueIdLen) {
803 return wrap(Builder->createStructType(
804 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
805 unwrapDI<DIFile>(File), LineNumber,
806 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
807 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
808 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
811 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
812 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
813 const char *Name, size_t NameLen,
814 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
815 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
816 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
817 return wrap(Builder->createVariantPart(
818 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
819 unwrapDI<DIFile>(File), LineNumber,
820 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
821 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
824 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
825 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
826 const char *Name, size_t NameLen,
827 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
828 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
829 LLVMMetadataRef Ty) {
830 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
831 StringRef(Name, NameLen),
832 unwrapDI<DIFile>(File), LineNo,
833 SizeInBits, AlignInBits, OffsetInBits,
834 fromRust(Flags), unwrapDI<DIType>(Ty)));
837 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
838 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
839 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
840 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
841 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
842 llvm::ConstantInt* D = nullptr;
844 D = unwrap<llvm::ConstantInt>(Discriminant);
846 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
847 StringRef(Name, NameLen),
848 unwrapDI<DIFile>(File), LineNo,
849 SizeInBits, AlignInBits, OffsetInBits, D,
850 fromRust(Flags), unwrapDI<DIType>(Ty)));
853 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
854 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
855 LLVMMetadataRef File, unsigned Line, unsigned Col) {
856 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
857 unwrapDI<DIFile>(File), Line, Col));
860 extern "C" LLVMMetadataRef
861 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
862 LLVMMetadataRef Scope,
863 LLVMMetadataRef File) {
864 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
865 unwrapDI<DIFile>(File)));
868 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
869 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
870 const char *Name, size_t NameLen,
871 const char *LinkageName, size_t LinkageNameLen,
872 LLVMMetadataRef File, unsigned LineNo,
873 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
874 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
875 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
877 llvm::DIExpression *InitExpr = nullptr;
878 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
879 InitExpr = Builder->createConstantValueExpression(
880 IntVal->getValue().getSExtValue());
881 } else if (llvm::ConstantFP *FPVal =
882 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
883 InitExpr = Builder->createConstantValueExpression(
884 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
887 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
888 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
889 StringRef(LinkageName, LinkageNameLen),
890 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
891 /* isDefined */ true,
892 InitExpr, unwrapDIPtr<MDNode>(Decl),
893 /* templateParams */ nullptr,
896 InitVal->setMetadata("dbg", VarExpr);
898 return wrap(VarExpr);
901 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
902 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
903 const char *Name, size_t NameLen,
904 LLVMMetadataRef File, unsigned LineNo,
905 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
906 unsigned ArgNo, uint32_t AlignInBits) {
907 if (Tag == 0x100) { // DW_TAG_auto_variable
908 return wrap(Builder->createAutoVariable(
909 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
910 unwrapDI<DIFile>(File), LineNo,
911 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
913 return wrap(Builder->createParameterVariable(
914 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
915 unwrapDI<DIFile>(File), LineNo,
916 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
920 extern "C" LLVMMetadataRef
921 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
922 uint32_t AlignInBits, LLVMMetadataRef Ty,
923 LLVMMetadataRef Subscripts) {
925 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
926 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
929 extern "C" LLVMMetadataRef
930 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
932 return wrap(Builder->getOrCreateSubrange(Lo, Count));
935 extern "C" LLVMMetadataRef
936 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
937 LLVMMetadataRef *Ptr, unsigned Count) {
938 Metadata **DataValue = unwrap(Ptr);
940 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
943 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
944 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
945 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
946 LLVMBasicBlockRef InsertAtEnd) {
947 return wrap(Builder->insertDeclare(
948 unwrap(V), unwrap<DILocalVariable>(VarInfo),
949 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
950 DebugLoc(cast<MDNode>(unwrap(DL))),
951 unwrap(InsertAtEnd)));
954 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
955 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
956 int64_t Value, bool IsUnsigned) {
957 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
960 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
961 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
962 const char *Name, size_t NameLen,
963 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
964 uint32_t AlignInBits, LLVMMetadataRef Elements,
965 LLVMMetadataRef ClassTy, bool IsScoped) {
966 return wrap(Builder->createEnumerationType(
967 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
968 unwrapDI<DIFile>(File), LineNumber,
969 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
970 unwrapDI<DIType>(ClassTy), "", IsScoped));
973 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
974 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
975 const char *Name, size_t NameLen,
976 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
977 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
978 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
979 return wrap(Builder->createUnionType(
980 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
981 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
982 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
983 StringRef(UniqueId, UniqueIdLen)));
986 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
987 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
988 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
989 bool IsDefault = false; // FIXME: should we ever set this true?
990 return wrap(Builder->createTemplateTypeParameter(
991 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
994 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
995 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
996 const char *Name, size_t NameLen, bool ExportSymbols) {
997 return wrap(Builder->createNameSpace(
998 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1003 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1004 LLVMMetadataRef CompositeTy,
1005 LLVMMetadataRef Elements,
1006 LLVMMetadataRef Params) {
1007 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1008 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1009 DINodeArray(unwrap<MDTuple>(Params)));
1012 extern "C" LLVMMetadataRef
1013 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1014 LLVMMetadataRef ScopeRef,
1015 LLVMMetadataRef InlinedAt) {
1016 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1017 DILocation *Loc = DILocation::get(
1018 Scope->getContext(), Line, Column, Scope,
1019 unwrapDIPtr<MDNode>(InlinedAt));
1023 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1024 return dwarf::DW_OP_deref;
1027 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1028 return dwarf::DW_OP_plus_uconst;
1031 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1032 RawRustStringOstream OS(Str);
1033 unwrap<llvm::Type>(Ty)->print(OS);
1036 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1037 RustStringRef Str) {
1038 RawRustStringOstream OS(Str);
1043 unwrap<llvm::Value>(V)->getType()->print(OS);
1045 unwrap<llvm::Value>(V)->print(OS);
1050 // LLVMArrayType function does not support 64-bit ElementCount
1051 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1052 uint64_t ElementCount) {
1053 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1056 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1058 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1059 RawRustStringOstream OS(Str);
1060 unwrap(T)->print(OS);
1063 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1064 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1065 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1066 RustStringRef FilenameOut, RustStringRef MessageOut) {
1067 // Undefined to call this not on an optimization diagnostic!
1068 llvm::DiagnosticInfoOptimizationBase *Opt =
1069 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1071 RawRustStringOstream PassNameOS(PassNameOut);
1072 PassNameOS << Opt->getPassName();
1073 *FunctionOut = wrap(&Opt->getFunction());
1075 RawRustStringOstream FilenameOS(FilenameOut);
1076 DiagnosticLocation loc = Opt->getLocation();
1077 if (loc.isValid()) {
1078 *Line = loc.getLine();
1079 *Column = loc.getColumn();
1080 FilenameOS << loc.getAbsolutePath();
1083 RawRustStringOstream MessageOS(MessageOut);
1084 MessageOS << Opt->getMsg();
1087 enum class LLVMRustDiagnosticLevel {
1095 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1096 LLVMRustDiagnosticLevel *LevelOut,
1097 unsigned *CookieOut,
1098 LLVMTwineRef *MessageOut) {
1099 // Undefined to call this not on an inline assembly diagnostic!
1100 llvm::DiagnosticInfoInlineAsm *IA =
1101 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1103 *CookieOut = IA->getLocCookie();
1104 *MessageOut = wrap(&IA->getMsgStr());
1106 switch (IA->getSeverity()) {
1108 *LevelOut = LLVMRustDiagnosticLevel::Error;
1111 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1114 *LevelOut = LLVMRustDiagnosticLevel::Note;
1117 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1120 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1124 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1125 RustStringRef Str) {
1126 RawRustStringOstream OS(Str);
1127 DiagnosticPrinterRawOStream DP(OS);
1128 unwrap(DI)->print(DP);
1131 enum class LLVMRustDiagnosticKind {
1135 DebugMetadataVersion,
1138 OptimizationRemarkMissed,
1139 OptimizationRemarkAnalysis,
1140 OptimizationRemarkAnalysisFPCommute,
1141 OptimizationRemarkAnalysisAliasing,
1142 OptimizationRemarkOther,
1143 OptimizationFailure,
1150 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1153 return LLVMRustDiagnosticKind::InlineAsm;
1155 return LLVMRustDiagnosticKind::StackSize;
1156 case DK_DebugMetadataVersion:
1157 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1158 case DK_SampleProfile:
1159 return LLVMRustDiagnosticKind::SampleProfile;
1160 case DK_OptimizationRemark:
1161 case DK_MachineOptimizationRemark:
1162 return LLVMRustDiagnosticKind::OptimizationRemark;
1163 case DK_OptimizationRemarkMissed:
1164 case DK_MachineOptimizationRemarkMissed:
1165 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1166 case DK_OptimizationRemarkAnalysis:
1167 case DK_MachineOptimizationRemarkAnalysis:
1168 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1169 case DK_OptimizationRemarkAnalysisFPCommute:
1170 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1171 case DK_OptimizationRemarkAnalysisAliasing:
1172 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1174 return LLVMRustDiagnosticKind::PGOProfile;
1176 return LLVMRustDiagnosticKind::Linker;
1177 case DK_Unsupported:
1178 return LLVMRustDiagnosticKind::Unsupported;
1179 #if LLVM_VERSION_GE(13, 0)
1181 return LLVMRustDiagnosticKind::SrcMgr;
1184 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1185 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1186 : LLVMRustDiagnosticKind::Other;
1190 extern "C" LLVMRustDiagnosticKind
1191 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1192 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1195 // This is kept distinct from LLVMGetTypeKind, because when
1196 // a new type kind is added, the Rust-side enum must be
1197 // updated or UB will result.
1198 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1199 switch (unwrap(Ty)->getTypeID()) {
1200 case Type::VoidTyID:
1201 return LLVMVoidTypeKind;
1202 case Type::HalfTyID:
1203 return LLVMHalfTypeKind;
1204 case Type::FloatTyID:
1205 return LLVMFloatTypeKind;
1206 case Type::DoubleTyID:
1207 return LLVMDoubleTypeKind;
1208 case Type::X86_FP80TyID:
1209 return LLVMX86_FP80TypeKind;
1210 case Type::FP128TyID:
1211 return LLVMFP128TypeKind;
1212 case Type::PPC_FP128TyID:
1213 return LLVMPPC_FP128TypeKind;
1214 case Type::LabelTyID:
1215 return LLVMLabelTypeKind;
1216 case Type::MetadataTyID:
1217 return LLVMMetadataTypeKind;
1218 case Type::IntegerTyID:
1219 return LLVMIntegerTypeKind;
1220 case Type::FunctionTyID:
1221 return LLVMFunctionTypeKind;
1222 case Type::StructTyID:
1223 return LLVMStructTypeKind;
1224 case Type::ArrayTyID:
1225 return LLVMArrayTypeKind;
1226 case Type::PointerTyID:
1227 return LLVMPointerTypeKind;
1228 case Type::FixedVectorTyID:
1229 return LLVMVectorTypeKind;
1230 case Type::X86_MMXTyID:
1231 return LLVMX86_MMXTypeKind;
1232 case Type::TokenTyID:
1233 return LLVMTokenTypeKind;
1234 case Type::ScalableVectorTyID:
1235 return LLVMScalableVectorTypeKind;
1236 case Type::BFloatTyID:
1237 return LLVMBFloatTypeKind;
1238 case Type::X86_AMXTyID:
1239 return LLVMX86_AMXTypeKind;
1240 #if LLVM_VERSION_GE(15, 0)
1241 case Type::DXILPointerTyID:
1242 report_fatal_error("Rust does not support DirectX typed pointers.");
1246 report_fatal_error("Unhandled TypeID.");
1249 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1251 #if LLVM_VERSION_LT(13, 0)
1252 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1254 using LLVMInlineAsmDiagHandlerTy = void*;
1257 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1258 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1259 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1260 // with LLVM 13 this function is gone.
1261 #if LLVM_VERSION_LT(13, 0)
1262 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1266 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1267 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1268 #if LLVM_VERSION_GE(13, 0)
1269 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1270 *Cookie = SM->getLocCookie();
1271 return wrap(&SM->getSMDiag());
1273 report_fatal_error("Shouldn't get called on older versions");
1277 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1278 RustStringRef MessageOut,
1279 RustStringRef BufferOut,
1280 LLVMRustDiagnosticLevel* LevelOut,
1282 unsigned* RangesOut,
1283 size_t* NumRanges) {
1284 SMDiagnostic& D = *unwrap(DRef);
1285 RawRustStringOstream MessageOS(MessageOut);
1286 MessageOS << D.getMessage();
1288 switch (D.getKind()) {
1289 case SourceMgr::DK_Error:
1290 *LevelOut = LLVMRustDiagnosticLevel::Error;
1292 case SourceMgr::DK_Warning:
1293 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1295 case SourceMgr::DK_Note:
1296 *LevelOut = LLVMRustDiagnosticLevel::Note;
1298 case SourceMgr::DK_Remark:
1299 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1302 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1305 if (D.getLoc() == SMLoc())
1308 const SourceMgr &LSM = *D.getSourceMgr();
1309 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1310 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1312 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1314 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1315 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1316 for (size_t i = 0; i < *NumRanges; i++) {
1317 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1318 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1324 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1325 LLVMValueRef ParentPad,
1327 LLVMValueRef *LLArgs,
1329 Value **Args = unwrap(LLArgs);
1330 if (ParentPad == nullptr) {
1331 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1332 ParentPad = wrap(Constant::getNullValue(Ty));
1334 return wrap(unwrap(B)->CreateCleanupPad(
1335 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1338 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1339 LLVMValueRef CleanupPad,
1340 LLVMBasicBlockRef UnwindBB) {
1341 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1342 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1345 extern "C" LLVMValueRef
1346 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1347 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1348 Value **Args = unwrap(LLArgs);
1349 return wrap(unwrap(B)->CreateCatchPad(
1350 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1353 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1355 LLVMBasicBlockRef BB) {
1356 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1360 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1361 LLVMValueRef ParentPad,
1362 LLVMBasicBlockRef BB,
1363 unsigned NumHandlers,
1365 if (ParentPad == nullptr) {
1366 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1367 ParentPad = wrap(Constant::getNullValue(Ty));
1369 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1370 NumHandlers, Name));
1373 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1374 LLVMBasicBlockRef Handler) {
1375 Value *CatchSwitch = unwrap(CatchSwitchRef);
1376 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1379 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1380 LLVMValueRef *Inputs,
1381 unsigned NumInputs) {
1382 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1385 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1389 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1390 LLVMValueRef *Args, unsigned NumArgs,
1391 OperandBundleDef *Bundle) {
1392 Value *Callee = unwrap(Fn);
1393 FunctionType *FTy = unwrap<FunctionType>(Ty);
1394 unsigned Len = Bundle ? 1 : 0;
1395 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1396 return wrap(unwrap(B)->CreateCall(
1397 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1400 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1401 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1402 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1405 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1406 LLVMValueRef Dst, unsigned DstAlign,
1407 LLVMValueRef Src, unsigned SrcAlign,
1408 LLVMValueRef Size, bool IsVolatile) {
1409 return wrap(unwrap(B)->CreateMemCpy(
1410 unwrap(Dst), MaybeAlign(DstAlign),
1411 unwrap(Src), MaybeAlign(SrcAlign),
1412 unwrap(Size), IsVolatile));
1415 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1416 LLVMValueRef Dst, unsigned DstAlign,
1417 LLVMValueRef Src, unsigned SrcAlign,
1418 LLVMValueRef Size, bool IsVolatile) {
1419 return wrap(unwrap(B)->CreateMemMove(
1420 unwrap(Dst), MaybeAlign(DstAlign),
1421 unwrap(Src), MaybeAlign(SrcAlign),
1422 unwrap(Size), IsVolatile));
1425 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1426 LLVMValueRef Dst, unsigned DstAlign,
1428 LLVMValueRef Size, bool IsVolatile) {
1429 return wrap(unwrap(B)->CreateMemSet(
1430 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1433 extern "C" LLVMValueRef
1434 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1435 LLVMValueRef *Args, unsigned NumArgs,
1436 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1437 OperandBundleDef *Bundle, const char *Name) {
1438 Value *Callee = unwrap(Fn);
1439 FunctionType *FTy = unwrap<FunctionType>(Ty);
1440 unsigned Len = Bundle ? 1 : 0;
1441 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1442 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1443 makeArrayRef(unwrap(Args), NumArgs),
1447 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1448 LLVMBasicBlockRef BB) {
1449 auto Point = unwrap(BB)->getFirstInsertionPt();
1450 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1453 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1454 const char *Name, size_t NameLen) {
1455 Triple TargetTriple(unwrap(M)->getTargetTriple());
1456 GlobalObject *GV = unwrap<GlobalObject>(V);
1457 if (TargetTriple.supportsCOMDAT()) {
1458 StringRef NameRef(Name, NameLen);
1459 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1463 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1464 GlobalObject *GV = unwrap<GlobalObject>(V);
1465 GV->setComdat(nullptr);
1468 enum class LLVMRustLinkage {
1469 ExternalLinkage = 0,
1470 AvailableExternallyLinkage = 1,
1471 LinkOnceAnyLinkage = 2,
1472 LinkOnceODRLinkage = 3,
1475 AppendingLinkage = 6,
1476 InternalLinkage = 7,
1478 ExternalWeakLinkage = 9,
1482 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1484 case LLVMExternalLinkage:
1485 return LLVMRustLinkage::ExternalLinkage;
1486 case LLVMAvailableExternallyLinkage:
1487 return LLVMRustLinkage::AvailableExternallyLinkage;
1488 case LLVMLinkOnceAnyLinkage:
1489 return LLVMRustLinkage::LinkOnceAnyLinkage;
1490 case LLVMLinkOnceODRLinkage:
1491 return LLVMRustLinkage::LinkOnceODRLinkage;
1492 case LLVMWeakAnyLinkage:
1493 return LLVMRustLinkage::WeakAnyLinkage;
1494 case LLVMWeakODRLinkage:
1495 return LLVMRustLinkage::WeakODRLinkage;
1496 case LLVMAppendingLinkage:
1497 return LLVMRustLinkage::AppendingLinkage;
1498 case LLVMInternalLinkage:
1499 return LLVMRustLinkage::InternalLinkage;
1500 case LLVMPrivateLinkage:
1501 return LLVMRustLinkage::PrivateLinkage;
1502 case LLVMExternalWeakLinkage:
1503 return LLVMRustLinkage::ExternalWeakLinkage;
1504 case LLVMCommonLinkage:
1505 return LLVMRustLinkage::CommonLinkage;
1507 report_fatal_error("Invalid LLVMRustLinkage value!");
1511 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1513 case LLVMRustLinkage::ExternalLinkage:
1514 return LLVMExternalLinkage;
1515 case LLVMRustLinkage::AvailableExternallyLinkage:
1516 return LLVMAvailableExternallyLinkage;
1517 case LLVMRustLinkage::LinkOnceAnyLinkage:
1518 return LLVMLinkOnceAnyLinkage;
1519 case LLVMRustLinkage::LinkOnceODRLinkage:
1520 return LLVMLinkOnceODRLinkage;
1521 case LLVMRustLinkage::WeakAnyLinkage:
1522 return LLVMWeakAnyLinkage;
1523 case LLVMRustLinkage::WeakODRLinkage:
1524 return LLVMWeakODRLinkage;
1525 case LLVMRustLinkage::AppendingLinkage:
1526 return LLVMAppendingLinkage;
1527 case LLVMRustLinkage::InternalLinkage:
1528 return LLVMInternalLinkage;
1529 case LLVMRustLinkage::PrivateLinkage:
1530 return LLVMPrivateLinkage;
1531 case LLVMRustLinkage::ExternalWeakLinkage:
1532 return LLVMExternalWeakLinkage;
1533 case LLVMRustLinkage::CommonLinkage:
1534 return LLVMCommonLinkage;
1536 report_fatal_error("Invalid LLVMRustLinkage value!");
1539 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1540 return toRust(LLVMGetLinkage(V));
1543 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1544 LLVMRustLinkage RustLinkage) {
1545 LLVMSetLinkage(V, fromRust(RustLinkage));
1548 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1549 LLVMValueRef ConstantVal,
1550 LLVMValueRef *ConstantIndices,
1551 unsigned NumIndices) {
1552 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1554 Constant *Val = unwrap<Constant>(ConstantVal);
1555 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1558 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1559 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1560 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1562 auto C = unwrap<llvm::ConstantInt>(CV);
1563 if (C->getBitWidth() > 128) { return false; }
1565 #if LLVM_VERSION_GE(15, 0)
1567 AP = C->getValue().sext(128);
1569 AP = C->getValue().zext(128);
1573 AP = C->getValue().sextOrSelf(128);
1575 AP = C->getValue().zextOrSelf(128);
1578 *low = AP.getLoBits(64).getZExtValue();
1579 *high = AP.getHiBits(64).getZExtValue();
1583 enum class LLVMRustVisibility {
1589 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1591 case LLVMDefaultVisibility:
1592 return LLVMRustVisibility::Default;
1593 case LLVMHiddenVisibility:
1594 return LLVMRustVisibility::Hidden;
1595 case LLVMProtectedVisibility:
1596 return LLVMRustVisibility::Protected;
1598 report_fatal_error("Invalid LLVMRustVisibility value!");
1601 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1603 case LLVMRustVisibility::Default:
1604 return LLVMDefaultVisibility;
1605 case LLVMRustVisibility::Hidden:
1606 return LLVMHiddenVisibility;
1607 case LLVMRustVisibility::Protected:
1608 return LLVMProtectedVisibility;
1610 report_fatal_error("Invalid LLVMRustVisibility value!");
1613 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1614 return toRust(LLVMGetVisibility(V));
1617 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1618 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1619 LLVMTypeRef DestTy, bool isSigned) {
1620 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1623 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1624 LLVMRustVisibility RustVisibility) {
1625 LLVMSetVisibility(V, fromRust(RustVisibility));
1628 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1629 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1632 struct LLVMRustModuleBuffer {
1636 extern "C" LLVMRustModuleBuffer*
1637 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1638 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1640 raw_string_ostream OS(Ret->data);
1642 legacy::PassManager PM;
1643 PM.add(createBitcodeWriterPass(OS));
1647 return Ret.release();
1651 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1655 extern "C" const void*
1656 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1657 return Buffer->data.data();
1661 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1662 return Buffer->data.length();
1666 LLVMRustModuleCost(LLVMModuleRef M) {
1667 auto f = unwrap(M)->functions();
1668 return std::distance(std::begin(f), std::end(f));
1671 // Vector reductions:
1672 extern "C" LLVMValueRef
1673 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1674 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1676 extern "C" LLVMValueRef
1677 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1678 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1680 extern "C" LLVMValueRef
1681 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1682 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1684 extern "C" LLVMValueRef
1685 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1686 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1688 extern "C" LLVMValueRef
1689 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1690 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1692 extern "C" LLVMValueRef
1693 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1694 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1696 extern "C" LLVMValueRef
1697 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1698 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1700 extern "C" LLVMValueRef
1701 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1702 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1704 extern "C" LLVMValueRef
1705 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1706 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1708 extern "C" LLVMValueRef
1709 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1710 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1711 I->setHasNoNaNs(NoNaN);
1714 extern "C" LLVMValueRef
1715 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1716 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1717 I->setHasNoNaNs(NoNaN);
1721 extern "C" LLVMValueRef
1722 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1723 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1725 extern "C" LLVMValueRef
1726 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1727 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1730 // This struct contains all necessary info about a symbol exported from a DLL.
1731 struct LLVMRustCOFFShortExport {
1733 bool ordinal_present;
1734 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1738 // Machine must be a COFF machine type, as defined in PE specs.
1739 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1740 const char* ImportName,
1742 const LLVMRustCOFFShortExport* Exports,
1747 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1748 ConvertedExports.reserve(NumExports);
1750 for (size_t i = 0; i < NumExports; ++i) {
1751 bool ordinal_present = Exports[i].ordinal_present;
1752 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1753 ConvertedExports.push_back(llvm::object::COFFShortExport{
1754 Exports[i].name, // Name
1755 std::string{}, // ExtName
1756 std::string{}, // SymbolName
1757 std::string{}, // AliasTarget
1759 ordinal_present, // Noname
1766 auto Error = llvm::object::writeImportLibrary(
1770 static_cast<llvm::COFF::MachineTypes>(Machine),
1773 std::string errorString;
1774 llvm::raw_string_ostream stream(errorString);
1777 LLVMRustSetLastError(errorString.c_str());
1778 return LLVMRustResult::Failure;
1780 return LLVMRustResult::Success;
1784 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1785 extern "C" DiagnosticHandler *
1786 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1787 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1788 return DH.release();
1791 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1792 // handling. Ownership of the handler is moved to the LLVMContext.
1793 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1794 DiagnosticHandler *DH) {
1795 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1798 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1800 // Configures a diagnostic handler that invokes provided callback when a
1801 // backend needs to emit a diagnostic.
1803 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1804 // the RemarkPasses array specifies individual passes for which remarks will be
1806 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1807 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1808 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1809 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1811 class RustDiagnosticHandler final : public DiagnosticHandler {
1813 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1814 void *DiagnosticHandlerContext,
1815 bool RemarkAllPasses,
1816 std::vector<std::string> RemarkPasses)
1817 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1818 DiagnosticHandlerContext(DiagnosticHandlerContext),
1819 RemarkAllPasses(RemarkAllPasses),
1820 RemarkPasses(RemarkPasses) {}
1822 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1823 if (DiagnosticHandlerCallback) {
1824 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1830 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1831 return isRemarkEnabled(PassName);
1834 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1835 return isRemarkEnabled(PassName);
1838 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1839 return isRemarkEnabled(PassName);
1842 bool isAnyRemarkEnabled() const override {
1843 return RemarkAllPasses || !RemarkPasses.empty();
1847 bool isRemarkEnabled(StringRef PassName) const {
1848 if (RemarkAllPasses)
1851 for (auto &Pass : RemarkPasses)
1852 if (Pass == PassName)
1858 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1859 void *DiagnosticHandlerContext = nullptr;
1861 bool RemarkAllPasses = false;
1862 std::vector<std::string> RemarkPasses;
1865 std::vector<std::string> Passes;
1866 for (size_t I = 0; I != RemarkPassesLen; ++I)
1867 Passes.push_back(RemarkPasses[I]);
1869 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1870 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
1873 extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
1874 RawRustStringOstream OS(Str);
1875 GlobalValue *GV = unwrap<GlobalValue>(V);
1876 Mangler().getNameWithPrefix(OS, GV, true);
1879 // LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just
1880 // use its implementation.
1881 #if LLVM_VERSION_LT(15, 0)
1882 extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
1883 return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));