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" char *LLVMRustGetLastError(void) {
80 char *Ret = LastError;
85 extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) {
86 return unwrap(M)->getInstructionCount();
89 extern "C" void LLVMRustSetLastError(const char *Err) {
90 free((void *)LastError);
91 LastError = strdup(Err);
94 extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
95 auto ctx = new LLVMContext();
96 ctx->setDiscardValueNames(shouldDiscardNames);
100 extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
101 const char *Triple) {
102 unwrap(M)->setTargetTriple(Triple::normalize(Triple));
105 extern "C" void LLVMRustPrintPassTimings() {
106 raw_fd_ostream OS(2, false); // stderr.
107 TimerGroup::printAll(OS);
110 extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
112 return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
115 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
118 LLVMTypeRef FunctionTy) {
119 return wrap(unwrap(M)
120 ->getOrInsertFunction(StringRef(Name, NameLen),
121 unwrap<FunctionType>(FunctionTy))
126 extern "C" LLVMValueRef
127 LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
128 Module *Mod = unwrap(M);
129 StringRef NameRef(Name, NameLen);
131 // We don't use Module::getOrInsertGlobal because that returns a Constant*,
132 // which may either be the real GlobalVariable*, or a constant bitcast of it
133 // if our type doesn't match the original declaration. We always want the
134 // GlobalVariable* so we can access linkage, visibility, etc.
135 GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true);
137 GV = new GlobalVariable(*Mod, unwrap(Ty), false,
138 GlobalValue::ExternalLinkage, nullptr, NameRef);
142 extern "C" LLVMValueRef
143 LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
144 return wrap(new GlobalVariable(*unwrap(M),
147 GlobalValue::PrivateLinkage,
151 extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
152 return wrap(Type::getMetadataTy(*unwrap(C)));
155 static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
158 return Attribute::AlwaysInline;
160 return Attribute::ByVal;
162 return Attribute::Cold;
164 return Attribute::InlineHint;
166 return Attribute::MinSize;
168 return Attribute::Naked;
170 return Attribute::NoAlias;
172 return Attribute::NoCapture;
174 return Attribute::NoInline;
176 return Attribute::NonNull;
178 return Attribute::NoRedZone;
180 return Attribute::NoReturn;
182 return Attribute::NoUnwind;
183 case OptimizeForSize:
184 return Attribute::OptimizeForSize;
186 return Attribute::ReadOnly;
188 return Attribute::SExt;
190 return Attribute::StructRet;
192 return Attribute::UWTable;
194 return Attribute::ZExt;
196 return Attribute::InReg;
198 return Attribute::SanitizeThread;
199 case SanitizeAddress:
200 return Attribute::SanitizeAddress;
202 return Attribute::SanitizeMemory;
204 return Attribute::NonLazyBind;
206 return Attribute::OptimizeNone;
208 return Attribute::ReturnsTwice;
210 return Attribute::ReadNone;
211 case InaccessibleMemOnly:
212 return Attribute::InaccessibleMemOnly;
213 case SanitizeHWAddress:
214 return Attribute::SanitizeHWAddress;
216 return Attribute::WillReturn;
217 case StackProtectReq:
218 return Attribute::StackProtectReq;
219 case StackProtectStrong:
220 return Attribute::StackProtectStrong;
222 return Attribute::StackProtect;
224 report_fatal_error("bad AttributeKind");
227 template<typename T> static inline void AddAttribute(T *t, unsigned Index, Attribute Attr) {
228 #if LLVM_VERSION_LT(14, 0)
229 t->addAttribute(Index, Attr);
231 t->addAttributeAtIndex(Index, Attr);
235 extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
236 LLVMRustAttribute RustAttr) {
237 CallBase *Call = unwrap<CallBase>(Instr);
238 Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
239 AddAttribute(Call, Index, Attr);
242 extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index,
244 CallBase *Call = unwrap<CallBase>(Instr);
245 Attribute Attr = Attribute::get(Call->getContext(), Name);
246 AddAttribute(Call, Index, Attr);
249 extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
252 CallBase *Call = unwrap<CallBase>(Instr);
253 Attribute Attr = Attribute::getWithAlignment(Call->getContext(), Align(Bytes));
254 AddAttribute(Call, Index, Attr);
257 extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
260 CallBase *Call = unwrap<CallBase>(Instr);
261 Attribute Attr = Attribute::getWithDereferenceableBytes(Call->getContext(), Bytes);
262 AddAttribute(Call, Index, Attr);
265 extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
268 CallBase *Call = unwrap<CallBase>(Instr);
269 Attribute Attr = Attribute::getWithDereferenceableOrNullBytes(Call->getContext(), Bytes);
270 AddAttribute(Call, Index, Attr);
273 extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
275 CallBase *Call = unwrap<CallBase>(Instr);
276 Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
277 AddAttribute(Call, Index, Attr);
280 extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index,
282 CallBase *Call = unwrap<CallBase>(Instr);
283 Attribute Attr = Attribute::getWithStructRetType(Call->getContext(), unwrap(Ty));
284 AddAttribute(Call, Index, Attr);
287 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
288 LLVMRustAttribute RustAttr) {
289 Function *A = unwrap<Function>(Fn);
290 Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
291 AddAttribute(A, Index, Attr);
294 extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
297 Function *A = unwrap<Function>(Fn);
298 AddAttribute(A, Index, Attribute::getWithAlignment(
299 A->getContext(), llvm::Align(Bytes)));
302 extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
304 Function *A = unwrap<Function>(Fn);
305 AddAttribute(A, Index, Attribute::getWithDereferenceableBytes(A->getContext(),
309 extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
312 Function *A = unwrap<Function>(Fn);
313 AddAttribute(A, Index, Attribute::getWithDereferenceableOrNullBytes(
314 A->getContext(), Bytes));
317 extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
319 Function *F = unwrap<Function>(Fn);
320 Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
321 AddAttribute(F, Index, Attr);
324 extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index,
326 Function *F = unwrap<Function>(Fn);
327 Attribute Attr = Attribute::getWithStructRetType(F->getContext(), unwrap(Ty));
328 AddAttribute(F, Index, Attr);
331 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
335 Function *F = unwrap<Function>(Fn);
336 AddAttribute(F, Index, Attribute::get(
337 F->getContext(), StringRef(Name), StringRef(Value)));
340 extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
342 LLVMRustAttribute RustAttr) {
343 Function *F = unwrap<Function>(Fn);
344 Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr));
345 auto PAL = F->getAttributes();
346 AttributeList PALNew;
347 #if LLVM_VERSION_LT(14, 0)
349 PALNew = PAL.removeAttributes(F->getContext(), Index, B);
352 M.addAttribute(Attr);
353 PALNew = PAL.removeAttributesAtIndex(F->getContext(), Index, M);
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(LLVMModuleRef M, const char *Name,
731 unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
734 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
735 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
738 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
739 return new DIBuilder(*unwrap(M));
742 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
746 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
750 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
751 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
752 const char *Producer, size_t ProducerLen, bool isOptimized,
753 const char *Flags, unsigned RuntimeVer,
754 const char *SplitName, size_t SplitNameLen,
755 LLVMRustDebugEmissionKind Kind,
756 uint64_t DWOId, bool SplitDebugInlining) {
757 auto *File = unwrapDI<DIFile>(FileRef);
759 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
760 isOptimized, Flags, RuntimeVer,
761 StringRef(SplitName, SplitNameLen),
762 fromRust(Kind), DWOId, SplitDebugInlining));
765 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
766 LLVMRustDIBuilderRef Builder,
767 const char *Filename, size_t FilenameLen,
768 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
769 const char *Checksum, size_t ChecksumLen) {
770 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
771 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
773 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
774 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
775 StringRef(Directory, DirectoryLen),
779 extern "C" LLVMMetadataRef
780 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
781 LLVMMetadataRef ParameterTypes) {
782 return wrap(Builder->createSubroutineType(
783 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
786 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
787 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
788 const char *Name, size_t NameLen,
789 const char *LinkageName, size_t LinkageNameLen,
790 LLVMMetadataRef File, unsigned LineNo,
791 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
792 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
793 LLVMMetadataRef Decl) {
794 DITemplateParameterArray TParams =
795 DITemplateParameterArray(unwrap<MDTuple>(TParam));
796 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
797 DINode::DIFlags llvmFlags = fromRust(Flags);
798 DISubprogram *Sub = Builder->createFunction(
799 unwrapDI<DIScope>(Scope),
800 StringRef(Name, NameLen),
801 StringRef(LinkageName, LinkageNameLen),
802 unwrapDI<DIFile>(File), LineNo,
803 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
804 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
806 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
810 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
811 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
812 uint64_t SizeInBits, unsigned Encoding) {
813 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
816 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
817 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
818 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
819 return wrap(Builder->createTypedef(
820 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
821 LineNo, unwrapDIPtr<DIScope>(Scope)));
824 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
825 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
826 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
827 const char *Name, size_t NameLen) {
828 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
829 SizeInBits, AlignInBits,
831 StringRef(Name, NameLen)));
834 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
835 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
836 const char *Name, size_t NameLen,
837 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
838 uint32_t AlignInBits, LLVMRustDIFlags Flags,
839 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
840 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
841 const char *UniqueId, size_t UniqueIdLen) {
842 return wrap(Builder->createStructType(
843 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
844 unwrapDI<DIFile>(File), LineNumber,
845 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
846 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
847 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
850 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
851 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
852 const char *Name, size_t NameLen,
853 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
854 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
855 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
856 return wrap(Builder->createVariantPart(
857 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
858 unwrapDI<DIFile>(File), LineNumber,
859 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
860 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
863 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
864 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
865 const char *Name, size_t NameLen,
866 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
867 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
868 LLVMMetadataRef Ty) {
869 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
870 StringRef(Name, NameLen),
871 unwrapDI<DIFile>(File), LineNo,
872 SizeInBits, AlignInBits, OffsetInBits,
873 fromRust(Flags), unwrapDI<DIType>(Ty)));
876 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
877 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
878 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
879 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
880 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
881 llvm::ConstantInt* D = nullptr;
883 D = unwrap<llvm::ConstantInt>(Discriminant);
885 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
886 StringRef(Name, NameLen),
887 unwrapDI<DIFile>(File), LineNo,
888 SizeInBits, AlignInBits, OffsetInBits, D,
889 fromRust(Flags), unwrapDI<DIType>(Ty)));
892 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
893 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
894 LLVMMetadataRef File, unsigned Line, unsigned Col) {
895 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
896 unwrapDI<DIFile>(File), Line, Col));
899 extern "C" LLVMMetadataRef
900 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
901 LLVMMetadataRef Scope,
902 LLVMMetadataRef File) {
903 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
904 unwrapDI<DIFile>(File)));
907 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
908 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
909 const char *Name, size_t NameLen,
910 const char *LinkageName, size_t LinkageNameLen,
911 LLVMMetadataRef File, unsigned LineNo,
912 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
913 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
914 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
916 llvm::DIExpression *InitExpr = nullptr;
917 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
918 InitExpr = Builder->createConstantValueExpression(
919 IntVal->getValue().getSExtValue());
920 } else if (llvm::ConstantFP *FPVal =
921 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
922 InitExpr = Builder->createConstantValueExpression(
923 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
926 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
927 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
928 StringRef(LinkageName, LinkageNameLen),
929 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
930 /* isDefined */ true,
931 InitExpr, unwrapDIPtr<MDNode>(Decl),
932 /* templateParams */ nullptr,
935 InitVal->setMetadata("dbg", VarExpr);
937 return wrap(VarExpr);
940 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
941 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
942 const char *Name, size_t NameLen,
943 LLVMMetadataRef File, unsigned LineNo,
944 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
945 unsigned ArgNo, uint32_t AlignInBits) {
946 if (Tag == 0x100) { // DW_TAG_auto_variable
947 return wrap(Builder->createAutoVariable(
948 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
949 unwrapDI<DIFile>(File), LineNo,
950 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
952 return wrap(Builder->createParameterVariable(
953 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
954 unwrapDI<DIFile>(File), LineNo,
955 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
959 extern "C" LLVMMetadataRef
960 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
961 uint32_t AlignInBits, LLVMMetadataRef Ty,
962 LLVMMetadataRef Subscripts) {
964 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
965 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
968 extern "C" LLVMMetadataRef
969 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
971 return wrap(Builder->getOrCreateSubrange(Lo, Count));
974 extern "C" LLVMMetadataRef
975 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
976 LLVMMetadataRef *Ptr, unsigned Count) {
977 Metadata **DataValue = unwrap(Ptr);
979 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
982 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
983 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
984 int64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
985 LLVMBasicBlockRef InsertAtEnd) {
986 return wrap(Builder->insertDeclare(
987 unwrap(V), unwrap<DILocalVariable>(VarInfo),
988 Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
989 DebugLoc(cast<MDNode>(unwrap(DL))),
990 unwrap(InsertAtEnd)));
993 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
994 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
995 int64_t Value, bool IsUnsigned) {
996 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
999 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
1000 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1001 const char *Name, size_t NameLen,
1002 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1003 uint32_t AlignInBits, LLVMMetadataRef Elements,
1004 LLVMMetadataRef ClassTy, bool IsScoped) {
1005 return wrap(Builder->createEnumerationType(
1006 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
1007 unwrapDI<DIFile>(File), LineNumber,
1008 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
1009 unwrapDI<DIType>(ClassTy), "", IsScoped));
1012 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
1013 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1014 const char *Name, size_t NameLen,
1015 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1016 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
1017 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
1018 return wrap(Builder->createUnionType(
1019 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1020 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1021 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1022 StringRef(UniqueId, UniqueIdLen)));
1025 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
1026 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1027 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
1028 bool IsDefault = false; // FIXME: should we ever set this true?
1029 return wrap(Builder->createTemplateTypeParameter(
1030 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1033 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1034 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1035 const char *Name, size_t NameLen, bool ExportSymbols) {
1036 return wrap(Builder->createNameSpace(
1037 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1042 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1043 LLVMMetadataRef CompositeTy,
1044 LLVMMetadataRef Elements,
1045 LLVMMetadataRef Params) {
1046 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
1047 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1048 DINodeArray(unwrap<MDTuple>(Params)));
1051 extern "C" LLVMMetadataRef
1052 LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
1053 LLVMMetadataRef ScopeRef,
1054 LLVMMetadataRef InlinedAt) {
1055 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1056 DILocation *Loc = DILocation::get(
1057 Scope->getContext(), Line, Column, Scope,
1058 unwrapDIPtr<MDNode>(InlinedAt));
1062 extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {
1063 return dwarf::DW_OP_deref;
1066 extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1067 return dwarf::DW_OP_plus_uconst;
1070 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1071 RawRustStringOstream OS(Str);
1072 unwrap<llvm::Type>(Ty)->print(OS);
1075 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1076 RustStringRef Str) {
1077 RawRustStringOstream OS(Str);
1082 unwrap<llvm::Value>(V)->getType()->print(OS);
1084 unwrap<llvm::Value>(V)->print(OS);
1089 // LLVMArrayType function does not support 64-bit ElementCount
1090 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1091 uint64_t ElementCount) {
1092 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1095 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1097 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1098 RawRustStringOstream OS(Str);
1099 unwrap(T)->print(OS);
1102 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1103 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1104 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1105 RustStringRef FilenameOut, RustStringRef MessageOut) {
1106 // Undefined to call this not on an optimization diagnostic!
1107 llvm::DiagnosticInfoOptimizationBase *Opt =
1108 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1110 RawRustStringOstream PassNameOS(PassNameOut);
1111 PassNameOS << Opt->getPassName();
1112 *FunctionOut = wrap(&Opt->getFunction());
1114 RawRustStringOstream FilenameOS(FilenameOut);
1115 DiagnosticLocation loc = Opt->getLocation();
1116 if (loc.isValid()) {
1117 *Line = loc.getLine();
1118 *Column = loc.getColumn();
1119 FilenameOS << loc.getAbsolutePath();
1122 RawRustStringOstream MessageOS(MessageOut);
1123 MessageOS << Opt->getMsg();
1126 enum class LLVMRustDiagnosticLevel {
1134 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1135 LLVMRustDiagnosticLevel *LevelOut,
1136 unsigned *CookieOut,
1137 LLVMTwineRef *MessageOut) {
1138 // Undefined to call this not on an inline assembly diagnostic!
1139 llvm::DiagnosticInfoInlineAsm *IA =
1140 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1142 *CookieOut = IA->getLocCookie();
1143 *MessageOut = wrap(&IA->getMsgStr());
1145 switch (IA->getSeverity()) {
1147 *LevelOut = LLVMRustDiagnosticLevel::Error;
1150 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1153 *LevelOut = LLVMRustDiagnosticLevel::Note;
1156 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1159 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1163 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1164 RustStringRef Str) {
1165 RawRustStringOstream OS(Str);
1166 DiagnosticPrinterRawOStream DP(OS);
1167 unwrap(DI)->print(DP);
1170 enum class LLVMRustDiagnosticKind {
1174 DebugMetadataVersion,
1177 OptimizationRemarkMissed,
1178 OptimizationRemarkAnalysis,
1179 OptimizationRemarkAnalysisFPCommute,
1180 OptimizationRemarkAnalysisAliasing,
1181 OptimizationRemarkOther,
1182 OptimizationFailure,
1189 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1192 return LLVMRustDiagnosticKind::InlineAsm;
1194 return LLVMRustDiagnosticKind::StackSize;
1195 case DK_DebugMetadataVersion:
1196 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1197 case DK_SampleProfile:
1198 return LLVMRustDiagnosticKind::SampleProfile;
1199 case DK_OptimizationRemark:
1200 case DK_MachineOptimizationRemark:
1201 return LLVMRustDiagnosticKind::OptimizationRemark;
1202 case DK_OptimizationRemarkMissed:
1203 case DK_MachineOptimizationRemarkMissed:
1204 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1205 case DK_OptimizationRemarkAnalysis:
1206 case DK_MachineOptimizationRemarkAnalysis:
1207 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1208 case DK_OptimizationRemarkAnalysisFPCommute:
1209 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1210 case DK_OptimizationRemarkAnalysisAliasing:
1211 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1213 return LLVMRustDiagnosticKind::PGOProfile;
1215 return LLVMRustDiagnosticKind::Linker;
1216 case DK_Unsupported:
1217 return LLVMRustDiagnosticKind::Unsupported;
1218 #if LLVM_VERSION_GE(13, 0)
1220 return LLVMRustDiagnosticKind::SrcMgr;
1223 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1224 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1225 : LLVMRustDiagnosticKind::Other;
1229 extern "C" LLVMRustDiagnosticKind
1230 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1231 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1234 // This is kept distinct from LLVMGetTypeKind, because when
1235 // a new type kind is added, the Rust-side enum must be
1236 // updated or UB will result.
1237 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1238 switch (unwrap(Ty)->getTypeID()) {
1239 case Type::VoidTyID:
1240 return LLVMVoidTypeKind;
1241 case Type::HalfTyID:
1242 return LLVMHalfTypeKind;
1243 case Type::FloatTyID:
1244 return LLVMFloatTypeKind;
1245 case Type::DoubleTyID:
1246 return LLVMDoubleTypeKind;
1247 case Type::X86_FP80TyID:
1248 return LLVMX86_FP80TypeKind;
1249 case Type::FP128TyID:
1250 return LLVMFP128TypeKind;
1251 case Type::PPC_FP128TyID:
1252 return LLVMPPC_FP128TypeKind;
1253 case Type::LabelTyID:
1254 return LLVMLabelTypeKind;
1255 case Type::MetadataTyID:
1256 return LLVMMetadataTypeKind;
1257 case Type::IntegerTyID:
1258 return LLVMIntegerTypeKind;
1259 case Type::FunctionTyID:
1260 return LLVMFunctionTypeKind;
1261 case Type::StructTyID:
1262 return LLVMStructTypeKind;
1263 case Type::ArrayTyID:
1264 return LLVMArrayTypeKind;
1265 case Type::PointerTyID:
1266 return LLVMPointerTypeKind;
1267 case Type::FixedVectorTyID:
1268 return LLVMVectorTypeKind;
1269 case Type::X86_MMXTyID:
1270 return LLVMX86_MMXTypeKind;
1271 case Type::TokenTyID:
1272 return LLVMTokenTypeKind;
1273 case Type::ScalableVectorTyID:
1274 return LLVMScalableVectorTypeKind;
1275 case Type::BFloatTyID:
1276 return LLVMBFloatTypeKind;
1277 case Type::X86_AMXTyID:
1278 return LLVMX86_AMXTypeKind;
1280 report_fatal_error("Unhandled TypeID.");
1283 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1285 #if LLVM_VERSION_LT(13, 0)
1286 using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1288 using LLVMInlineAsmDiagHandlerTy = void*;
1291 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1292 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1293 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1294 // with LLVM 13 this function is gone.
1295 #if LLVM_VERSION_LT(13, 0)
1296 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1300 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1301 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1302 #if LLVM_VERSION_GE(13, 0)
1303 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1304 *Cookie = SM->getLocCookie();
1305 return wrap(&SM->getSMDiag());
1307 report_fatal_error("Shouldn't get called on older versions");
1311 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1312 RustStringRef MessageOut,
1313 RustStringRef BufferOut,
1314 LLVMRustDiagnosticLevel* LevelOut,
1316 unsigned* RangesOut,
1317 size_t* NumRanges) {
1318 SMDiagnostic& D = *unwrap(DRef);
1319 RawRustStringOstream MessageOS(MessageOut);
1320 MessageOS << D.getMessage();
1322 switch (D.getKind()) {
1323 case SourceMgr::DK_Error:
1324 *LevelOut = LLVMRustDiagnosticLevel::Error;
1326 case SourceMgr::DK_Warning:
1327 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1329 case SourceMgr::DK_Note:
1330 *LevelOut = LLVMRustDiagnosticLevel::Note;
1332 case SourceMgr::DK_Remark:
1333 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1336 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1339 if (D.getLoc() == SMLoc())
1342 const SourceMgr &LSM = *D.getSourceMgr();
1343 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1344 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1346 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1348 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1349 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1350 for (size_t i = 0; i < *NumRanges; i++) {
1351 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1352 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1358 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1359 LLVMValueRef ParentPad,
1361 LLVMValueRef *LLArgs,
1363 Value **Args = unwrap(LLArgs);
1364 if (ParentPad == nullptr) {
1365 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1366 ParentPad = wrap(Constant::getNullValue(Ty));
1368 return wrap(unwrap(B)->CreateCleanupPad(
1369 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1372 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1373 LLVMValueRef CleanupPad,
1374 LLVMBasicBlockRef UnwindBB) {
1375 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1376 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1379 extern "C" LLVMValueRef
1380 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1381 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1382 Value **Args = unwrap(LLArgs);
1383 return wrap(unwrap(B)->CreateCatchPad(
1384 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1387 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1389 LLVMBasicBlockRef BB) {
1390 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1394 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1395 LLVMValueRef ParentPad,
1396 LLVMBasicBlockRef BB,
1397 unsigned NumHandlers,
1399 if (ParentPad == nullptr) {
1400 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1401 ParentPad = wrap(Constant::getNullValue(Ty));
1403 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1404 NumHandlers, Name));
1407 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1408 LLVMBasicBlockRef Handler) {
1409 Value *CatchSwitch = unwrap(CatchSwitchRef);
1410 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1413 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1414 LLVMValueRef *Inputs,
1415 unsigned NumInputs) {
1416 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1419 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1423 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1424 LLVMValueRef *Args, unsigned NumArgs,
1425 OperandBundleDef *Bundle) {
1426 Value *Callee = unwrap(Fn);
1427 FunctionType *FTy = unwrap<FunctionType>(Ty);
1428 unsigned Len = Bundle ? 1 : 0;
1429 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1430 return wrap(unwrap(B)->CreateCall(
1431 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1434 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
1435 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1436 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
1439 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1440 LLVMValueRef Dst, unsigned DstAlign,
1441 LLVMValueRef Src, unsigned SrcAlign,
1442 LLVMValueRef Size, bool IsVolatile) {
1443 return wrap(unwrap(B)->CreateMemCpy(
1444 unwrap(Dst), MaybeAlign(DstAlign),
1445 unwrap(Src), MaybeAlign(SrcAlign),
1446 unwrap(Size), IsVolatile));
1449 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1450 LLVMValueRef Dst, unsigned DstAlign,
1451 LLVMValueRef Src, unsigned SrcAlign,
1452 LLVMValueRef Size, bool IsVolatile) {
1453 return wrap(unwrap(B)->CreateMemMove(
1454 unwrap(Dst), MaybeAlign(DstAlign),
1455 unwrap(Src), MaybeAlign(SrcAlign),
1456 unwrap(Size), IsVolatile));
1459 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1460 LLVMValueRef Dst, unsigned DstAlign,
1462 LLVMValueRef Size, bool IsVolatile) {
1463 return wrap(unwrap(B)->CreateMemSet(
1464 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1467 extern "C" LLVMValueRef
1468 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1469 LLVMValueRef *Args, unsigned NumArgs,
1470 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1471 OperandBundleDef *Bundle, const char *Name) {
1472 Value *Callee = unwrap(Fn);
1473 FunctionType *FTy = unwrap<FunctionType>(Ty);
1474 unsigned Len = Bundle ? 1 : 0;
1475 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1476 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
1477 makeArrayRef(unwrap(Args), NumArgs),
1481 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1482 LLVMBasicBlockRef BB) {
1483 auto Point = unwrap(BB)->getFirstInsertionPt();
1484 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1487 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1488 const char *Name, size_t NameLen) {
1489 Triple TargetTriple(unwrap(M)->getTargetTriple());
1490 GlobalObject *GV = unwrap<GlobalObject>(V);
1491 if (TargetTriple.supportsCOMDAT()) {
1492 StringRef NameRef(Name, NameLen);
1493 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1497 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1498 GlobalObject *GV = unwrap<GlobalObject>(V);
1499 GV->setComdat(nullptr);
1502 enum class LLVMRustLinkage {
1503 ExternalLinkage = 0,
1504 AvailableExternallyLinkage = 1,
1505 LinkOnceAnyLinkage = 2,
1506 LinkOnceODRLinkage = 3,
1509 AppendingLinkage = 6,
1510 InternalLinkage = 7,
1512 ExternalWeakLinkage = 9,
1516 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1518 case LLVMExternalLinkage:
1519 return LLVMRustLinkage::ExternalLinkage;
1520 case LLVMAvailableExternallyLinkage:
1521 return LLVMRustLinkage::AvailableExternallyLinkage;
1522 case LLVMLinkOnceAnyLinkage:
1523 return LLVMRustLinkage::LinkOnceAnyLinkage;
1524 case LLVMLinkOnceODRLinkage:
1525 return LLVMRustLinkage::LinkOnceODRLinkage;
1526 case LLVMWeakAnyLinkage:
1527 return LLVMRustLinkage::WeakAnyLinkage;
1528 case LLVMWeakODRLinkage:
1529 return LLVMRustLinkage::WeakODRLinkage;
1530 case LLVMAppendingLinkage:
1531 return LLVMRustLinkage::AppendingLinkage;
1532 case LLVMInternalLinkage:
1533 return LLVMRustLinkage::InternalLinkage;
1534 case LLVMPrivateLinkage:
1535 return LLVMRustLinkage::PrivateLinkage;
1536 case LLVMExternalWeakLinkage:
1537 return LLVMRustLinkage::ExternalWeakLinkage;
1538 case LLVMCommonLinkage:
1539 return LLVMRustLinkage::CommonLinkage;
1541 report_fatal_error("Invalid LLVMRustLinkage value!");
1545 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1547 case LLVMRustLinkage::ExternalLinkage:
1548 return LLVMExternalLinkage;
1549 case LLVMRustLinkage::AvailableExternallyLinkage:
1550 return LLVMAvailableExternallyLinkage;
1551 case LLVMRustLinkage::LinkOnceAnyLinkage:
1552 return LLVMLinkOnceAnyLinkage;
1553 case LLVMRustLinkage::LinkOnceODRLinkage:
1554 return LLVMLinkOnceODRLinkage;
1555 case LLVMRustLinkage::WeakAnyLinkage:
1556 return LLVMWeakAnyLinkage;
1557 case LLVMRustLinkage::WeakODRLinkage:
1558 return LLVMWeakODRLinkage;
1559 case LLVMRustLinkage::AppendingLinkage:
1560 return LLVMAppendingLinkage;
1561 case LLVMRustLinkage::InternalLinkage:
1562 return LLVMInternalLinkage;
1563 case LLVMRustLinkage::PrivateLinkage:
1564 return LLVMPrivateLinkage;
1565 case LLVMRustLinkage::ExternalWeakLinkage:
1566 return LLVMExternalWeakLinkage;
1567 case LLVMRustLinkage::CommonLinkage:
1568 return LLVMCommonLinkage;
1570 report_fatal_error("Invalid LLVMRustLinkage value!");
1573 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1574 return toRust(LLVMGetLinkage(V));
1577 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1578 LLVMRustLinkage RustLinkage) {
1579 LLVMSetLinkage(V, fromRust(RustLinkage));
1582 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1583 LLVMValueRef ConstantVal,
1584 LLVMValueRef *ConstantIndices,
1585 unsigned NumIndices) {
1586 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1588 Constant *Val = unwrap<Constant>(ConstantVal);
1589 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1592 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1593 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1594 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1596 auto C = unwrap<llvm::ConstantInt>(CV);
1597 if (C->getBitWidth() > 128) { return false; }
1600 AP = C->getValue().sextOrSelf(128);
1602 AP = C->getValue().zextOrSelf(128);
1604 *low = AP.getLoBits(64).getZExtValue();
1605 *high = AP.getHiBits(64).getZExtValue();
1609 enum class LLVMRustVisibility {
1615 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1617 case LLVMDefaultVisibility:
1618 return LLVMRustVisibility::Default;
1619 case LLVMHiddenVisibility:
1620 return LLVMRustVisibility::Hidden;
1621 case LLVMProtectedVisibility:
1622 return LLVMRustVisibility::Protected;
1624 report_fatal_error("Invalid LLVMRustVisibility value!");
1627 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1629 case LLVMRustVisibility::Default:
1630 return LLVMDefaultVisibility;
1631 case LLVMRustVisibility::Hidden:
1632 return LLVMHiddenVisibility;
1633 case LLVMRustVisibility::Protected:
1634 return LLVMProtectedVisibility;
1636 report_fatal_error("Invalid LLVMRustVisibility value!");
1639 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1640 return toRust(LLVMGetVisibility(V));
1643 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1644 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1645 LLVMTypeRef DestTy, bool isSigned) {
1646 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1649 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1650 LLVMRustVisibility RustVisibility) {
1651 LLVMSetVisibility(V, fromRust(RustVisibility));
1654 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1655 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1658 struct LLVMRustModuleBuffer {
1662 extern "C" LLVMRustModuleBuffer*
1663 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1664 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1666 raw_string_ostream OS(Ret->data);
1668 legacy::PassManager PM;
1669 PM.add(createBitcodeWriterPass(OS));
1673 return Ret.release();
1677 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1681 extern "C" const void*
1682 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1683 return Buffer->data.data();
1687 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1688 return Buffer->data.length();
1692 LLVMRustModuleCost(LLVMModuleRef M) {
1693 auto f = unwrap(M)->functions();
1694 return std::distance(std::begin(f), std::end(f));
1697 // Vector reductions:
1698 extern "C" LLVMValueRef
1699 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1700 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1702 extern "C" LLVMValueRef
1703 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1704 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1706 extern "C" LLVMValueRef
1707 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1708 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1710 extern "C" LLVMValueRef
1711 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1712 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1714 extern "C" LLVMValueRef
1715 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1716 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1718 extern "C" LLVMValueRef
1719 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1720 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1722 extern "C" LLVMValueRef
1723 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1724 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1726 extern "C" LLVMValueRef
1727 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1728 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1730 extern "C" LLVMValueRef
1731 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1732 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1734 extern "C" LLVMValueRef
1735 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1736 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1737 I->setHasNoNaNs(NoNaN);
1740 extern "C" LLVMValueRef
1741 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1742 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1743 I->setHasNoNaNs(NoNaN);
1747 extern "C" LLVMValueRef
1748 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1749 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1751 extern "C" LLVMValueRef
1752 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1753 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1756 // This struct contains all necessary info about a symbol exported from a DLL.
1757 struct LLVMRustCOFFShortExport {
1759 bool ordinal_present;
1760 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1764 // Machine must be a COFF machine type, as defined in PE specs.
1765 extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1766 const char* ImportName,
1768 const LLVMRustCOFFShortExport* Exports,
1773 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1774 ConvertedExports.reserve(NumExports);
1776 for (size_t i = 0; i < NumExports; ++i) {
1777 bool ordinal_present = Exports[i].ordinal_present;
1778 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
1779 ConvertedExports.push_back(llvm::object::COFFShortExport{
1780 Exports[i].name, // Name
1781 std::string{}, // ExtName
1782 std::string{}, // SymbolName
1783 std::string{}, // AliasTarget
1785 ordinal_present, // Noname
1792 auto Error = llvm::object::writeImportLibrary(
1796 static_cast<llvm::COFF::MachineTypes>(Machine),
1799 std::string errorString;
1800 llvm::raw_string_ostream stream(errorString);
1803 LLVMRustSetLastError(errorString.c_str());
1804 return LLVMRustResult::Failure;
1806 return LLVMRustResult::Success;
1810 // Transfers ownership of DiagnosticHandler unique_ptr to the caller.
1811 extern "C" DiagnosticHandler *
1812 LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
1813 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
1814 return DH.release();
1817 // Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
1818 // handling. Ownership of the handler is moved to the LLVMContext.
1819 extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
1820 DiagnosticHandler *DH) {
1821 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
1824 using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
1826 // Configures a diagnostic handler that invokes provided callback when a
1827 // backend needs to emit a diagnostic.
1829 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
1830 // the RemarkPasses array specifies individual passes for which remarks will be
1832 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
1833 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1834 void *DiagnosticHandlerContext, bool RemarkAllPasses,
1835 const char * const * RemarkPasses, size_t RemarkPassesLen) {
1837 class RustDiagnosticHandler final : public DiagnosticHandler {
1839 RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
1840 void *DiagnosticHandlerContext,
1841 bool RemarkAllPasses,
1842 std::vector<std::string> RemarkPasses)
1843 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
1844 DiagnosticHandlerContext(DiagnosticHandlerContext),
1845 RemarkAllPasses(RemarkAllPasses),
1846 RemarkPasses(RemarkPasses) {}
1848 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
1849 if (DiagnosticHandlerCallback) {
1850 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
1856 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
1857 return isRemarkEnabled(PassName);
1860 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
1861 return isRemarkEnabled(PassName);
1864 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
1865 return isRemarkEnabled(PassName);
1868 bool isAnyRemarkEnabled() const override {
1869 return RemarkAllPasses || !RemarkPasses.empty();
1873 bool isRemarkEnabled(StringRef PassName) const {
1874 if (RemarkAllPasses)
1877 for (auto &Pass : RemarkPasses)
1878 if (Pass == PassName)
1884 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
1885 void *DiagnosticHandlerContext = nullptr;
1887 bool RemarkAllPasses = false;
1888 std::vector<std::string> RemarkPasses;
1891 std::vector<std::string> Passes;
1892 for (size_t I = 0; I != RemarkPassesLen; ++I)
1893 Passes.push_back(RemarkPasses[I]);
1895 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
1896 DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));