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/Object/Archive.h"
10 #include "llvm/Object/COFFImportFile.h"
11 #include "llvm/Object/ObjectFile.h"
12 #include "llvm/Bitcode/BitcodeWriterPass.h"
13 #include "llvm/Support/Signals.h"
14 #include "llvm/ADT/Optional.h"
18 //===----------------------------------------------------------------------===
20 // This file defines alternate interfaces to core functions that are more
21 // readily callable by Rust's FFI.
23 //===----------------------------------------------------------------------===
26 using namespace llvm::sys;
27 using namespace llvm::object;
29 // LLVMAtomicOrdering is already an enum - don't create another
31 static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
33 case LLVMAtomicOrderingNotAtomic:
34 return AtomicOrdering::NotAtomic;
35 case LLVMAtomicOrderingUnordered:
36 return AtomicOrdering::Unordered;
37 case LLVMAtomicOrderingMonotonic:
38 return AtomicOrdering::Monotonic;
39 case LLVMAtomicOrderingAcquire:
40 return AtomicOrdering::Acquire;
41 case LLVMAtomicOrderingRelease:
42 return AtomicOrdering::Release;
43 case LLVMAtomicOrderingAcquireRelease:
44 return AtomicOrdering::AcquireRelease;
45 case LLVMAtomicOrderingSequentiallyConsistent:
46 return AtomicOrdering::SequentiallyConsistent;
49 report_fatal_error("Invalid LLVMAtomicOrdering value!");
52 static LLVM_THREAD_LOCAL char *LastError;
54 // Custom error handler for fatal LLVM errors.
56 // Notably it exits the process with code 101, unlike LLVM's default of 1.
57 static void FatalErrorHandler(void *UserData,
58 #if LLVM_VERSION_LT(14, 0)
59 const std::string& Reason,
64 // Do the same thing that the default error handler does.
65 std::cerr << "LLVM ERROR: " << Reason << std::endl;
67 // Since this error handler exits the process, we have to run any cleanup that
68 // LLVM would run after handling the error. This might change with an LLVM
70 sys::RunInterruptHandlers();
75 extern "C" void LLVMRustInstallFatalErrorHandler() {
76 install_fatal_error_handler(FatalErrorHandler);
79 extern "C" void LLVMRustDisableSystemDialogsOnCrash() {
80 sys::DisableSystemDialogsOnCrash();
83 extern "C" char *LLVMRustGetLastError(void) {
84 char *Ret = LastError;
89 extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) {
90 return unwrap(M)->getInstructionCount();
93 extern "C" void LLVMRustSetLastError(const char *Err) {
94 free((void *)LastError);
95 LastError = strdup(Err);
98 extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
99 auto ctx = new LLVMContext();
100 ctx->setDiscardValueNames(shouldDiscardNames);
104 extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
105 const char *Triple) {
106 unwrap(M)->setTargetTriple(Triple::normalize(Triple));
109 extern "C" void LLVMRustPrintPassTimings() {
110 raw_fd_ostream OS(2, false); // stderr.
111 TimerGroup::printAll(OS);
114 extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
116 return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
119 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
122 LLVMTypeRef FunctionTy) {
123 return wrap(unwrap(M)
124 ->getOrInsertFunction(StringRef(Name, NameLen),
125 unwrap<FunctionType>(FunctionTy))
130 extern "C" LLVMValueRef
131 LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
132 Module *Mod = unwrap(M);
133 StringRef NameRef(Name, NameLen);
135 // We don't use Module::getOrInsertGlobal because that returns a Constant*,
136 // which may either be the real GlobalVariable*, or a constant bitcast of it
137 // if our type doesn't match the original declaration. We always want the
138 // GlobalVariable* so we can access linkage, visibility, etc.
139 GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true);
141 GV = new GlobalVariable(*Mod, unwrap(Ty), false,
142 GlobalValue::ExternalLinkage, nullptr, NameRef);
146 extern "C" LLVMValueRef
147 LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
148 return wrap(new GlobalVariable(*unwrap(M),
151 GlobalValue::PrivateLinkage,
155 extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
156 return wrap(Type::getMetadataTy(*unwrap(C)));
159 static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
162 return Attribute::AlwaysInline;
164 return Attribute::ByVal;
166 return Attribute::Cold;
168 return Attribute::InlineHint;
170 return Attribute::MinSize;
172 return Attribute::Naked;
174 return Attribute::NoAlias;
176 return Attribute::NoCapture;
178 return Attribute::NoInline;
180 return Attribute::NonNull;
182 return Attribute::NoRedZone;
184 return Attribute::NoReturn;
186 return Attribute::NoUnwind;
187 case OptimizeForSize:
188 return Attribute::OptimizeForSize;
190 return Attribute::ReadOnly;
192 return Attribute::SExt;
194 return Attribute::StructRet;
196 return Attribute::UWTable;
198 return Attribute::ZExt;
200 return Attribute::InReg;
202 return Attribute::SanitizeThread;
203 case SanitizeAddress:
204 return Attribute::SanitizeAddress;
206 return Attribute::SanitizeMemory;
208 return Attribute::NonLazyBind;
210 return Attribute::OptimizeNone;
212 return Attribute::ReturnsTwice;
214 return Attribute::ReadNone;
215 case InaccessibleMemOnly:
216 return Attribute::InaccessibleMemOnly;
217 case SanitizeHWAddress:
218 return Attribute::SanitizeHWAddress;
220 return Attribute::WillReturn;
221 case StackProtectReq:
222 return Attribute::StackProtectReq;
223 case StackProtectStrong:
224 return Attribute::StackProtectStrong;
226 return Attribute::StackProtect;
228 report_fatal_error("bad AttributeKind");
231 template<typename T> static inline void AddAttribute(T *t, unsigned Index, Attribute Attr) {
232 #if LLVM_VERSION_LT(14, 0)
233 t->addAttribute(Index, Attr);
235 t->addAttributeAtIndex(Index, Attr);
239 extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
240 LLVMRustAttribute RustAttr) {
241 CallBase *Call = unwrap<CallBase>(Instr);
242 Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
243 AddAttribute(Call, Index, Attr);
246 extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index,
248 CallBase *Call = unwrap<CallBase>(Instr);
249 Attribute Attr = Attribute::get(Call->getContext(), Name);
250 AddAttribute(Call, Index, Attr);
253 extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
256 CallBase *Call = unwrap<CallBase>(Instr);
257 Attribute Attr = Attribute::getWithAlignment(Call->getContext(), Align(Bytes));
258 AddAttribute(Call, Index, Attr);
261 extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
264 CallBase *Call = unwrap<CallBase>(Instr);
265 Attribute Attr = Attribute::getWithDereferenceableBytes(Call->getContext(), Bytes);
266 AddAttribute(Call, Index, Attr);
269 extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
272 CallBase *Call = unwrap<CallBase>(Instr);
273 Attribute Attr = Attribute::getWithDereferenceableOrNullBytes(Call->getContext(), Bytes);
274 AddAttribute(Call, Index, Attr);
277 extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
279 CallBase *Call = unwrap<CallBase>(Instr);
280 Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
281 AddAttribute(Call, Index, Attr);
284 extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index,
286 CallBase *Call = unwrap<CallBase>(Instr);
287 Attribute Attr = Attribute::getWithStructRetType(Call->getContext(), unwrap(Ty));
288 AddAttribute(Call, Index, Attr);
291 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
292 LLVMRustAttribute RustAttr) {
293 Function *A = unwrap<Function>(Fn);
294 Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
295 AddAttribute(A, Index, Attr);
298 extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
301 Function *A = unwrap<Function>(Fn);
302 AddAttribute(A, Index, Attribute::getWithAlignment(
303 A->getContext(), llvm::Align(Bytes)));
306 extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
308 Function *A = unwrap<Function>(Fn);
309 AddAttribute(A, Index, Attribute::getWithDereferenceableBytes(A->getContext(),
313 extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
316 Function *A = unwrap<Function>(Fn);
317 AddAttribute(A, Index, Attribute::getWithDereferenceableOrNullBytes(
318 A->getContext(), Bytes));
321 extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
323 Function *F = unwrap<Function>(Fn);
324 Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
325 AddAttribute(F, Index, Attr);
328 extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index,
330 Function *F = unwrap<Function>(Fn);
331 Attribute Attr = Attribute::getWithStructRetType(F->getContext(), unwrap(Ty));
332 AddAttribute(F, Index, Attr);
335 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
339 Function *F = unwrap<Function>(Fn);
340 AddAttribute(F, Index, Attribute::get(
341 F->getContext(), StringRef(Name), StringRef(Value)));
344 extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
346 LLVMRustAttribute RustAttr) {
347 Function *F = unwrap<Function>(Fn);
348 AttributeList PAL = F->getAttributes();
349 AttributeList PALNew;
350 #if LLVM_VERSION_LT(14, 0)
351 PALNew = PAL.removeAttribute(F->getContext(), Index, fromRust(RustAttr));
353 PALNew = PAL.removeAttributeAtIndex(F->getContext(), Index, fromRust(RustAttr));
355 F->setAttributes(PALNew);
358 // Enable a fast-math flag
360 // https://llvm.org/docs/LangRef.html#fast-math-flags
361 extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
362 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
367 extern "C" LLVMValueRef
368 LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
369 const char *Name, LLVMAtomicOrdering Order) {
370 Value *Ptr = unwrap(Source);
371 LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
372 LI->setAtomic(fromRust(Order));
376 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
379 LLVMAtomicOrdering Order) {
380 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
381 SI->setAtomic(fromRust(Order));
385 // FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
386 // once we raise our minimum support to LLVM 10.
387 extern "C" LLVMValueRef
388 LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
389 LLVMValueRef Old, LLVMValueRef Source,
390 LLVMAtomicOrdering Order,
391 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
392 #if LLVM_VERSION_GE(13,0)
393 // Rust probably knows the alignment of the target value and should be able to
394 // specify something more precise than MaybeAlign here. See also
395 // https://reviews.llvm.org/D97224 which may be a useful reference.
396 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
397 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
398 fromRust(FailureOrder));
400 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
401 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
402 fromRust(FailureOrder));
408 enum class LLVMRustSynchronizationScope {
413 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
415 case LLVMRustSynchronizationScope::SingleThread:
416 return SyncScope::SingleThread;
417 case LLVMRustSynchronizationScope::CrossThread:
418 return SyncScope::System;
420 report_fatal_error("bad SynchronizationScope.");
424 extern "C" LLVMValueRef
425 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
426 LLVMRustSynchronizationScope Scope) {
427 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
430 enum class LLVMRustAsmDialect {
435 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
437 case LLVMRustAsmDialect::Att:
438 return InlineAsm::AD_ATT;
439 case LLVMRustAsmDialect::Intel:
440 return InlineAsm::AD_Intel;
442 report_fatal_error("bad AsmDialect.");
446 extern "C" LLVMValueRef
447 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
448 char *Constraints, size_t ConstraintsLen,
449 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
450 LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
451 #if LLVM_VERSION_GE(13, 0)
452 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
453 StringRef(AsmString, AsmStringLen),
454 StringRef(Constraints, ConstraintsLen),
455 HasSideEffects, IsAlignStack,
456 fromRust(Dialect), CanThrow));
458 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
459 StringRef(AsmString, AsmStringLen),
460 StringRef(Constraints, ConstraintsLen),
461 HasSideEffects, IsAlignStack,
466 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
467 size_t ConstraintsLen) {
468 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
469 StringRef(Constraints, ConstraintsLen));
472 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
474 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
477 typedef DIBuilder *LLVMRustDIBuilderRef;
479 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
480 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
483 #define DIDescriptor DIScope
484 #define DIArray DINodeArray
485 #define unwrapDI unwrapDIPtr
487 // These values **must** match debuginfo::DIFlags! They also *happen*
488 // to match LLVM, but that isn't required as we do giant sets of
489 // matching below. The value shouldn't be directly passed to LLVM.
490 enum class LLVMRustDIFlags : uint32_t {
495 FlagFwdDecl = (1 << 2),
496 FlagAppleBlock = (1 << 3),
497 FlagBlockByrefStruct = (1 << 4),
498 FlagVirtual = (1 << 5),
499 FlagArtificial = (1 << 6),
500 FlagExplicit = (1 << 7),
501 FlagPrototyped = (1 << 8),
502 FlagObjcClassComplete = (1 << 9),
503 FlagObjectPointer = (1 << 10),
504 FlagVector = (1 << 11),
505 FlagStaticMember = (1 << 12),
506 FlagLValueReference = (1 << 13),
507 FlagRValueReference = (1 << 14),
508 FlagExternalTypeRef = (1 << 15),
509 FlagIntroducedVirtual = (1 << 18),
510 FlagBitField = (1 << 19),
511 FlagNoReturn = (1 << 20),
512 // Do not add values that are not supported by the minimum LLVM
513 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
516 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
517 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
518 static_cast<uint32_t>(B));
521 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
522 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
523 static_cast<uint32_t>(B));
526 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
530 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
532 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
533 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
536 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
537 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
539 switch (visibility(Flags)) {
540 case LLVMRustDIFlags::FlagPrivate:
541 Result |= DINode::DIFlags::FlagPrivate;
543 case LLVMRustDIFlags::FlagProtected:
544 Result |= DINode::DIFlags::FlagProtected;
546 case LLVMRustDIFlags::FlagPublic:
547 Result |= DINode::DIFlags::FlagPublic;
550 // The rest are handled below
554 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
555 Result |= DINode::DIFlags::FlagFwdDecl;
557 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
558 Result |= DINode::DIFlags::FlagAppleBlock;
560 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
561 Result |= DINode::DIFlags::FlagVirtual;
563 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
564 Result |= DINode::DIFlags::FlagArtificial;
566 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
567 Result |= DINode::DIFlags::FlagExplicit;
569 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
570 Result |= DINode::DIFlags::FlagPrototyped;
572 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
573 Result |= DINode::DIFlags::FlagObjcClassComplete;
575 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
576 Result |= DINode::DIFlags::FlagObjectPointer;
578 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
579 Result |= DINode::DIFlags::FlagVector;
581 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
582 Result |= DINode::DIFlags::FlagStaticMember;
584 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
585 Result |= DINode::DIFlags::FlagLValueReference;
587 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
588 Result |= DINode::DIFlags::FlagRValueReference;
590 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
591 Result |= DINode::DIFlags::FlagIntroducedVirtual;
593 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
594 Result |= DINode::DIFlags::FlagBitField;
596 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
597 Result |= DINode::DIFlags::FlagNoReturn;
603 // These values **must** match debuginfo::DISPFlags! They also *happen*
604 // to match LLVM, but that isn't required as we do giant sets of
605 // matching below. The value shouldn't be directly passed to LLVM.
606 enum class LLVMRustDISPFlags : uint32_t {
609 SPFlagPureVirtual = 2,
610 SPFlagLocalToUnit = (1 << 2),
611 SPFlagDefinition = (1 << 3),
612 SPFlagOptimized = (1 << 4),
613 SPFlagMainSubprogram = (1 << 5),
614 // Do not add values that are not supported by the minimum LLVM
615 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
616 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
619 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
620 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
621 static_cast<uint32_t>(B));
624 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
625 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
626 static_cast<uint32_t>(B));
629 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
633 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
635 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
636 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
639 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
640 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
642 switch (virtuality(SPFlags)) {
643 case LLVMRustDISPFlags::SPFlagVirtual:
644 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
646 case LLVMRustDISPFlags::SPFlagPureVirtual:
647 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
650 // The rest are handled below
654 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
655 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
657 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
658 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
660 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
661 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
663 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
664 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
670 enum class LLVMRustDebugEmissionKind {
676 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
678 case LLVMRustDebugEmissionKind::NoDebug:
679 return DICompileUnit::DebugEmissionKind::NoDebug;
680 case LLVMRustDebugEmissionKind::FullDebug:
681 return DICompileUnit::DebugEmissionKind::FullDebug;
682 case LLVMRustDebugEmissionKind::LineTablesOnly:
683 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
685 report_fatal_error("bad DebugEmissionKind.");
689 enum class LLVMRustChecksumKind {
696 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
698 case LLVMRustChecksumKind::None:
700 case LLVMRustChecksumKind::MD5:
701 return DIFile::ChecksumKind::CSK_MD5;
702 case LLVMRustChecksumKind::SHA1:
703 return DIFile::ChecksumKind::CSK_SHA1;
704 case LLVMRustChecksumKind::SHA256:
705 return DIFile::ChecksumKind::CSK_SHA256;
707 report_fatal_error("bad ChecksumKind.");
711 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
712 return DEBUG_METADATA_VERSION;
715 extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
717 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
719 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
721 extern "C" bool LLVMRustIsRustLLVM() {
729 extern "C" void LLVMRustAddModuleFlag(
731 Module::ModFlagBehavior MergeBehavior,
734 unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
737 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
738 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
741 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
742 return new DIBuilder(*unwrap(M));
745 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
749 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
753 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
754 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
755 const char *Producer, size_t ProducerLen, bool isOptimized,
756 const char *Flags, unsigned RuntimeVer,
757 const char *SplitName, size_t SplitNameLen,
758 LLVMRustDebugEmissionKind Kind,
759 uint64_t DWOId, bool SplitDebugInlining) {
760 auto *File = unwrapDI<DIFile>(FileRef);
762 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
763 isOptimized, Flags, RuntimeVer,
764 StringRef(SplitName, SplitNameLen),
765 fromRust(Kind), DWOId, SplitDebugInlining));
768 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
769 LLVMRustDIBuilderRef Builder,
770 const char *Filename, size_t FilenameLen,
771 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
772 const char *Checksum, size_t ChecksumLen) {
773 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
774 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
776 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
777 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
778 StringRef(Directory, DirectoryLen),
782 extern "C" LLVMMetadataRef
783 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
784 LLVMMetadataRef ParameterTypes) {
785 return wrap(Builder->createSubroutineType(
786 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
789 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
790 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
791 const char *Name, size_t NameLen,
792 const char *LinkageName, size_t LinkageNameLen,
793 LLVMMetadataRef File, unsigned LineNo,
794 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
795 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
796 LLVMMetadataRef Decl) {
797 DITemplateParameterArray TParams =
798 DITemplateParameterArray(unwrap<MDTuple>(TParam));
799 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
800 DINode::DIFlags llvmFlags = fromRust(Flags);
801 DISubprogram *Sub = Builder->createFunction(
802 unwrapDI<DIScope>(Scope),
803 StringRef(Name, NameLen),
804 StringRef(LinkageName, LinkageNameLen),
805 unwrapDI<DIFile>(File), LineNo,
806 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
807 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
809 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
813 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
814 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
815 uint64_t SizeInBits, unsigned Encoding) {
816 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
819 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
820 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
821 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
822 return wrap(Builder->createTypedef(
823 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
824 LineNo, unwrapDIPtr<DIScope>(Scope)));
827 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
828 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
829 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
830 const char *Name, size_t NameLen) {
831 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
832 SizeInBits, AlignInBits,
834 StringRef(Name, NameLen)));
837 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
838 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
839 const char *Name, size_t NameLen,
840 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
841 uint32_t AlignInBits, LLVMRustDIFlags Flags,
842 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
843 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
844 const char *UniqueId, size_t UniqueIdLen) {
845 return wrap(Builder->createStructType(
846 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
847 unwrapDI<DIFile>(File), LineNumber,
848 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
849 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
850 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
853 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
854 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
855 const char *Name, size_t NameLen,
856 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
857 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
858 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
859 return wrap(Builder->createVariantPart(
860 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
861 unwrapDI<DIFile>(File), LineNumber,
862 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
863 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
866 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
867 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
868 const char *Name, size_t NameLen,
869 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
870 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
871 LLVMMetadataRef Ty) {
872 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
873 StringRef(Name, NameLen),
874 unwrapDI<DIFile>(File), LineNo,
875 SizeInBits, AlignInBits, OffsetInBits,
876 fromRust(Flags), unwrapDI<DIType>(Ty)));
879 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
880 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
881 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
882 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
883 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
884 llvm::ConstantInt* D = nullptr;
886 D = unwrap<llvm::ConstantInt>(Discriminant);
888 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
889 StringRef(Name, NameLen),
890 unwrapDI<DIFile>(File), LineNo,
891 SizeInBits, AlignInBits, OffsetInBits, D,
892 fromRust(Flags), unwrapDI<DIType>(Ty)));
895 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
896 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
897 LLVMMetadataRef File, unsigned Line, unsigned Col) {
898 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
899 unwrapDI<DIFile>(File), Line, Col));
902 extern "C" LLVMMetadataRef
903 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
904 LLVMMetadataRef Scope,
905 LLVMMetadataRef File) {
906 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
907 unwrapDI<DIFile>(File)));
910 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
911 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
912 const char *Name, size_t NameLen,
913 const char *LinkageName, size_t LinkageNameLen,
914 LLVMMetadataRef File, unsigned LineNo,
915 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
916 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
917 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
919 llvm::DIExpression *InitExpr = nullptr;
920 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
921 InitExpr = Builder->createConstantValueExpression(
922 IntVal->getValue().getSExtValue());
923 } else if (llvm::ConstantFP *FPVal =
924 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
925 InitExpr = Builder->createConstantValueExpression(
926 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
929 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
930 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
931 StringRef(LinkageName, LinkageNameLen),
932 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
933 /* isDefined */ true,
934 InitExpr, unwrapDIPtr<MDNode>(Decl),
935 /* templateParams */ nullptr,
938 InitVal->setMetadata("dbg", VarExpr);
940 return wrap(VarExpr);
943 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
944 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
945 const char *Name, size_t NameLen,
946 LLVMMetadataRef File, unsigned LineNo,
947 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
948 unsigned ArgNo, uint32_t AlignInBits) {
949 if (Tag == 0x100) { // DW_TAG_auto_variable
950 return wrap(Builder->createAutoVariable(
951 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
952 unwrapDI<DIFile>(File), LineNo,
953 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
955 return wrap(Builder->createParameterVariable(
956 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
957 unwrapDI<DIFile>(File), LineNo,
958 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
962 extern "C" LLVMMetadataRef
963 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
964 uint32_t AlignInBits, LLVMMetadataRef Ty,
965 LLVMMetadataRef Subscripts) {
967 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
968 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
971 extern "C" LLVMMetadataRef
972 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
974 return wrap(Builder->getOrCreateSubrange(Lo, Count));
977 extern "C" LLVMMetadataRef
978 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
979 LLVMMetadataRef *Ptr, unsigned Count) {
980 Metadata **DataValue = unwrap(Ptr);
982 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
985 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
986 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
987 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
988 LLVMBasicBlockRef InsertAtEnd) {
989 return wrap(Builder->insertDeclare(
990 unwrap(V), unwrap<DILocalVariable>(VarInfo),
991 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
992 DebugLoc(cast<MDNode>(unwrap(DL))),
993 unwrap(InsertAtEnd)));
996 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
997 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
998 int64_t Value, bool IsUnsigned) {
999 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
1002 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
1003 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1004 const char *Name, size_t NameLen,
1005 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1006 uint32_t AlignInBits, LLVMMetadataRef Elements,
1007 LLVMMetadataRef ClassTy, bool IsScoped) {
1008 return wrap(Builder->createEnumerationType(
1009 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
1010 unwrapDI<DIFile>(File), LineNumber,
1011 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
1012 unwrapDI<DIType>(ClassTy), "", IsScoped));
1015 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
1016 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1017 const char *Name, size_t NameLen,
1018 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1019 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
1020 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
1021 return wrap(Builder->createUnionType(
1022 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1023 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1024 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1025 StringRef(UniqueId, UniqueIdLen)));
1028 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1029 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1030 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1031 bool IsDefault = false; // FIXME: should we ever set this true?
1032 return wrap(Builder->createTemplateTypeParameter(
1033 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1036 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1037 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1038 const char *Name, size_t NameLen, bool ExportSymbols) {
1039 return wrap(Builder->createNameSpace(
1040 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1045 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1046 LLVMMetadataRef CompositeTy,
1047 LLVMMetadataRef Elements,
1048 LLVMMetadataRef Params) {
1049 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1050 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1051 DINodeArray(unwrap<MDTuple>(Params)));
1054 extern "C" LLVMMetadataRef
1055 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1056 LLVMMetadataRef ScopeRef,
1057 LLVMMetadataRef InlinedAt) {
1058 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1059 DILocation *Loc = DILocation::get(
1060 Scope->getContext(), Line, Column, Scope,
1061 unwrapDIPtr<MDNode>(InlinedAt));
1065 extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
1066 return dwarf::DW_OP_deref;
1069 extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1070 return dwarf::DW_OP_plus_uconst;
1073 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1074 RawRustStringOstream OS(Str);
1075 unwrap<llvm::Type>(Ty)->print(OS);
1078 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1079 RustStringRef Str) {
1080 RawRustStringOstream OS(Str);
1085 unwrap<llvm::Value>(V)->getType()->print(OS);
1087 unwrap<llvm::Value>(V)->print(OS);
1092 // LLVMArrayType function does not support 64-bit ElementCount
1093 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1094 uint64_t ElementCount) {
1095 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1098 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1100 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1101 RawRustStringOstream OS(Str);
1102 unwrap(T)->print(OS);
1105 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1106 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1107 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1108 RustStringRef FilenameOut, RustStringRef MessageOut) {
1109 // Undefined to call this not on an optimization diagnostic!
1110 llvm::DiagnosticInfoOptimizationBase *Opt =
1111 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1113 RawRustStringOstream PassNameOS(PassNameOut);
1114 PassNameOS << Opt->getPassName();
1115 *FunctionOut = wrap(&Opt->getFunction());
1117 RawRustStringOstream FilenameOS(FilenameOut);
1118 DiagnosticLocation loc = Opt->getLocation();
1119 if (loc.isValid()) {
1120 *Line = loc.getLine();
1121 *Column = loc.getColumn();
1122 FilenameOS << loc.getAbsolutePath();
1125 RawRustStringOstream MessageOS(MessageOut);
1126 MessageOS << Opt->getMsg();
1129 enum class LLVMRustDiagnosticLevel {
1137 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1138 LLVMRustDiagnosticLevel *LevelOut,
1139 unsigned *CookieOut,
1140 LLVMTwineRef *MessageOut) {
1141 // Undefined to call this not on an inline assembly diagnostic!
1142 llvm::DiagnosticInfoInlineAsm *IA =
1143 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1145 *CookieOut = IA->getLocCookie();
1146 *MessageOut = wrap(&IA->getMsgStr());
1148 switch (IA->getSeverity()) {
1150 *LevelOut = LLVMRustDiagnosticLevel::Error;
1153 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1156 *LevelOut = LLVMRustDiagnosticLevel::Note;
1159 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1162 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1166 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1167 RustStringRef Str) {
1168 RawRustStringOstream OS(Str);
1169 DiagnosticPrinterRawOStream DP(OS);
1170 unwrap(DI)->print(DP);
1173 enum class LLVMRustDiagnosticKind {
1177 DebugMetadataVersion,
1180 OptimizationRemarkMissed,
1181 OptimizationRemarkAnalysis,
1182 OptimizationRemarkAnalysisFPCommute,
1183 OptimizationRemarkAnalysisAliasing,
1184 OptimizationRemarkOther,
1185 OptimizationFailure,
1192 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1195 return LLVMRustDiagnosticKind::InlineAsm;
1197 return LLVMRustDiagnosticKind::StackSize;
1198 case DK_DebugMetadataVersion:
1199 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1200 case DK_SampleProfile:
1201 return LLVMRustDiagnosticKind::SampleProfile;
1202 case DK_OptimizationRemark:
1203 case DK_MachineOptimizationRemark:
1204 return LLVMRustDiagnosticKind::OptimizationRemark;
1205 case DK_OptimizationRemarkMissed:
1206 case DK_MachineOptimizationRemarkMissed:
1207 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1208 case DK_OptimizationRemarkAnalysis:
1209 case DK_MachineOptimizationRemarkAnalysis:
1210 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1211 case DK_OptimizationRemarkAnalysisFPCommute:
1212 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1213 case DK_OptimizationRemarkAnalysisAliasing:
1214 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1216 return LLVMRustDiagnosticKind::PGOProfile;
1218 return LLVMRustDiagnosticKind::Linker;
1219 case DK_Unsupported:
1220 return LLVMRustDiagnosticKind::Unsupported;
1221 #if LLVM_VERSION_GE(13, 0)
1223 return LLVMRustDiagnosticKind::SrcMgr;
1226 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1227 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1228 : LLVMRustDiagnosticKind::Other;
1232 extern "C" LLVMRustDiagnosticKind
1233 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1234 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1237 // This is kept distinct from LLVMGetTypeKind, because when
1238 // a new type kind is added, the Rust-side enum must be
1239 // updated or UB will result.
1240 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1241 switch (unwrap(Ty)->getTypeID()) {
1242 case Type::VoidTyID:
1243 return LLVMVoidTypeKind;
1244 case Type::HalfTyID:
1245 return LLVMHalfTypeKind;
1246 case Type::FloatTyID:
1247 return LLVMFloatTypeKind;
1248 case Type::DoubleTyID:
1249 return LLVMDoubleTypeKind;
1250 case Type::X86_FP80TyID:
1251 return LLVMX86_FP80TypeKind;
1252 case Type::FP128TyID:
1253 return LLVMFP128TypeKind;
1254 case Type::PPC_FP128TyID:
1255 return LLVMPPC_FP128TypeKind;
1256 case Type::LabelTyID:
1257 return LLVMLabelTypeKind;
1258 case Type::MetadataTyID:
1259 return LLVMMetadataTypeKind;
1260 case Type::IntegerTyID:
1261 return LLVMIntegerTypeKind;
1262 case Type::FunctionTyID:
1263 return LLVMFunctionTypeKind;
1264 case Type::StructTyID:
1265 return LLVMStructTypeKind;
1266 case Type::ArrayTyID:
1267 return LLVMArrayTypeKind;
1268 case Type::PointerTyID:
1269 return LLVMPointerTypeKind;
1270 case Type::FixedVectorTyID:
1271 return LLVMVectorTypeKind;
1272 case Type::X86_MMXTyID:
1273 return LLVMX86_MMXTypeKind;
1274 case Type::TokenTyID:
1275 return LLVMTokenTypeKind;
1276 case Type::ScalableVectorTyID:
1277 return LLVMScalableVectorTypeKind;
1278 case Type::BFloatTyID:
1279 return LLVMBFloatTypeKind;
1280 case Type::X86_AMXTyID:
1281 return LLVMX86_AMXTypeKind;
1283 report_fatal_error("Unhandled TypeID.");
1286 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1288 #if LLVM_VERSION_LT(13, 0)
1289 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1291 using LLVMInlineAsmDiagHandlerTy = void*;
1294 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1295 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1296 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1297 // with LLVM 13 this function is gone.
1298 #if LLVM_VERSION_LT(13, 0)
1299 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1303 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1304 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1305 #if LLVM_VERSION_GE(13, 0)
1306 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1307 *Cookie = SM->getLocCookie();
1308 return wrap(&SM->getSMDiag());
1310 report_fatal_error("Shouldn't get called on older versions");
1314 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1315 RustStringRef MessageOut,
1316 RustStringRef BufferOut,
1317 LLVMRustDiagnosticLevel* LevelOut,
1319 unsigned* RangesOut,
1320 size_t* NumRanges) {
1321 SMDiagnostic& D = *unwrap(DRef);
1322 RawRustStringOstream MessageOS(MessageOut);
1323 MessageOS << D.getMessage();
1325 switch (D.getKind()) {
1326 case SourceMgr::DK_Error:
1327 *LevelOut = LLVMRustDiagnosticLevel::Error;
1329 case SourceMgr::DK_Warning:
1330 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1332 case SourceMgr::DK_Note:
1333 *LevelOut = LLVMRustDiagnosticLevel::Note;
1335 case SourceMgr::DK_Remark:
1336 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1339 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1342 if (D.getLoc() == SMLoc())
1345 const SourceMgr &LSM = *D.getSourceMgr();
1346 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1347 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1349 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1351 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1352 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1353 for (size_t i = 0; i < *NumRanges; i++) {
1354 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1355 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1361 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1362 LLVMValueRef ParentPad,
1364 LLVMValueRef *LLArgs,
1366 Value **Args = unwrap(LLArgs);
1367 if (ParentPad == nullptr) {
1368 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1369 ParentPad = wrap(Constant::getNullValue(Ty));
1371 return wrap(unwrap(B)->CreateCleanupPad(
1372 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1375 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1376 LLVMValueRef CleanupPad,
1377 LLVMBasicBlockRef UnwindBB) {
1378 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1379 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1382 extern "C" LLVMValueRef
1383 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1384 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1385 Value **Args = unwrap(LLArgs);
1386 return wrap(unwrap(B)->CreateCatchPad(
1387 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1390 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1392 LLVMBasicBlockRef BB) {
1393 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1397 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1398 LLVMValueRef ParentPad,
1399 LLVMBasicBlockRef BB,
1400 unsigned NumHandlers,
1402 if (ParentPad == nullptr) {
1403 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1404 ParentPad = wrap(Constant::getNullValue(Ty));
1406 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1407 NumHandlers, Name));
1410 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1411 LLVMBasicBlockRef Handler) {
1412 Value *CatchSwitch = unwrap(CatchSwitchRef);
1413 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1416 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1417 LLVMValueRef *Inputs,
1418 unsigned NumInputs) {
1419 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1422 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1426 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1427 LLVMValueRef *Args, unsigned NumArgs,
1428 OperandBundleDef *Bundle) {
1429 Value *Callee = unwrap(Fn);
1430 FunctionType *FTy = unwrap<FunctionType>(Ty);
1431 unsigned Len = Bundle ? 1 : 0;
1432 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1433 return wrap(unwrap(B)->CreateCall(
1434 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1437 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1438 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1439 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1442 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1443 LLVMValueRef Dst, unsigned DstAlign,
1444 LLVMValueRef Src, unsigned SrcAlign,
1445 LLVMValueRef Size, bool IsVolatile) {
1446 return wrap(unwrap(B)->CreateMemCpy(
1447 unwrap(Dst), MaybeAlign(DstAlign),
1448 unwrap(Src), MaybeAlign(SrcAlign),
1449 unwrap(Size), IsVolatile));
1452 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1453 LLVMValueRef Dst, unsigned DstAlign,
1454 LLVMValueRef Src, unsigned SrcAlign,
1455 LLVMValueRef Size, bool IsVolatile) {
1456 return wrap(unwrap(B)->CreateMemMove(
1457 unwrap(Dst), MaybeAlign(DstAlign),
1458 unwrap(Src), MaybeAlign(SrcAlign),
1459 unwrap(Size), IsVolatile));
1462 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1463 LLVMValueRef Dst, unsigned DstAlign,
1465 LLVMValueRef Size, bool IsVolatile) {
1466 return wrap(unwrap(B)->CreateMemSet(
1467 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1470 extern "C" LLVMValueRef
1471 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1472 LLVMValueRef *Args, unsigned NumArgs,
1473 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1474 OperandBundleDef *Bundle, const char *Name) {
1475 Value *Callee = unwrap(Fn);
1476 FunctionType *FTy = unwrap<FunctionType>(Ty);
1477 unsigned Len = Bundle ? 1 : 0;
1478 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1479 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1480 makeArrayRef(unwrap(Args), NumArgs),
1484 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1485 LLVMBasicBlockRef BB) {
1486 auto Point = unwrap(BB)->getFirstInsertionPt();
1487 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1490 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1491 const char *Name, size_t NameLen) {
1492 Triple TargetTriple(unwrap(M)->getTargetTriple());
1493 GlobalObject *GV = unwrap<GlobalObject>(V);
1494 if (TargetTriple.supportsCOMDAT()) {
1495 StringRef NameRef(Name, NameLen);
1496 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1500 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1501 GlobalObject *GV = unwrap<GlobalObject>(V);
1502 GV->setComdat(nullptr);
1505 enum class LLVMRustLinkage {
1506 ExternalLinkage = 0,
1507 AvailableExternallyLinkage = 1,
1508 LinkOnceAnyLinkage = 2,
1509 LinkOnceODRLinkage = 3,
1512 AppendingLinkage = 6,
1513 InternalLinkage = 7,
1515 ExternalWeakLinkage = 9,
1519 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1521 case LLVMExternalLinkage:
1522 return LLVMRustLinkage::ExternalLinkage;
1523 case LLVMAvailableExternallyLinkage:
1524 return LLVMRustLinkage::AvailableExternallyLinkage;
1525 case LLVMLinkOnceAnyLinkage:
1526 return LLVMRustLinkage::LinkOnceAnyLinkage;
1527 case LLVMLinkOnceODRLinkage:
1528 return LLVMRustLinkage::LinkOnceODRLinkage;
1529 case LLVMWeakAnyLinkage:
1530 return LLVMRustLinkage::WeakAnyLinkage;
1531 case LLVMWeakODRLinkage:
1532 return LLVMRustLinkage::WeakODRLinkage;
1533 case LLVMAppendingLinkage:
1534 return LLVMRustLinkage::AppendingLinkage;
1535 case LLVMInternalLinkage:
1536 return LLVMRustLinkage::InternalLinkage;
1537 case LLVMPrivateLinkage:
1538 return LLVMRustLinkage::PrivateLinkage;
1539 case LLVMExternalWeakLinkage:
1540 return LLVMRustLinkage::ExternalWeakLinkage;
1541 case LLVMCommonLinkage:
1542 return LLVMRustLinkage::CommonLinkage;
1544 report_fatal_error("Invalid LLVMRustLinkage value!");
1548 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1550 case LLVMRustLinkage::ExternalLinkage:
1551 return LLVMExternalLinkage;
1552 case LLVMRustLinkage::AvailableExternallyLinkage:
1553 return LLVMAvailableExternallyLinkage;
1554 case LLVMRustLinkage::LinkOnceAnyLinkage:
1555 return LLVMLinkOnceAnyLinkage;
1556 case LLVMRustLinkage::LinkOnceODRLinkage:
1557 return LLVMLinkOnceODRLinkage;
1558 case LLVMRustLinkage::WeakAnyLinkage:
1559 return LLVMWeakAnyLinkage;
1560 case LLVMRustLinkage::WeakODRLinkage:
1561 return LLVMWeakODRLinkage;
1562 case LLVMRustLinkage::AppendingLinkage:
1563 return LLVMAppendingLinkage;
1564 case LLVMRustLinkage::InternalLinkage:
1565 return LLVMInternalLinkage;
1566 case LLVMRustLinkage::PrivateLinkage:
1567 return LLVMPrivateLinkage;
1568 case LLVMRustLinkage::ExternalWeakLinkage:
1569 return LLVMExternalWeakLinkage;
1570 case LLVMRustLinkage::CommonLinkage:
1571 return LLVMCommonLinkage;
1573 report_fatal_error("Invalid LLVMRustLinkage value!");
1576 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1577 return toRust(LLVMGetLinkage(V));
1580 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1581 LLVMRustLinkage RustLinkage) {
1582 LLVMSetLinkage(V, fromRust(RustLinkage));
1585 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1586 LLVMValueRef ConstantVal,
1587 LLVMValueRef *ConstantIndices,
1588 unsigned NumIndices) {
1589 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1591 Constant *Val = unwrap<Constant>(ConstantVal);
1592 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1595 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1596 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1597 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1599 auto C = unwrap<llvm::ConstantInt>(CV);
1600 if (C->getBitWidth() > 128) { return false; }
1603 AP = C->getValue().sextOrSelf(128);
1605 AP = C->getValue().zextOrSelf(128);
1607 *low = AP.getLoBits(64).getZExtValue();
1608 *high = AP.getHiBits(64).getZExtValue();
1612 enum class LLVMRustVisibility {
1618 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1620 case LLVMDefaultVisibility:
1621 return LLVMRustVisibility::Default;
1622 case LLVMHiddenVisibility:
1623 return LLVMRustVisibility::Hidden;
1624 case LLVMProtectedVisibility:
1625 return LLVMRustVisibility::Protected;
1627 report_fatal_error("Invalid LLVMRustVisibility value!");
1630 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1632 case LLVMRustVisibility::Default:
1633 return LLVMDefaultVisibility;
1634 case LLVMRustVisibility::Hidden:
1635 return LLVMHiddenVisibility;
1636 case LLVMRustVisibility::Protected:
1637 return LLVMProtectedVisibility;
1639 report_fatal_error("Invalid LLVMRustVisibility value!");
1642 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1643 return toRust(LLVMGetVisibility(V));
1646 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1647 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1648 LLVMTypeRef DestTy, bool isSigned) {
1649 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1652 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1653 LLVMRustVisibility RustVisibility) {
1654 LLVMSetVisibility(V, fromRust(RustVisibility));
1657 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1658 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1661 struct LLVMRustModuleBuffer {
1665 extern "C" LLVMRustModuleBuffer*
1666 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1667 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1669 raw_string_ostream OS(Ret->data);
1671 legacy::PassManager PM;
1672 PM.add(createBitcodeWriterPass(OS));
1676 return Ret.release();
1680 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1684 extern "C" const void*
1685 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1686 return Buffer->data.data();
1690 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1691 return Buffer->data.length();
1695 LLVMRustModuleCost(LLVMModuleRef M) {
1696 auto f = unwrap(M)->functions();
1697 return std::distance(std::begin(f), std::end(f));
1700 // Vector reductions:
1701 extern "C" LLVMValueRef
1702 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1703 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1705 extern "C" LLVMValueRef
1706 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1707 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1709 extern "C" LLVMValueRef
1710 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1711 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1713 extern "C" LLVMValueRef
1714 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1715 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1717 extern "C" LLVMValueRef
1718 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1719 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1721 extern "C" LLVMValueRef
1722 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1723 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1725 extern "C" LLVMValueRef
1726 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1727 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1729 extern "C" LLVMValueRef
1730 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1731 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1733 extern "C" LLVMValueRef
1734 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1735 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1737 extern "C" LLVMValueRef
1738 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1739 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1740 I->setHasNoNaNs(NoNaN);
1743 extern "C" LLVMValueRef
1744 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1745 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1746 I->setHasNoNaNs(NoNaN);
1750 extern "C" LLVMValueRef
1751 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1752 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1754 extern "C" LLVMValueRef
1755 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1756 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1759 // This struct contains all necessary info about a symbol exported from a DLL.
1760 struct LLVMRustCOFFShortExport {
1762 bool ordinal_present;
1763 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1767 // Machine must be a COFF machine type, as defined in PE specs.
1768 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1769 const char* ImportName,
1771 const LLVMRustCOFFShortExport* Exports,
1776 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1777 ConvertedExports.reserve(NumExports);
1779 for (size_t i = 0; i < NumExports; ++i) {
1780 bool ordinal_present = Exports[i].ordinal_present;
1781 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1782 ConvertedExports.push_back(llvm::object::COFFShortExport{
1783 Exports[i].name, // Name
1784 std::string{}, // ExtName
1785 std::string{}, // SymbolName
1786 std::string{}, // AliasTarget
1788 ordinal_present, // Noname
1795 auto Error = llvm::object::writeImportLibrary(
1799 static_cast<llvm::COFF::MachineTypes>(Machine),
1802 std::string errorString;
1803 llvm::raw_string_ostream stream(errorString);
1806 LLVMRustSetLastError(errorString.c_str());
1807 return LLVMRustResult::Failure;
1809 return LLVMRustResult::Success;
1813 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1814 extern "C" DiagnosticHandler *
1815 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1816 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1817 return DH.release();
1820 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1821 // handling. Ownership of the handler is moved to the LLVMContext.
1822 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1823 DiagnosticHandler *DH) {
1824 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1827 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1829 // Configures a diagnostic handler that invokes provided callback when a
1830 // backend needs to emit a diagnostic.
1832 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1833 // the RemarkPasses array specifies individual passes for which remarks will be
1835 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1836 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1837 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1838 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1840 class RustDiagnosticHandler final : public DiagnosticHandler {
1842 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1843 void *DiagnosticHandlerContext,
1844 bool RemarkAllPasses,
1845 std::vector<std::string> RemarkPasses)
1846 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1847 DiagnosticHandlerContext(DiagnosticHandlerContext),
1848 RemarkAllPasses(RemarkAllPasses),
1849 RemarkPasses(RemarkPasses) {}
1851 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1852 if (DiagnosticHandlerCallback) {
1853 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1859 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1860 return isRemarkEnabled(PassName);
1863 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1864 return isRemarkEnabled(PassName);
1867 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1868 return isRemarkEnabled(PassName);
1871 bool isAnyRemarkEnabled() const override {
1872 return RemarkAllPasses || !RemarkPasses.empty();
1876 bool isRemarkEnabled(StringRef PassName) const {
1877 if (RemarkAllPasses)
1880 for (auto &Pass : RemarkPasses)
1881 if (Pass == PassName)
1887 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1888 void *DiagnosticHandlerContext = nullptr;
1890 bool RemarkAllPasses = false;
1891 std::vector<std::string> RemarkPasses;
1894 std::vector<std::string> Passes;
1895 for (size_t I = 0; I != RemarkPassesLen; ++I)
1896 Passes.push_back(RemarkPasses[I]);
1898 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1899 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));