2 #include "llvm/IR/CallSite.h"
3 #include "llvm/IR/DebugInfoMetadata.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/Object/Archive.h"
9 #include "llvm/Object/ObjectFile.h"
10 #include "llvm/Bitcode/BitcodeWriterPass.h"
11 #include "llvm/Support/Signals.h"
12 #include "llvm/ADT/Optional.h"
16 //===----------------------------------------------------------------------===
18 // This file defines alternate interfaces to core functions that are more
19 // readily callable by Rust's FFI.
21 //===----------------------------------------------------------------------===
24 using namespace llvm::sys;
25 using namespace llvm::object;
27 // LLVMAtomicOrdering is already an enum - don't create another
29 static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
31 case LLVMAtomicOrderingNotAtomic:
32 return AtomicOrdering::NotAtomic;
33 case LLVMAtomicOrderingUnordered:
34 return AtomicOrdering::Unordered;
35 case LLVMAtomicOrderingMonotonic:
36 return AtomicOrdering::Monotonic;
37 case LLVMAtomicOrderingAcquire:
38 return AtomicOrdering::Acquire;
39 case LLVMAtomicOrderingRelease:
40 return AtomicOrdering::Release;
41 case LLVMAtomicOrderingAcquireRelease:
42 return AtomicOrdering::AcquireRelease;
43 case LLVMAtomicOrderingSequentiallyConsistent:
44 return AtomicOrdering::SequentiallyConsistent;
47 report_fatal_error("Invalid LLVMAtomicOrdering value!");
50 static LLVM_THREAD_LOCAL char *LastError;
52 // Custom error handler for fatal LLVM errors.
54 // Notably it exits the process with code 101, unlike LLVM's default of 1.
55 static void FatalErrorHandler(void *UserData,
56 const std::string& Reason,
58 // Do the same thing that the default error handler does.
59 std::cerr << "LLVM ERROR: " << Reason << std::endl;
61 // Since this error handler exits the process, we have to run any cleanup that
62 // LLVM would run after handling the error. This might change with an LLVM
64 sys::RunInterruptHandlers();
69 extern "C" void LLVMRustInstallFatalErrorHandler() {
70 install_fatal_error_handler(FatalErrorHandler);
73 extern "C" LLVMMemoryBufferRef
74 LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
75 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr =
76 MemoryBuffer::getFile(Path, -1, false);
78 LLVMRustSetLastError(BufOr.getError().message().c_str());
81 return wrap(BufOr.get().release());
84 extern "C" char *LLVMRustGetLastError(void) {
85 char *Ret = LastError;
90 extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) {
91 return unwrap(M)->getInstructionCount();
94 extern "C" void LLVMRustSetLastError(const char *Err) {
95 free((void *)LastError);
96 LastError = strdup(Err);
99 extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
100 auto ctx = new LLVMContext();
101 ctx->setDiscardValueNames(shouldDiscardNames);
105 extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
106 const char *Triple) {
107 unwrap(M)->setTargetTriple(Triple::normalize(Triple));
110 extern "C" void LLVMRustPrintPassTimings() {
111 raw_fd_ostream OS(2, false); // stderr.
112 TimerGroup::printAll(OS);
115 extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
117 return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
120 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
123 LLVMTypeRef FunctionTy) {
124 return wrap(unwrap(M)
125 ->getOrInsertFunction(StringRef(Name, NameLen),
126 unwrap<FunctionType>(FunctionTy))
127 #if LLVM_VERSION_GE(9, 0)
133 extern "C" LLVMValueRef
134 LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
135 StringRef NameRef(Name, NameLen);
136 return wrap(unwrap(M)->getOrInsertGlobal(NameRef, unwrap(Ty)));
139 extern "C" LLVMValueRef
140 LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
141 return wrap(new GlobalVariable(*unwrap(M),
144 GlobalValue::PrivateLinkage,
148 extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
149 return wrap(Type::getMetadataTy(*unwrap(C)));
152 static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
155 return Attribute::AlwaysInline;
157 return Attribute::ByVal;
159 return Attribute::Cold;
161 return Attribute::InlineHint;
163 return Attribute::MinSize;
165 return Attribute::Naked;
167 return Attribute::NoAlias;
169 return Attribute::NoCapture;
171 return Attribute::NoInline;
173 return Attribute::NonNull;
175 return Attribute::NoRedZone;
177 return Attribute::NoReturn;
179 return Attribute::NoUnwind;
180 case OptimizeForSize:
181 return Attribute::OptimizeForSize;
183 return Attribute::ReadOnly;
185 return Attribute::SExt;
187 return Attribute::StructRet;
189 return Attribute::UWTable;
191 return Attribute::ZExt;
193 return Attribute::InReg;
195 return Attribute::SanitizeThread;
196 case SanitizeAddress:
197 return Attribute::SanitizeAddress;
199 return Attribute::SanitizeMemory;
201 return Attribute::NonLazyBind;
203 return Attribute::OptimizeNone;
205 return Attribute::ReturnsTwice;
207 return Attribute::ReadNone;
208 case InaccessibleMemOnly:
209 return Attribute::InaccessibleMemOnly;
211 report_fatal_error("bad AttributeKind");
214 extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
215 LLVMRustAttribute RustAttr) {
216 CallSite Call = CallSite(unwrap<Instruction>(Instr));
217 Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
218 Call.addAttribute(Index, Attr);
221 extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
224 CallSite Call = CallSite(unwrap<Instruction>(Instr));
226 B.addAlignmentAttr(Bytes);
227 Call.setAttributes(Call.getAttributes().addAttributes(
228 Call->getContext(), Index, B));
231 extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
234 CallSite Call = CallSite(unwrap<Instruction>(Instr));
236 B.addDereferenceableAttr(Bytes);
237 Call.setAttributes(Call.getAttributes().addAttributes(
238 Call->getContext(), Index, B));
241 extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
244 CallSite Call = CallSite(unwrap<Instruction>(Instr));
246 B.addDereferenceableOrNullAttr(Bytes);
247 Call.setAttributes(Call.getAttributes().addAttributes(
248 Call->getContext(), Index, B));
251 extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
253 CallSite Call = CallSite(unwrap<Instruction>(Instr));
254 #if LLVM_VERSION_GE(9, 0)
255 Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
257 Attribute Attr = Attribute::get(Call->getContext(), Attribute::ByVal);
259 Call.addAttribute(Index, Attr);
262 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
263 LLVMRustAttribute RustAttr) {
264 Function *A = unwrap<Function>(Fn);
265 Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
267 A->addAttributes(Index, B);
270 extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
273 Function *A = unwrap<Function>(Fn);
275 B.addAlignmentAttr(Bytes);
276 A->addAttributes(Index, B);
279 extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
281 Function *A = unwrap<Function>(Fn);
283 B.addDereferenceableAttr(Bytes);
284 A->addAttributes(Index, B);
287 extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
290 Function *A = unwrap<Function>(Fn);
292 B.addDereferenceableOrNullAttr(Bytes);
293 A->addAttributes(Index, B);
296 extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
298 Function *F = unwrap<Function>(Fn);
299 #if LLVM_VERSION_GE(9, 0)
300 Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
302 Attribute Attr = Attribute::get(F->getContext(), Attribute::ByVal);
304 F->addAttribute(Index, Attr);
307 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
311 Function *F = unwrap<Function>(Fn);
313 B.addAttribute(Name, Value);
314 F->addAttributes(Index, B);
317 extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
319 LLVMRustAttribute RustAttr) {
320 Function *F = unwrap<Function>(Fn);
321 Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr));
323 auto PAL = F->getAttributes();
324 auto PALNew = PAL.removeAttributes(F->getContext(), Index, B);
325 F->setAttributes(PALNew);
328 // enable fpmath flag UnsafeAlgebra
329 extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) {
330 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
335 extern "C" LLVMValueRef
336 LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef Source, const char *Name,
337 LLVMAtomicOrdering Order) {
338 LoadInst *LI = new LoadInst(unwrap(Source));
339 LI->setAtomic(fromRust(Order));
340 return wrap(unwrap(B)->Insert(LI, Name));
343 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
346 LLVMAtomicOrdering Order) {
347 StoreInst *SI = new StoreInst(unwrap(V), unwrap(Target));
348 SI->setAtomic(fromRust(Order));
349 return wrap(unwrap(B)->Insert(SI));
352 extern "C" LLVMValueRef
353 LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
354 LLVMValueRef Old, LLVMValueRef Source,
355 LLVMAtomicOrdering Order,
356 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
357 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
358 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
359 fromRust(FailureOrder));
364 enum class LLVMRustSynchronizationScope {
370 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
372 case LLVMRustSynchronizationScope::SingleThread:
373 return SyncScope::SingleThread;
374 case LLVMRustSynchronizationScope::CrossThread:
375 return SyncScope::System;
377 report_fatal_error("bad SynchronizationScope.");
381 extern "C" LLVMValueRef
382 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
383 LLVMRustSynchronizationScope Scope) {
384 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
387 enum class LLVMRustAsmDialect {
393 static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
395 case LLVMRustAsmDialect::Att:
396 return InlineAsm::AD_ATT;
397 case LLVMRustAsmDialect::Intel:
398 return InlineAsm::AD_Intel;
400 report_fatal_error("bad AsmDialect.");
404 extern "C" LLVMValueRef
405 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
406 char *Constraints, size_t ConstraintsLen,
407 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
408 LLVMRustAsmDialect Dialect) {
409 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
410 StringRef(AsmString, AsmStringLen),
411 StringRef(Constraints, ConstraintsLen),
412 HasSideEffects, IsAlignStack, fromRust(Dialect)));
415 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
416 size_t ConstraintsLen) {
417 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
418 StringRef(Constraints, ConstraintsLen));
421 extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
423 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
426 typedef DIBuilder *LLVMRustDIBuilderRef;
428 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
429 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
432 #define DIDescriptor DIScope
433 #define DIArray DINodeArray
434 #define unwrapDI unwrapDIPtr
436 // These values **must** match debuginfo::DIFlags! They also *happen*
437 // to match LLVM, but that isn't required as we do giant sets of
438 // matching below. The value shouldn't be directly passed to LLVM.
439 enum class LLVMRustDIFlags : uint32_t {
444 FlagFwdDecl = (1 << 2),
445 FlagAppleBlock = (1 << 3),
446 FlagBlockByrefStruct = (1 << 4),
447 FlagVirtual = (1 << 5),
448 FlagArtificial = (1 << 6),
449 FlagExplicit = (1 << 7),
450 FlagPrototyped = (1 << 8),
451 FlagObjcClassComplete = (1 << 9),
452 FlagObjectPointer = (1 << 10),
453 FlagVector = (1 << 11),
454 FlagStaticMember = (1 << 12),
455 FlagLValueReference = (1 << 13),
456 FlagRValueReference = (1 << 14),
457 FlagExternalTypeRef = (1 << 15),
458 FlagIntroducedVirtual = (1 << 18),
459 FlagBitField = (1 << 19),
460 FlagNoReturn = (1 << 20),
461 // Do not add values that are not supported by the minimum LLVM
462 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
465 inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
466 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
467 static_cast<uint32_t>(B));
470 inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
471 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
472 static_cast<uint32_t>(B));
475 inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
479 inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
481 inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
482 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
485 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
486 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
488 switch (visibility(Flags)) {
489 case LLVMRustDIFlags::FlagPrivate:
490 Result |= DINode::DIFlags::FlagPrivate;
492 case LLVMRustDIFlags::FlagProtected:
493 Result |= DINode::DIFlags::FlagProtected;
495 case LLVMRustDIFlags::FlagPublic:
496 Result |= DINode::DIFlags::FlagPublic;
499 // The rest are handled below
503 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
504 Result |= DINode::DIFlags::FlagFwdDecl;
506 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
507 Result |= DINode::DIFlags::FlagAppleBlock;
509 #if LLVM_VERSION_LT(10, 0)
510 if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) {
511 Result |= DINode::DIFlags::FlagBlockByrefStruct;
514 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
515 Result |= DINode::DIFlags::FlagVirtual;
517 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
518 Result |= DINode::DIFlags::FlagArtificial;
520 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
521 Result |= DINode::DIFlags::FlagExplicit;
523 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
524 Result |= DINode::DIFlags::FlagPrototyped;
526 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
527 Result |= DINode::DIFlags::FlagObjcClassComplete;
529 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
530 Result |= DINode::DIFlags::FlagObjectPointer;
532 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
533 Result |= DINode::DIFlags::FlagVector;
535 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
536 Result |= DINode::DIFlags::FlagStaticMember;
538 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
539 Result |= DINode::DIFlags::FlagLValueReference;
541 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
542 Result |= DINode::DIFlags::FlagRValueReference;
544 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
545 Result |= DINode::DIFlags::FlagIntroducedVirtual;
547 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
548 Result |= DINode::DIFlags::FlagBitField;
550 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
551 Result |= DINode::DIFlags::FlagNoReturn;
557 // These values **must** match debuginfo::DISPFlags! They also *happen*
558 // to match LLVM, but that isn't required as we do giant sets of
559 // matching below. The value shouldn't be directly passed to LLVM.
560 enum class LLVMRustDISPFlags : uint32_t {
563 SPFlagPureVirtual = 2,
564 SPFlagLocalToUnit = (1 << 2),
565 SPFlagDefinition = (1 << 3),
566 SPFlagOptimized = (1 << 4),
567 SPFlagMainSubprogram = (1 << 5),
568 // Do not add values that are not supported by the minimum LLVM
569 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
570 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
573 inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
574 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
575 static_cast<uint32_t>(B));
578 inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
579 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
580 static_cast<uint32_t>(B));
583 inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
587 inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
589 inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
590 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
593 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
594 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
596 switch (virtuality(SPFlags)) {
597 case LLVMRustDISPFlags::SPFlagVirtual:
598 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
600 case LLVMRustDISPFlags::SPFlagPureVirtual:
601 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
604 // The rest are handled below
608 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
609 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
611 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
612 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
614 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
615 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
617 #if LLVM_VERSION_GE(9, 0)
618 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
619 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
626 enum class LLVMRustDebugEmissionKind {
632 static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
634 case LLVMRustDebugEmissionKind::NoDebug:
635 return DICompileUnit::DebugEmissionKind::NoDebug;
636 case LLVMRustDebugEmissionKind::FullDebug:
637 return DICompileUnit::DebugEmissionKind::FullDebug;
638 case LLVMRustDebugEmissionKind::LineTablesOnly:
639 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
641 report_fatal_error("bad DebugEmissionKind.");
645 enum class LLVMRustChecksumKind {
651 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
653 case LLVMRustChecksumKind::None:
655 case LLVMRustChecksumKind::MD5:
656 return DIFile::ChecksumKind::CSK_MD5;
657 case LLVMRustChecksumKind::SHA1:
658 return DIFile::ChecksumKind::CSK_SHA1;
660 report_fatal_error("bad ChecksumKind.");
664 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
665 return DEBUG_METADATA_VERSION;
668 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
670 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
672 extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
674 unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
677 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
678 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
681 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
682 return new DIBuilder(*unwrap(M));
685 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
689 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
693 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
694 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
695 const char *Producer, size_t ProducerLen, bool isOptimized,
696 const char *Flags, unsigned RuntimeVer,
697 const char *SplitName, size_t SplitNameLen,
698 LLVMRustDebugEmissionKind Kind) {
699 auto *File = unwrapDI<DIFile>(FileRef);
701 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
702 isOptimized, Flags, RuntimeVer,
703 StringRef(SplitName, SplitNameLen),
707 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
708 LLVMRustDIBuilderRef Builder,
709 const char *Filename, size_t FilenameLen,
710 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
711 const char *Checksum, size_t ChecksumLen) {
712 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
713 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
715 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
716 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
717 StringRef(Directory, DirectoryLen),
721 extern "C" LLVMMetadataRef
722 LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
723 LLVMMetadataRef ParameterTypes) {
724 return wrap(Builder->createSubroutineType(
725 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
728 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
729 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
730 const char *Name, size_t NameLen,
731 const char *LinkageName, size_t LinkageNameLen,
732 LLVMMetadataRef File, unsigned LineNo,
733 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
734 LLVMRustDISPFlags SPFlags, LLVMValueRef Fn, LLVMMetadataRef TParam,
735 LLVMMetadataRef Decl) {
736 DITemplateParameterArray TParams =
737 DITemplateParameterArray(unwrap<MDTuple>(TParam));
738 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
739 DINode::DIFlags llvmFlags = fromRust(Flags);
740 #if LLVM_VERSION_LT(9, 0)
741 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram))
742 llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
744 DISubprogram *Sub = Builder->createFunction(
745 unwrapDI<DIScope>(Scope),
746 StringRef(Name, NameLen),
747 StringRef(LinkageName, LinkageNameLen),
748 unwrapDI<DIFile>(File), LineNo,
749 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
750 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
751 unwrap<Function>(Fn)->setSubprogram(Sub);
755 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
756 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
757 uint64_t SizeInBits, unsigned Encoding) {
758 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
761 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
762 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
763 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
764 const char *Name, size_t NameLen) {
765 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
766 SizeInBits, AlignInBits,
768 StringRef(Name, NameLen)));
771 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
772 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
773 const char *Name, size_t NameLen,
774 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
775 uint32_t AlignInBits, LLVMRustDIFlags Flags,
776 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
777 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
778 const char *UniqueId, size_t UniqueIdLen) {
779 return wrap(Builder->createStructType(
780 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
781 unwrapDI<DIFile>(File), LineNumber,
782 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
783 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
784 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
787 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
788 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
789 const char *Name, size_t NameLen,
790 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
791 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
792 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
793 return wrap(Builder->createVariantPart(
794 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
795 unwrapDI<DIFile>(File), LineNumber,
796 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
797 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
800 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
801 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
802 const char *Name, size_t NameLen,
803 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
804 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
805 LLVMMetadataRef Ty) {
806 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
807 StringRef(Name, NameLen),
808 unwrapDI<DIFile>(File), LineNo,
809 SizeInBits, AlignInBits, OffsetInBits,
810 fromRust(Flags), unwrapDI<DIType>(Ty)));
813 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
814 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
815 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
816 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
817 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
818 llvm::ConstantInt* D = nullptr;
820 D = unwrap<llvm::ConstantInt>(Discriminant);
822 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
823 StringRef(Name, NameLen),
824 unwrapDI<DIFile>(File), LineNo,
825 SizeInBits, AlignInBits, OffsetInBits, D,
826 fromRust(Flags), unwrapDI<DIType>(Ty)));
829 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
830 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
831 LLVMMetadataRef File, unsigned Line, unsigned Col) {
832 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
833 unwrapDI<DIFile>(File), Line, Col));
836 extern "C" LLVMMetadataRef
837 LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
838 LLVMMetadataRef Scope,
839 LLVMMetadataRef File) {
840 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
841 unwrapDI<DIFile>(File)));
844 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
845 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
846 const char *Name, size_t NameLen,
847 const char *LinkageName, size_t LinkageNameLen,
848 LLVMMetadataRef File, unsigned LineNo,
849 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
850 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
851 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
853 llvm::DIExpression *InitExpr = nullptr;
854 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
855 InitExpr = Builder->createConstantValueExpression(
856 IntVal->getValue().getSExtValue());
857 } else if (llvm::ConstantFP *FPVal =
858 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
859 InitExpr = Builder->createConstantValueExpression(
860 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
863 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
864 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
865 StringRef(LinkageName, LinkageNameLen),
866 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
867 #if LLVM_VERSION_GE(10, 0)
868 /* isDefined */ true,
870 InitExpr, unwrapDIPtr<MDNode>(Decl),
871 /* templateParams */ nullptr,
874 InitVal->setMetadata("dbg", VarExpr);
876 return wrap(VarExpr);
879 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
880 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
881 const char *Name, size_t NameLen,
882 LLVMMetadataRef File, unsigned LineNo,
883 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
884 unsigned ArgNo, uint32_t AlignInBits) {
885 if (Tag == 0x100) { // DW_TAG_auto_variable
886 return wrap(Builder->createAutoVariable(
887 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
888 unwrapDI<DIFile>(File), LineNo,
889 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
891 return wrap(Builder->createParameterVariable(
892 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
893 unwrapDI<DIFile>(File), LineNo,
894 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
898 extern "C" LLVMMetadataRef
899 LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
900 uint32_t AlignInBits, LLVMMetadataRef Ty,
901 LLVMMetadataRef Subscripts) {
903 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
904 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
907 extern "C" LLVMMetadataRef
908 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
910 return wrap(Builder->getOrCreateSubrange(Lo, Count));
913 extern "C" LLVMMetadataRef
914 LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
915 LLVMMetadataRef *Ptr, unsigned Count) {
916 Metadata **DataValue = unwrap(Ptr);
918 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
921 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
922 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
923 int64_t *AddrOps, unsigned AddrOpsCount, LLVMValueRef DL,
924 LLVMBasicBlockRef InsertAtEnd) {
925 return wrap(Builder->insertDeclare(
926 unwrap(V), unwrap<DILocalVariable>(VarInfo),
927 Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
928 DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
929 unwrap(InsertAtEnd)));
932 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
933 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
934 int64_t Value, bool IsUnsigned) {
935 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
938 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
939 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
940 const char *Name, size_t NameLen,
941 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
942 uint32_t AlignInBits, LLVMMetadataRef Elements,
943 LLVMMetadataRef ClassTy, bool IsScoped) {
944 return wrap(Builder->createEnumerationType(
945 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
946 unwrapDI<DIFile>(File), LineNumber,
947 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
948 unwrapDI<DIType>(ClassTy), "", IsScoped));
951 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
952 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
953 const char *Name, size_t NameLen,
954 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
955 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
956 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
957 return wrap(Builder->createUnionType(
958 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
959 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
960 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
961 StringRef(UniqueId, UniqueIdLen)));
964 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
965 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
966 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
967 return wrap(Builder->createTemplateTypeParameter(
968 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty)));
971 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
972 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
973 const char *Name, size_t NameLen, bool ExportSymbols) {
974 return wrap(Builder->createNameSpace(
975 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
980 LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
981 LLVMMetadataRef CompositeTy,
982 LLVMMetadataRef Elements,
983 LLVMMetadataRef Params) {
984 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
985 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
986 DINodeArray(unwrap<MDTuple>(Params)));
989 extern "C" LLVMValueRef
990 LLVMRustDIBuilderCreateDebugLocation(LLVMContextRef ContextRef, unsigned Line,
991 unsigned Column, LLVMMetadataRef Scope,
992 LLVMMetadataRef InlinedAt) {
993 LLVMContext &Context = *unwrap(ContextRef);
995 DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(Scope),
996 unwrapDIPtr<MDNode>(InlinedAt));
998 return wrap(MetadataAsValue::get(Context, debug_loc.getAsMDNode()));
1001 extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {
1002 return dwarf::DW_OP_deref;
1005 extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() {
1006 return dwarf::DW_OP_plus_uconst;
1009 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1010 RawRustStringOstream OS(Str);
1011 unwrap<llvm::Type>(Ty)->print(OS);
1014 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1015 RustStringRef Str) {
1016 RawRustStringOstream OS(Str);
1021 unwrap<llvm::Value>(V)->getType()->print(OS);
1023 unwrap<llvm::Value>(V)->print(OS);
1028 // Note that the two following functions look quite similar to the
1029 // LLVMGetSectionName function. Sadly, it appears that this function only
1030 // returns a char* pointer, which isn't guaranteed to be null-terminated. The
1031 // function provided by LLVM doesn't return the length, so we've created our own
1032 // function which returns the length as well as the data pointer.
1034 // For an example of this not returning a null terminated string, see
1035 // lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the
1036 // branches explicitly creates a StringRef without a null terminator, and then
1039 inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
1040 return reinterpret_cast<section_iterator *>(SI);
1043 extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI,
1045 #if LLVM_VERSION_GE(10, 0)
1046 auto NameOrErr = (*unwrap(SI))->getName();
1048 report_fatal_error(NameOrErr.takeError());
1049 *Ptr = NameOrErr->data();
1050 return NameOrErr->size();
1053 if (std::error_code EC = (*unwrap(SI))->getName(Ret))
1054 report_fatal_error(EC.message());
1060 // LLVMArrayType function does not support 64-bit ElementCount
1061 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1062 uint64_t ElementCount) {
1063 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1066 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1068 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1069 RawRustStringOstream OS(Str);
1070 unwrap(T)->print(OS);
1073 extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1074 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
1075 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1076 RustStringRef FilenameOut, RustStringRef MessageOut) {
1077 // Undefined to call this not on an optimization diagnostic!
1078 llvm::DiagnosticInfoOptimizationBase *Opt =
1079 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1081 RawRustStringOstream PassNameOS(PassNameOut);
1082 PassNameOS << Opt->getPassName();
1083 *FunctionOut = wrap(&Opt->getFunction());
1085 RawRustStringOstream FilenameOS(FilenameOut);
1086 DiagnosticLocation loc = Opt->getLocation();
1087 if (loc.isValid()) {
1088 *Line = loc.getLine();
1089 *Column = loc.getColumn();
1090 FilenameOS << loc.getAbsolutePath();
1093 RawRustStringOstream MessageOS(MessageOut);
1094 MessageOS << Opt->getMsg();
1097 enum class LLVMRustDiagnosticLevel {
1105 LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1106 LLVMRustDiagnosticLevel *LevelOut,
1107 unsigned *CookieOut,
1108 LLVMTwineRef *MessageOut,
1109 LLVMValueRef *InstructionOut) {
1110 // Undefined to call this not on an inline assembly diagnostic!
1111 llvm::DiagnosticInfoInlineAsm *IA =
1112 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
1114 *CookieOut = IA->getLocCookie();
1115 *MessageOut = wrap(&IA->getMsgStr());
1116 *InstructionOut = wrap(IA->getInstruction());
1118 switch (IA->getSeverity()) {
1120 *LevelOut = LLVMRustDiagnosticLevel::Error;
1123 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1126 *LevelOut = LLVMRustDiagnosticLevel::Note;
1129 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1132 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1136 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1137 RustStringRef Str) {
1138 RawRustStringOstream OS(Str);
1139 DiagnosticPrinterRawOStream DP(OS);
1140 unwrap(DI)->print(DP);
1143 enum class LLVMRustDiagnosticKind {
1147 DebugMetadataVersion,
1150 OptimizationRemarkMissed,
1151 OptimizationRemarkAnalysis,
1152 OptimizationRemarkAnalysisFPCommute,
1153 OptimizationRemarkAnalysisAliasing,
1154 OptimizationRemarkOther,
1155 OptimizationFailure,
1160 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1163 return LLVMRustDiagnosticKind::InlineAsm;
1165 return LLVMRustDiagnosticKind::StackSize;
1166 case DK_DebugMetadataVersion:
1167 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1168 case DK_SampleProfile:
1169 return LLVMRustDiagnosticKind::SampleProfile;
1170 case DK_OptimizationRemark:
1171 return LLVMRustDiagnosticKind::OptimizationRemark;
1172 case DK_OptimizationRemarkMissed:
1173 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1174 case DK_OptimizationRemarkAnalysis:
1175 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
1176 case DK_OptimizationRemarkAnalysisFPCommute:
1177 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1178 case DK_OptimizationRemarkAnalysisAliasing:
1179 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
1181 return LLVMRustDiagnosticKind::PGOProfile;
1183 return LLVMRustDiagnosticKind::Linker;
1185 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1186 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1187 : LLVMRustDiagnosticKind::Other;
1191 extern "C" LLVMRustDiagnosticKind
1192 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1193 return toRust((DiagnosticKind)unwrap(DI)->getKind());
1196 // This is kept distinct from LLVMGetTypeKind, because when
1197 // a new type kind is added, the Rust-side enum must be
1198 // updated or UB will result.
1199 extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1200 switch (unwrap(Ty)->getTypeID()) {
1201 case Type::VoidTyID:
1202 return LLVMVoidTypeKind;
1203 case Type::HalfTyID:
1204 return LLVMHalfTypeKind;
1205 case Type::FloatTyID:
1206 return LLVMFloatTypeKind;
1207 case Type::DoubleTyID:
1208 return LLVMDoubleTypeKind;
1209 case Type::X86_FP80TyID:
1210 return LLVMX86_FP80TypeKind;
1211 case Type::FP128TyID:
1212 return LLVMFP128TypeKind;
1213 case Type::PPC_FP128TyID:
1214 return LLVMPPC_FP128TypeKind;
1215 case Type::LabelTyID:
1216 return LLVMLabelTypeKind;
1217 case Type::MetadataTyID:
1218 return LLVMMetadataTypeKind;
1219 case Type::IntegerTyID:
1220 return LLVMIntegerTypeKind;
1221 case Type::FunctionTyID:
1222 return LLVMFunctionTypeKind;
1223 case Type::StructTyID:
1224 return LLVMStructTypeKind;
1225 case Type::ArrayTyID:
1226 return LLVMArrayTypeKind;
1227 case Type::PointerTyID:
1228 return LLVMPointerTypeKind;
1229 case Type::VectorTyID:
1230 return LLVMVectorTypeKind;
1231 case Type::X86_MMXTyID:
1232 return LLVMX86_MMXTypeKind;
1233 case Type::TokenTyID:
1234 return LLVMTokenTypeKind;
1236 report_fatal_error("Unhandled TypeID.");
1239 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1241 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
1242 LLVMContextRef C, LLVMContext::InlineAsmDiagHandlerTy H, void *CX) {
1243 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
1246 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1247 RustStringRef MessageOut,
1248 RustStringRef BufferOut,
1249 LLVMRustDiagnosticLevel* LevelOut,
1251 unsigned* RangesOut,
1252 size_t* NumRanges) {
1253 SMDiagnostic& D = *unwrap(DRef);
1254 RawRustStringOstream MessageOS(MessageOut);
1255 MessageOS << D.getMessage();
1257 switch (D.getKind()) {
1258 case SourceMgr::DK_Error:
1259 *LevelOut = LLVMRustDiagnosticLevel::Error;
1261 case SourceMgr::DK_Warning:
1262 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1264 case SourceMgr::DK_Note:
1265 *LevelOut = LLVMRustDiagnosticLevel::Note;
1267 case SourceMgr::DK_Remark:
1268 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1271 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1274 if (D.getLoc() == SMLoc())
1277 const SourceMgr &LSM = *D.getSourceMgr();
1278 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1279 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1281 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1283 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1284 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1285 for (size_t i = 0; i < *NumRanges; i++) {
1286 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1287 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1293 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1294 LLVMValueRef ParentPad,
1296 LLVMValueRef *LLArgs,
1298 Value **Args = unwrap(LLArgs);
1299 if (ParentPad == nullptr) {
1300 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1301 ParentPad = wrap(Constant::getNullValue(Ty));
1303 return wrap(unwrap(B)->CreateCleanupPad(
1304 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1307 extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1308 LLVMValueRef CleanupPad,
1309 LLVMBasicBlockRef UnwindBB) {
1310 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1311 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
1314 extern "C" LLVMValueRef
1315 LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1316 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
1317 Value **Args = unwrap(LLArgs);
1318 return wrap(unwrap(B)->CreateCatchPad(
1319 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
1322 extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1324 LLVMBasicBlockRef BB) {
1325 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1329 extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1330 LLVMValueRef ParentPad,
1331 LLVMBasicBlockRef BB,
1332 unsigned NumHandlers,
1334 if (ParentPad == nullptr) {
1335 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1336 ParentPad = wrap(Constant::getNullValue(Ty));
1338 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1339 NumHandlers, Name));
1342 extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1343 LLVMBasicBlockRef Handler) {
1344 Value *CatchSwitch = unwrap(CatchSwitchRef);
1345 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
1348 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1349 LLVMValueRef *Inputs,
1350 unsigned NumInputs) {
1351 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1354 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
1358 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
1359 LLVMValueRef *Args, unsigned NumArgs,
1360 OperandBundleDef *Bundle) {
1361 unsigned Len = Bundle ? 1 : 0;
1362 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1363 return wrap(unwrap(B)->CreateCall(
1364 unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Bundles));
1367 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1368 LLVMValueRef Dst, unsigned DstAlign,
1369 LLVMValueRef Src, unsigned SrcAlign,
1370 LLVMValueRef Size, bool IsVolatile) {
1371 #if LLVM_VERSION_GE(10, 0)
1372 return wrap(unwrap(B)->CreateMemCpy(
1373 unwrap(Dst), MaybeAlign(DstAlign),
1374 unwrap(Src), MaybeAlign(SrcAlign),
1375 unwrap(Size), IsVolatile));
1377 return wrap(unwrap(B)->CreateMemCpy(
1378 unwrap(Dst), DstAlign,
1379 unwrap(Src), SrcAlign,
1380 unwrap(Size), IsVolatile));
1384 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1385 LLVMValueRef Dst, unsigned DstAlign,
1386 LLVMValueRef Src, unsigned SrcAlign,
1387 LLVMValueRef Size, bool IsVolatile) {
1388 #if LLVM_VERSION_GE(10, 0)
1389 return wrap(unwrap(B)->CreateMemMove(
1390 unwrap(Dst), MaybeAlign(DstAlign),
1391 unwrap(Src), MaybeAlign(SrcAlign),
1392 unwrap(Size), IsVolatile));
1394 return wrap(unwrap(B)->CreateMemMove(
1395 unwrap(Dst), DstAlign,
1396 unwrap(Src), SrcAlign,
1397 unwrap(Size), IsVolatile));
1401 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1402 LLVMValueRef Dst, unsigned DstAlign,
1404 LLVMValueRef Size, bool IsVolatile) {
1405 #if LLVM_VERSION_GE(10, 0)
1406 return wrap(unwrap(B)->CreateMemSet(
1407 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
1409 return wrap(unwrap(B)->CreateMemSet(
1410 unwrap(Dst), unwrap(Val), unwrap(Size), DstAlign, IsVolatile));
1414 extern "C" LLVMValueRef
1415 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
1416 unsigned NumArgs, LLVMBasicBlockRef Then,
1417 LLVMBasicBlockRef Catch, OperandBundleDef *Bundle,
1419 unsigned Len = Bundle ? 1 : 0;
1420 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1421 return wrap(unwrap(B)->CreateInvoke(unwrap(Fn), unwrap(Then), unwrap(Catch),
1422 makeArrayRef(unwrap(Args), NumArgs),
1426 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1427 LLVMBasicBlockRef BB) {
1428 auto Point = unwrap(BB)->getFirstInsertionPt();
1429 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
1432 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
1433 const char *Name, size_t NameLen) {
1434 Triple TargetTriple(unwrap(M)->getTargetTriple());
1435 GlobalObject *GV = unwrap<GlobalObject>(V);
1436 if (!TargetTriple.isOSBinFormatMachO()) {
1437 StringRef NameRef(Name, NameLen);
1438 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
1442 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1443 GlobalObject *GV = unwrap<GlobalObject>(V);
1444 GV->setComdat(nullptr);
1447 enum class LLVMRustLinkage {
1448 ExternalLinkage = 0,
1449 AvailableExternallyLinkage = 1,
1450 LinkOnceAnyLinkage = 2,
1451 LinkOnceODRLinkage = 3,
1454 AppendingLinkage = 6,
1455 InternalLinkage = 7,
1457 ExternalWeakLinkage = 9,
1461 static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1463 case LLVMExternalLinkage:
1464 return LLVMRustLinkage::ExternalLinkage;
1465 case LLVMAvailableExternallyLinkage:
1466 return LLVMRustLinkage::AvailableExternallyLinkage;
1467 case LLVMLinkOnceAnyLinkage:
1468 return LLVMRustLinkage::LinkOnceAnyLinkage;
1469 case LLVMLinkOnceODRLinkage:
1470 return LLVMRustLinkage::LinkOnceODRLinkage;
1471 case LLVMWeakAnyLinkage:
1472 return LLVMRustLinkage::WeakAnyLinkage;
1473 case LLVMWeakODRLinkage:
1474 return LLVMRustLinkage::WeakODRLinkage;
1475 case LLVMAppendingLinkage:
1476 return LLVMRustLinkage::AppendingLinkage;
1477 case LLVMInternalLinkage:
1478 return LLVMRustLinkage::InternalLinkage;
1479 case LLVMPrivateLinkage:
1480 return LLVMRustLinkage::PrivateLinkage;
1481 case LLVMExternalWeakLinkage:
1482 return LLVMRustLinkage::ExternalWeakLinkage;
1483 case LLVMCommonLinkage:
1484 return LLVMRustLinkage::CommonLinkage;
1486 report_fatal_error("Invalid LLVMRustLinkage value!");
1490 static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1492 case LLVMRustLinkage::ExternalLinkage:
1493 return LLVMExternalLinkage;
1494 case LLVMRustLinkage::AvailableExternallyLinkage:
1495 return LLVMAvailableExternallyLinkage;
1496 case LLVMRustLinkage::LinkOnceAnyLinkage:
1497 return LLVMLinkOnceAnyLinkage;
1498 case LLVMRustLinkage::LinkOnceODRLinkage:
1499 return LLVMLinkOnceODRLinkage;
1500 case LLVMRustLinkage::WeakAnyLinkage:
1501 return LLVMWeakAnyLinkage;
1502 case LLVMRustLinkage::WeakODRLinkage:
1503 return LLVMWeakODRLinkage;
1504 case LLVMRustLinkage::AppendingLinkage:
1505 return LLVMAppendingLinkage;
1506 case LLVMRustLinkage::InternalLinkage:
1507 return LLVMInternalLinkage;
1508 case LLVMRustLinkage::PrivateLinkage:
1509 return LLVMPrivateLinkage;
1510 case LLVMRustLinkage::ExternalWeakLinkage:
1511 return LLVMExternalWeakLinkage;
1512 case LLVMRustLinkage::CommonLinkage:
1513 return LLVMCommonLinkage;
1515 report_fatal_error("Invalid LLVMRustLinkage value!");
1518 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
1519 return toRust(LLVMGetLinkage(V));
1522 extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1523 LLVMRustLinkage RustLinkage) {
1524 LLVMSetLinkage(V, fromRust(RustLinkage));
1527 // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1528 // the common sizes (1, 8, 16, 32, 64, 128 bits)
1529 extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1531 auto C = unwrap<llvm::ConstantInt>(CV);
1532 if (C->getBitWidth() > 128) { return false; }
1535 AP = C->getValue().sextOrSelf(128);
1537 AP = C->getValue().zextOrSelf(128);
1539 *low = AP.getLoBits(64).getZExtValue();
1540 *high = AP.getHiBits(64).getZExtValue();
1544 enum class LLVMRustVisibility {
1550 static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1552 case LLVMDefaultVisibility:
1553 return LLVMRustVisibility::Default;
1554 case LLVMHiddenVisibility:
1555 return LLVMRustVisibility::Hidden;
1556 case LLVMProtectedVisibility:
1557 return LLVMRustVisibility::Protected;
1559 report_fatal_error("Invalid LLVMRustVisibility value!");
1562 static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1564 case LLVMRustVisibility::Default:
1565 return LLVMDefaultVisibility;
1566 case LLVMRustVisibility::Hidden:
1567 return LLVMHiddenVisibility;
1568 case LLVMRustVisibility::Protected:
1569 return LLVMProtectedVisibility;
1571 report_fatal_error("Invalid LLVMRustVisibility value!");
1574 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
1575 return toRust(LLVMGetVisibility(V));
1578 // Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1579 extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1580 LLVMTypeRef DestTy, bool isSigned) {
1581 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1584 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1585 LLVMRustVisibility RustVisibility) {
1586 LLVMSetVisibility(V, fromRust(RustVisibility));
1589 struct LLVMRustModuleBuffer {
1593 extern "C" LLVMRustModuleBuffer*
1594 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
1595 #if LLVM_VERSION_GE(10, 0)
1596 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
1598 auto Ret = llvm::make_unique<LLVMRustModuleBuffer>();
1601 raw_string_ostream OS(Ret->data);
1603 legacy::PassManager PM;
1604 PM.add(createBitcodeWriterPass(OS));
1608 return Ret.release();
1612 LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1616 extern "C" const void*
1617 LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1618 return Buffer->data.data();
1622 LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1623 return Buffer->data.length();
1627 LLVMRustModuleCost(LLVMModuleRef M) {
1628 auto f = unwrap(M)->functions();
1629 return std::distance(std::begin(f), std::end(f));
1632 // Vector reductions:
1633 extern "C" LLVMValueRef
1634 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1635 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1637 extern "C" LLVMValueRef
1638 LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1639 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1641 extern "C" LLVMValueRef
1642 LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1643 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1645 extern "C" LLVMValueRef
1646 LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1647 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1649 extern "C" LLVMValueRef
1650 LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1651 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1653 extern "C" LLVMValueRef
1654 LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1655 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1657 extern "C" LLVMValueRef
1658 LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1659 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1661 extern "C" LLVMValueRef
1662 LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1663 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1665 extern "C" LLVMValueRef
1666 LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1667 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1669 extern "C" LLVMValueRef
1670 LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1671 return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN));
1673 extern "C" LLVMValueRef
1674 LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
1675 return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN));
1678 extern "C" LLVMValueRef
1679 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1680 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1682 extern "C" LLVMValueRef
1683 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1684 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));