diff options
Diffstat (limited to 'compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp')
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 902 |
1 files changed, 439 insertions, 463 deletions
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 9f941637d8c..b8cef6a7e25 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1,28 +1,40 @@ #include "LLVMWrapper.h" + +#include "llvm-c/Analysis.h" +#include "llvm-c/Core.h" +#include "llvm-c/DebugInfo.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/Bitcode/BitcodeWriter.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DiagnosticHandler.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsARM.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" #include "llvm/IR/Value.h" -#include "llvm/Object/Archive.h" #include "llvm/Object/COFFImportFile.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Pass.h" #include "llvm/Remarks/RemarkFormat.h" #include "llvm/Remarks/RemarkSerializer.h" #include "llvm/Remarks/RemarkStreamer.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/JSON.h" #include "llvm/Support/ModRef.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/Timer.h" #include "llvm/Support/ToolOutputFile.h" - #include <iostream> // for raw `write` in the bad-alloc handler @@ -43,6 +55,10 @@ using namespace llvm; using namespace llvm::sys; using namespace llvm::object; +// This opcode is an LLVM detail that could hypothetically change (?), so +// verify that the hard-coded value in `dwarf_const.rs` still agrees with LLVM. +static_assert(dwarf::DW_OP_LLVM_fragment == 0x1000); + // LLVMAtomicOrdering is already an enum - don't create another // one. static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) { @@ -140,26 +156,14 @@ extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M, unwrap(M)->setTargetTriple(Triple::normalize(Triple)); } -extern "C" const char *LLVMRustPrintPassTimings(size_t *Len) { - std::string buf; - auto SS = raw_string_ostream(buf); - TimerGroup::printAll(SS); - SS.flush(); - *Len = buf.length(); - char *CStr = (char *)malloc(*Len); - memcpy(CStr, buf.c_str(), *Len); - return CStr; +extern "C" void LLVMRustPrintPassTimings(RustStringRef OutBuf) { + auto OS = RawRustStringOstream(OutBuf); + TimerGroup::printAll(OS); } -extern "C" const char *LLVMRustPrintStatistics(size_t *Len) { - std::string buf; - auto SS = raw_string_ostream(buf); - llvm::PrintStatistics(SS); - SS.flush(); - *Len = buf.length(); - char *CStr = (char *)malloc(*Len); - memcpy(CStr, buf.c_str(), *Len); - return CStr; +extern "C" void LLVMRustPrintStatistics(RustStringRef OutBuf) { + auto OS = RawRustStringOstream(OutBuf); + llvm::PrintStatistics(OS); } extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name, @@ -167,31 +171,28 @@ extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name, return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen))); } -enum class LLVMRustTailCallKind { - None, - Tail, - MustTail, - NoTail, +enum class LLVMRustVerifierFailureAction { + AbortProcessAction = 0, + PrintMessageAction = 1, + ReturnStatusAction = 2, }; -static CallInst::TailCallKind fromRust(LLVMRustTailCallKind Kind) { - switch (Kind) { - case LLVMRustTailCallKind::None: - return CallInst::TailCallKind::TCK_None; - case LLVMRustTailCallKind::Tail: - return CallInst::TailCallKind::TCK_Tail; - case LLVMRustTailCallKind::MustTail: - return CallInst::TailCallKind::TCK_MustTail; - case LLVMRustTailCallKind::NoTail: - return CallInst::TailCallKind::TCK_NoTail; - default: - report_fatal_error("bad CallInst::TailCallKind."); +static LLVMVerifierFailureAction +fromRust(LLVMRustVerifierFailureAction Action) { + switch (Action) { + case LLVMRustVerifierFailureAction::AbortProcessAction: + return LLVMAbortProcessAction; + case LLVMRustVerifierFailureAction::PrintMessageAction: + return LLVMPrintMessageAction; + case LLVMRustVerifierFailureAction::ReturnStatusAction: + return LLVMReturnStatusAction; } + report_fatal_error("Invalid LLVMVerifierFailureAction value!"); } -extern "C" void LLVMRustSetTailCallKind(LLVMValueRef Call, - LLVMRustTailCallKind TCK) { - unwrap<CallInst>(Call)->setTailCallKind(fromRust(TCK)); +extern "C" LLVMBool +LLVMRustVerifyFunction(LLVMValueRef Fn, LLVMRustVerifierFailureAction Action) { + return LLVMVerifyFunction(Fn, fromRust(Action)); } extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, @@ -228,94 +229,144 @@ extern "C" LLVMValueRef LLVMRustInsertPrivateGlobal(LLVMModuleRef M, GlobalValue::PrivateLinkage, nullptr)); } -static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { +// Must match the layout of `rustc_codegen_llvm::llvm::ffi::AttributeKind`. +enum class LLVMRustAttributeKind { + AlwaysInline = 0, + ByVal = 1, + Cold = 2, + InlineHint = 3, + MinSize = 4, + Naked = 5, + NoAlias = 6, + NoCapture = 7, + NoInline = 8, + NonNull = 9, + NoRedZone = 10, + NoReturn = 11, + NoUnwind = 12, + OptimizeForSize = 13, + ReadOnly = 14, + SExt = 15, + StructRet = 16, + UWTable = 17, + ZExt = 18, + InReg = 19, + SanitizeThread = 20, + SanitizeAddress = 21, + SanitizeMemory = 22, + NonLazyBind = 23, + OptimizeNone = 24, + ReadNone = 26, + SanitizeHWAddress = 28, + WillReturn = 29, + StackProtectReq = 30, + StackProtectStrong = 31, + StackProtect = 32, + NoUndef = 33, + SanitizeMemTag = 34, + NoCfCheck = 35, + ShadowCallStack = 36, + AllocSize = 37, + AllocatedPointer = 38, + AllocAlign = 39, + SanitizeSafeStack = 40, + FnRetThunkExtern = 41, + Writable = 42, + DeadOnUnwind = 43, +}; + +static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) { switch (Kind) { - case AlwaysInline: + case LLVMRustAttributeKind::AlwaysInline: return Attribute::AlwaysInline; - case ByVal: + case LLVMRustAttributeKind::ByVal: return Attribute::ByVal; - case Cold: + case LLVMRustAttributeKind::Cold: return Attribute::Cold; - case InlineHint: + case LLVMRustAttributeKind::InlineHint: return Attribute::InlineHint; - case MinSize: + case LLVMRustAttributeKind::MinSize: return Attribute::MinSize; - case Naked: + case LLVMRustAttributeKind::Naked: return Attribute::Naked; - case NoAlias: + case LLVMRustAttributeKind::NoAlias: return Attribute::NoAlias; - case NoCapture: + case LLVMRustAttributeKind::NoCapture: +#if LLVM_VERSION_GE(21, 0) + report_fatal_error("NoCapture doesn't exist in LLVM 21"); +#else return Attribute::NoCapture; - case NoCfCheck: +#endif + case LLVMRustAttributeKind::NoCfCheck: return Attribute::NoCfCheck; - case NoInline: + case LLVMRustAttributeKind::NoInline: return Attribute::NoInline; - case NonNull: + case LLVMRustAttributeKind::NonNull: return Attribute::NonNull; - case NoRedZone: + case LLVMRustAttributeKind::NoRedZone: return Attribute::NoRedZone; - case NoReturn: + case LLVMRustAttributeKind::NoReturn: return Attribute::NoReturn; - case NoUnwind: + case LLVMRustAttributeKind::NoUnwind: return Attribute::NoUnwind; - case OptimizeForSize: + case LLVMRustAttributeKind::OptimizeForSize: return Attribute::OptimizeForSize; - case ReadOnly: + case LLVMRustAttributeKind::ReadOnly: return Attribute::ReadOnly; - case SExt: + case LLVMRustAttributeKind::SExt: return Attribute::SExt; - case StructRet: + case LLVMRustAttributeKind::StructRet: return Attribute::StructRet; - case UWTable: + case LLVMRustAttributeKind::UWTable: return Attribute::UWTable; - case ZExt: + case LLVMRustAttributeKind::ZExt: return Attribute::ZExt; - case InReg: + case LLVMRustAttributeKind::InReg: return Attribute::InReg; - case SanitizeThread: + case LLVMRustAttributeKind::SanitizeThread: return Attribute::SanitizeThread; - case SanitizeAddress: + case LLVMRustAttributeKind::SanitizeAddress: return Attribute::SanitizeAddress; - case SanitizeMemory: + case LLVMRustAttributeKind::SanitizeMemory: return Attribute::SanitizeMemory; - case NonLazyBind: + case LLVMRustAttributeKind::NonLazyBind: return Attribute::NonLazyBind; - case OptimizeNone: + case LLVMRustAttributeKind::OptimizeNone: return Attribute::OptimizeNone; - case ReadNone: + case LLVMRustAttributeKind::ReadNone: return Attribute::ReadNone; - case SanitizeHWAddress: + case LLVMRustAttributeKind::SanitizeHWAddress: return Attribute::SanitizeHWAddress; - case WillReturn: + case LLVMRustAttributeKind::WillReturn: return Attribute::WillReturn; - case StackProtectReq: + case LLVMRustAttributeKind::StackProtectReq: return Attribute::StackProtectReq; - case StackProtectStrong: + case LLVMRustAttributeKind::StackProtectStrong: return Attribute::StackProtectStrong; - case StackProtect: + case LLVMRustAttributeKind::StackProtect: return Attribute::StackProtect; - case NoUndef: + case LLVMRustAttributeKind::NoUndef: return Attribute::NoUndef; - case SanitizeMemTag: + case LLVMRustAttributeKind::SanitizeMemTag: return Attribute::SanitizeMemTag; - case ShadowCallStack: + case LLVMRustAttributeKind::ShadowCallStack: return Attribute::ShadowCallStack; - case AllocSize: + case LLVMRustAttributeKind::AllocSize: return Attribute::AllocSize; - case AllocatedPointer: + case LLVMRustAttributeKind::AllocatedPointer: return Attribute::AllocatedPointer; - case AllocAlign: + case LLVMRustAttributeKind::AllocAlign: return Attribute::AllocAlign; - case SanitizeSafeStack: + case LLVMRustAttributeKind::SanitizeSafeStack: return Attribute::SafeStack; - case FnRetThunkExtern: + case LLVMRustAttributeKind::FnRetThunkExtern: return Attribute::FnRetThunkExtern; - case Writable: + case LLVMRustAttributeKind::Writable: return Attribute::Writable; - case DeadOnUnwind: + case LLVMRustAttributeKind::DeadOnUnwind: return Attribute::DeadOnUnwind; } - report_fatal_error("bad AttributeKind"); + report_fatal_error("bad LLVMRustAttributeKind"); } template <typename T> @@ -344,8 +395,25 @@ extern "C" void LLVMRustAddCallSiteAttributes(LLVMValueRef Instr, AddAttributes(Call, Index, Attrs, AttrsLen); } +extern "C" LLVMValueRef LLVMRustGetTerminator(LLVMBasicBlockRef BB) { + Instruction *ret = unwrap(BB)->getTerminator(); + return wrap(ret); +} + +extern "C" void LLVMRustEraseInstFromParent(LLVMValueRef Instr) { + if (auto I = dyn_cast<Instruction>(unwrap<Value>(Instr))) { + I->eraseFromParent(); + } +} + extern "C" LLVMAttributeRef -LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttribute RustAttr) { +LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) { +#if LLVM_VERSION_GE(21, 0) + // LLVM 21 replaced the NoCapture attribute with Captures(none). + if (RustAttr == LLVMRustAttributeKind::NoCapture) { + return wrap(Attribute::getWithCaptureInfo(*unwrap(C), CaptureInfo::none())); + } +#endif return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr))); } @@ -582,8 +650,6 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints, unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen))); } -typedef DIBuilder *LLVMRustDIBuilderRef; - template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) { return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr); } @@ -592,120 +658,67 @@ template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) { #define DIArray DINodeArray #define unwrapDI unwrapDIPtr -// These values **must** match debuginfo::DIFlags! They also *happen* -// to match LLVM, but that isn't required as we do giant sets of -// matching below. The value shouldn't be directly passed to LLVM. -enum class LLVMRustDIFlags : uint32_t { - FlagZero = 0, - FlagPrivate = 1, - FlagProtected = 2, - FlagPublic = 3, - FlagFwdDecl = (1 << 2), - FlagAppleBlock = (1 << 3), - FlagBlockByrefStruct = (1 << 4), - FlagVirtual = (1 << 5), - FlagArtificial = (1 << 6), - FlagExplicit = (1 << 7), - FlagPrototyped = (1 << 8), - FlagObjcClassComplete = (1 << 9), - FlagObjectPointer = (1 << 10), - FlagVector = (1 << 11), - FlagStaticMember = (1 << 12), - FlagLValueReference = (1 << 13), - FlagRValueReference = (1 << 14), - FlagExternalTypeRef = (1 << 15), - FlagIntroducedVirtual = (1 << 18), - FlagBitField = (1 << 19), - FlagNoReturn = (1 << 20), - // Do not add values that are not supported by the minimum LLVM - // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def -}; - -inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) { - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) & - static_cast<uint32_t>(B)); -} - -inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) { - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) | - static_cast<uint32_t>(B)); -} - -inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) { - return A = A | B; -} - -inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; } - -inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) { - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3); -} - -static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) { - DINode::DIFlags Result = DINode::DIFlags::FlagZero; - - switch (visibility(Flags)) { - case LLVMRustDIFlags::FlagPrivate: - Result |= DINode::DIFlags::FlagPrivate; - break; - case LLVMRustDIFlags::FlagProtected: - Result |= DINode::DIFlags::FlagProtected; - break; - case LLVMRustDIFlags::FlagPublic: - Result |= DINode::DIFlags::FlagPublic; - break; - default: - // The rest are handled below - break; +// Statically assert that `LLVMDIFlags` (C) and `DIFlags` (C++) have the same +// layout, at least for the flags we know about. This isn't guaranteed, but is +// likely to remain true, and as long as it is true it makes conversions easy. +#define ASSERT_DIFLAG_VALUE(FLAG, VALUE) \ + static_assert((LLVMDI##FLAG == (VALUE)) && (DINode::DIFlags::FLAG == (VALUE))) +ASSERT_DIFLAG_VALUE(FlagZero, 0); +ASSERT_DIFLAG_VALUE(FlagPrivate, 1); +ASSERT_DIFLAG_VALUE(FlagProtected, 2); +ASSERT_DIFLAG_VALUE(FlagPublic, 3); +// Bit (1 << 1) is part of the private/protected/public values above. +ASSERT_DIFLAG_VALUE(FlagFwdDecl, 1 << 2); +ASSERT_DIFLAG_VALUE(FlagAppleBlock, 1 << 3); +ASSERT_DIFLAG_VALUE(FlagReservedBit4, 1 << 4); +ASSERT_DIFLAG_VALUE(FlagVirtual, 1 << 5); +ASSERT_DIFLAG_VALUE(FlagArtificial, 1 << 6); +ASSERT_DIFLAG_VALUE(FlagExplicit, 1 << 7); +ASSERT_DIFLAG_VALUE(FlagPrototyped, 1 << 8); +ASSERT_DIFLAG_VALUE(FlagObjcClassComplete, 1 << 9); +ASSERT_DIFLAG_VALUE(FlagObjectPointer, 1 << 10); +ASSERT_DIFLAG_VALUE(FlagVector, 1 << 11); +ASSERT_DIFLAG_VALUE(FlagStaticMember, 1 << 12); +ASSERT_DIFLAG_VALUE(FlagLValueReference, 1 << 13); +ASSERT_DIFLAG_VALUE(FlagRValueReference, 1 << 14); +// Bit (1 << 15) has been recycled, but the C API value hasn't been renamed. +static_assert((LLVMDIFlagReserved == (1 << 15)) && + (DINode::DIFlags::FlagExportSymbols == (1 << 15))); +ASSERT_DIFLAG_VALUE(FlagSingleInheritance, 1 << 16); +ASSERT_DIFLAG_VALUE(FlagMultipleInheritance, 2 << 16); +ASSERT_DIFLAG_VALUE(FlagVirtualInheritance, 3 << 16); +// Bit (1 << 17) is part of the inheritance values above. +ASSERT_DIFLAG_VALUE(FlagIntroducedVirtual, 1 << 18); +ASSERT_DIFLAG_VALUE(FlagBitField, 1 << 19); +ASSERT_DIFLAG_VALUE(FlagNoReturn, 1 << 20); +// Bit (1 << 21) is unused, but was `LLVMDIFlagMainSubprogram`. +ASSERT_DIFLAG_VALUE(FlagTypePassByValue, 1 << 22); +ASSERT_DIFLAG_VALUE(FlagTypePassByReference, 1 << 23); +ASSERT_DIFLAG_VALUE(FlagEnumClass, 1 << 24); +ASSERT_DIFLAG_VALUE(FlagThunk, 1 << 25); +ASSERT_DIFLAG_VALUE(FlagNonTrivial, 1 << 26); +ASSERT_DIFLAG_VALUE(FlagBigEndian, 1 << 27); +ASSERT_DIFLAG_VALUE(FlagLittleEndian, 1 << 28); +ASSERT_DIFLAG_VALUE(FlagIndirectVirtualBase, (1 << 2) | (1 << 5)); +#undef ASSERT_DIFLAG_VALUE + +// There are two potential ways to convert `LLVMDIFlags` to `DIFlags`: +// - Check and copy every individual bit/subvalue from input to output. +// - Statically assert that both have the same layout, and cast. +// As long as the static assertions succeed, a cast is easier and faster. +// In the (hopefully) unlikely event that the assertions do fail someday, and +// LLVM doesn't expose its own conversion function, we'll have to switch over +// to copying each bit/subvalue. +static DINode::DIFlags fromRust(LLVMDIFlags Flags) { + // Check that all set bits are covered by the static assertions above. + const unsigned UNKNOWN_BITS = (1 << 31) | (1 << 30) | (1 << 29) | (1 << 21); + if (Flags & UNKNOWN_BITS) { + report_fatal_error("bad LLVMDIFlags"); } - if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) { - Result |= DINode::DIFlags::FlagFwdDecl; - } - if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) { - Result |= DINode::DIFlags::FlagAppleBlock; - } - if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) { - Result |= DINode::DIFlags::FlagVirtual; - } - if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) { - Result |= DINode::DIFlags::FlagArtificial; - } - if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) { - Result |= DINode::DIFlags::FlagExplicit; - } - if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) { - Result |= DINode::DIFlags::FlagPrototyped; - } - if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) { - Result |= DINode::DIFlags::FlagObjcClassComplete; - } - if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) { - Result |= DINode::DIFlags::FlagObjectPointer; - } - if (isSet(Flags & LLVMRustDIFlags::FlagVector)) { - Result |= DINode::DIFlags::FlagVector; - } - if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) { - Result |= DINode::DIFlags::FlagStaticMember; - } - if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) { - Result |= DINode::DIFlags::FlagLValueReference; - } - if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) { - Result |= DINode::DIFlags::FlagRValueReference; - } - if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) { - Result |= DINode::DIFlags::FlagIntroducedVirtual; - } - if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) { - Result |= DINode::DIFlags::FlagBitField; - } - if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) { - Result |= DINode::DIFlags::FlagNoReturn; - } - - return Result; + // As long as the static assertions are satisfied and no unknown bits are + // present, we can convert from `LLVMDIFlags` to `DIFlags` with a cast. + return static_cast<DINode::DIFlags>(Flags); } // These values **must** match debuginfo::DISPFlags! They also *happen* @@ -853,23 +866,101 @@ extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; } extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; } -extern "C" void LLVMRustAddModuleFlagU32(LLVMModuleRef M, - Module::ModFlagBehavior MergeBehavior, - const char *Name, uint32_t Value) { - unwrap(M)->addModuleFlag(MergeBehavior, Name, Value); +// FFI equivalent of LLVM's `llvm::Module::ModFlagBehavior`. +// Must match the layout of +// `rustc_codegen_llvm::llvm::ffi::ModuleFlagMergeBehavior`. +// +// There is a stable LLVM-C version of this enum (`LLVMModuleFlagBehavior`), +// but as of LLVM 19 it does not support all of the enum values in the unstable +// C++ API. +enum class LLVMRustModuleFlagMergeBehavior { + Error = 1, + Warning = 2, + Require = 3, + Override = 4, + Append = 5, + AppendUnique = 6, + Max = 7, + Min = 8, +}; + +static Module::ModFlagBehavior +fromRust(LLVMRustModuleFlagMergeBehavior Behavior) { + switch (Behavior) { + case LLVMRustModuleFlagMergeBehavior::Error: + return Module::ModFlagBehavior::Error; + case LLVMRustModuleFlagMergeBehavior::Warning: + return Module::ModFlagBehavior::Warning; + case LLVMRustModuleFlagMergeBehavior::Require: + return Module::ModFlagBehavior::Require; + case LLVMRustModuleFlagMergeBehavior::Override: + return Module::ModFlagBehavior::Override; + case LLVMRustModuleFlagMergeBehavior::Append: + return Module::ModFlagBehavior::Append; + case LLVMRustModuleFlagMergeBehavior::AppendUnique: + return Module::ModFlagBehavior::AppendUnique; + case LLVMRustModuleFlagMergeBehavior::Max: + return Module::ModFlagBehavior::Max; + case LLVMRustModuleFlagMergeBehavior::Min: + return Module::ModFlagBehavior::Min; + } + report_fatal_error("bad LLVMRustModuleFlagMergeBehavior"); +} + +extern "C" void +LLVMRustAddModuleFlagU32(LLVMModuleRef M, + LLVMRustModuleFlagMergeBehavior MergeBehavior, + const char *Name, size_t NameLen, uint32_t Value) { + unwrap(M)->addModuleFlag(fromRust(MergeBehavior), StringRef(Name, NameLen), + Value); } extern "C" void LLVMRustAddModuleFlagString( - LLVMModuleRef M, Module::ModFlagBehavior MergeBehavior, const char *Name, - const char *Value, size_t ValueLen) { + LLVMModuleRef M, LLVMRustModuleFlagMergeBehavior MergeBehavior, + const char *Name, size_t NameLen, const char *Value, size_t ValueLen) { unwrap(M)->addModuleFlag( - MergeBehavior, Name, + fromRust(MergeBehavior), StringRef(Name, NameLen), MDString::get(unwrap(M)->getContext(), StringRef(Value, ValueLen))); } -extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name, - size_t Len) { - return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr; +extern "C" LLVMValueRef LLVMRustGetLastInstruction(LLVMBasicBlockRef BB) { + auto Point = unwrap(BB)->rbegin(); + if (Point != unwrap(BB)->rend()) + return wrap(&*Point); + return nullptr; +} + +extern "C" void LLVMRustEraseInstUntilInclusive(LLVMBasicBlockRef bb, + LLVMValueRef I) { + auto &BB = *unwrap(bb); + auto &Inst = *unwrap<Instruction>(I); + auto It = BB.begin(); + while (&*It != &Inst) + ++It; + // Make sure we found the Instruction. + assert(It != BB.end()); + // Delete in rev order to ensure no dangling references. + while (It != BB.begin()) { + auto Prev = std::prev(It); + It->eraseFromParent(); + It = Prev; + } + It->eraseFromParent(); +} + +extern "C" bool LLVMRustHasMetadata(LLVMValueRef inst, unsigned kindID) { + if (auto *I = dyn_cast<Instruction>(unwrap<Value>(inst))) { + return I->hasMetadata(kindID); + } + return false; +} + +extern "C" LLVMMetadataRef LLVMRustDIGetInstMetadata(LLVMValueRef x) { + if (auto *I = dyn_cast<Instruction>(unwrap<Value>(x))) { + auto *MD = I->getDebugLoc().getAsMDNode(); + return wrap(MD); + } + return nullptr; } extern "C" void LLVMRustGlobalAddMetadata(LLVMValueRef Global, unsigned Kind, @@ -877,34 +968,30 @@ extern "C" void LLVMRustGlobalAddMetadata(LLVMValueRef Global, unsigned Kind, unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD)); } -extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) { - return new DIBuilder(*unwrap(M)); -} - -extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) { - delete Builder; +extern "C" LLVMDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) { + return wrap(new DIBuilder(*unwrap(M))); } -extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) { - Builder->finalize(); +extern "C" void LLVMRustDIBuilderDispose(LLVMDIBuilderRef Builder) { + delete unwrap(Builder); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit( - LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef, + LLVMDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef, const char *Producer, size_t ProducerLen, bool isOptimized, const char *Flags, unsigned RuntimeVer, const char *SplitName, size_t SplitNameLen, LLVMRustDebugEmissionKind Kind, uint64_t DWOId, bool SplitDebugInlining, LLVMRustDebugNameTableKind TableKind) { auto *File = unwrapDI<DIFile>(FileRef); - return wrap(Builder->createCompileUnit( + return wrap(unwrap(Builder)->createCompileUnit( Lang, File, StringRef(Producer, ProducerLen), isOptimized, Flags, RuntimeVer, StringRef(SplitName, SplitNameLen), fromRust(Kind), DWOId, SplitDebugInlining, false, fromRust(TableKind))); } extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename, +LLVMRustDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename, size_t FilenameLen, const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind, const char *Checksum, size_t ChecksumLen, @@ -917,29 +1004,29 @@ LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename, std::optional<StringRef> oSource{}; if (Source) oSource = StringRef(Source, SourceLen); - return wrap(Builder->createFile(StringRef(Filename, FilenameLen), - StringRef(Directory, DirectoryLen), CSInfo, - oSource)); + return wrap(unwrap(Builder)->createFile(StringRef(Filename, FilenameLen), + StringRef(Directory, DirectoryLen), + CSInfo, oSource)); } extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder, +LLVMRustDIBuilderCreateSubroutineType(LLVMDIBuilderRef Builder, LLVMMetadataRef ParameterTypes) { - return wrap(Builder->createSubroutineType( + return wrap(unwrap(Builder)->createSubroutineType( DITypeRefArray(unwrap<MDTuple>(ParameterTypes)))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, const char *LinkageName, size_t LinkageNameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, - unsigned ScopeLine, LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags, + unsigned ScopeLine, LLVMDIFlags Flags, LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam, LLVMMetadataRef Decl) { DITemplateParameterArray TParams = DITemplateParameterArray(unwrap<MDTuple>(TParam)); DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags); DINode::DIFlags llvmFlags = fromRust(Flags); - DISubprogram *Sub = Builder->createFunction( + DISubprogram *Sub = unwrap(Builder)->createFunction( unwrapDI<DIScope>(Scope), StringRef(Name, NameLen), StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo, unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags, llvmSPFlags, @@ -950,15 +1037,15 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, const char *LinkageName, size_t LinkageNameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, - LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) { + LLVMDIFlags Flags, LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) { DITemplateParameterArray TParams = DITemplateParameterArray(unwrap<MDTuple>(TParam)); DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags); DINode::DIFlags llvmFlags = fromRust(Flags); - DISubprogram *Sub = Builder->createMethod( + DISubprogram *Sub = unwrap(Builder)->createMethod( unwrapDI<DIScope>(Scope), StringRef(Name, NameLen), StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo, unwrapDI<DISubroutineType>(Ty), 0, 0, @@ -968,39 +1055,39 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod( } extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name, +LLVMRustDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name, size_t NameLen, uint64_t SizeInBits, unsigned Encoding) { - return wrap( - Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding)); + return wrap(unwrap(Builder)->createBasicType(StringRef(Name, NameLen), + SizeInBits, Encoding)); } extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateTypedef(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef Type, const char *Name, - size_t NameLen, LLVMMetadataRef File, - unsigned LineNo, LLVMMetadataRef Scope) { - return wrap(Builder->createTypedef( +LLVMRustDIBuilderCreateTypedef(LLVMDIBuilderRef Builder, LLVMMetadataRef Type, + const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNo, + LLVMMetadataRef Scope) { + return wrap(unwrap(Builder)->createTypedef( unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File), LineNo, unwrapDIPtr<DIScope>(Scope))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy, - uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace, - const char *Name, size_t NameLen) { - return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy), - SizeInBits, AlignInBits, AddressSpace, - StringRef(Name, NameLen))); + LLVMDIBuilderRef Builder, LLVMMetadataRef PointeeTy, uint64_t SizeInBits, + uint32_t AlignInBits, unsigned AddressSpace, const char *Name, + size_t NameLen) { + return wrap(unwrap(Builder)->createPointerType( + unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, AddressSpace, + StringRef(Name, NameLen))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, - uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags, LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements, unsigned RunTimeLang, LLVMMetadataRef VTableHolder, const char *UniqueId, size_t UniqueIdLen) { - return wrap(Builder->createStructType( + return wrap(unwrap(Builder)->createStructType( unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom), @@ -1009,12 +1096,12 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType( } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, - uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags, LLVMMetadataRef Discriminator, LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) { - return wrap(Builder->createVariantPart( + return wrap(unwrap(Builder)->createVariantPart( unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator), @@ -1023,57 +1110,50 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart( } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags, + uint32_t AlignInBits, uint64_t OffsetInBits, LLVMDIFlags Flags, LLVMMetadataRef Ty) { - return wrap(Builder->createMemberType( + return wrap(unwrap(Builder)->createMemberType( unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File), LineNo, SizeInBits, AlignInBits, OffsetInBits, fromRust(Flags), unwrapDI<DIType>(Ty))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant, - LLVMRustDIFlags Flags, LLVMMetadataRef Ty) { + LLVMDIFlags Flags, LLVMMetadataRef Ty) { llvm::ConstantInt *D = nullptr; if (Discriminant) { D = unwrap<llvm::ConstantInt>(Discriminant); } - return wrap(Builder->createVariantMemberType( + return wrap(unwrap(Builder)->createVariantMemberType( unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File), LineNo, SizeInBits, AlignInBits, OffsetInBits, D, fromRust(Flags), unwrapDI<DIType>(Ty))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticMemberType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, - LLVMRustDIFlags Flags, LLVMValueRef val, uint32_t AlignInBits) { - return wrap(Builder->createStaticMemberType( + LLVMDIFlags Flags, LLVMValueRef val, uint32_t AlignInBits) { + return wrap(unwrap(Builder)->createStaticMemberType( unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), fromRust(Flags), unwrap<llvm::ConstantInt>(val), llvm::dwarf::DW_TAG_member, AlignInBits)); } extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateLexicalBlock(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef Scope, LLVMMetadataRef File, - unsigned Line, unsigned Col) { - return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope), - unwrapDI<DIFile>(File), Line, Col)); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlockFile( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, LLVMMetadataRef File) { - return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope), - unwrapDI<DIFile>(File))); +LLVMRustDIBuilderCreateQualifiedType(LLVMDIBuilderRef Builder, unsigned Tag, + LLVMMetadataRef Type) { + return wrap( + unwrap(Builder)->createQualifiedType(Tag, unwrapDI<DIType>(Type))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name, + LLVMDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name, size_t NameLen, const char *LinkageName, size_t LinkageNameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V, LLVMMetadataRef Decl = nullptr, @@ -1082,16 +1162,16 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( llvm::DIExpression *InitExpr = nullptr; if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) { - InitExpr = Builder->createConstantValueExpression( + InitExpr = unwrap(Builder)->createConstantValueExpression( IntVal->getValue().getSExtValue()); } else if (llvm::ConstantFP *FPVal = llvm::dyn_cast<llvm::ConstantFP>(InitVal)) { - InitExpr = Builder->createConstantValueExpression( + InitExpr = unwrap(Builder)->createConstantValueExpression( FPVal->getValueAPF().bitcastToAPInt().getZExtValue()); } llvm::DIGlobalVariableExpression *VarExpr = - Builder->createGlobalVariableExpression( + unwrap(Builder)->createGlobalVariableExpression( unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen), StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit, @@ -1104,17 +1184,17 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable( - LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope, + LLVMDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo, - LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags, - unsigned ArgNo, uint32_t AlignInBits) { + LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMDIFlags Flags, unsigned ArgNo, + uint32_t AlignInBits) { if (Tag == 0x100) { // DW_TAG_auto_variable - return wrap(Builder->createAutoVariable( + return wrap(unwrap(Builder)->createAutoVariable( unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits)); } else { - return wrap(Builder->createParameterVariable( + return wrap(unwrap(Builder)->createParameterVariable( unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo, unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags))); @@ -1122,53 +1202,56 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable( } extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size, +LLVMRustDIBuilderCreateArrayType(LLVMDIBuilderRef Builder, uint64_t Size, uint32_t AlignInBits, LLVMMetadataRef Ty, LLVMMetadataRef Subscripts) { - return wrap( - Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty), - DINodeArray(unwrapDI<MDTuple>(Subscripts)))); + return wrap(unwrap(Builder)->createArrayType( + Size, AlignInBits, unwrapDI<DIType>(Ty), + DINodeArray(unwrapDI<MDTuple>(Subscripts)))); } extern "C" LLVMMetadataRef -LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo, +LLVMRustDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Builder, int64_t Lo, int64_t Count) { - return wrap(Builder->getOrCreateSubrange(Lo, Count)); + return wrap(unwrap(Builder)->getOrCreateSubrange(Lo, Count)); } extern "C" LLVMMetadataRef -LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder, +LLVMRustDIBuilderGetOrCreateArray(LLVMDIBuilderRef Builder, LLVMMetadataRef *Ptr, unsigned Count) { Metadata **DataValue = unwrap(Ptr); - return wrap( - Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get()); + return wrap(unwrap(Builder) + ->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)) + .get()); } -extern "C" void LLVMRustDIBuilderInsertDeclareAtEnd( - LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo, - uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL, - LLVMBasicBlockRef InsertAtEnd) { - Builder->insertDeclare(unwrap(V), unwrap<DILocalVariable>(VarInfo), - Builder->createExpression( - llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)), - DebugLoc(cast<MDNode>(unwrap(DL))), - unwrap(InsertAtEnd)); +extern "C" void +LLVMRustDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Builder, LLVMValueRef V, + LLVMMetadataRef VarInfo, uint64_t *AddrOps, + unsigned AddrOpsCount, LLVMMetadataRef DL, + LLVMBasicBlockRef InsertAtEnd) { + unwrap(Builder)->insertDeclare( + unwrap(V), unwrap<DILocalVariable>(VarInfo), + unwrap(Builder)->createExpression( + llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)), + DebugLoc(cast<MDNode>(unwrap(DL))), unwrap(InsertAtEnd)); } -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator( - LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen, - const uint64_t Value[2], unsigned SizeInBits, bool IsUnsigned) { - return wrap(Builder->createEnumerator( +extern "C" LLVMMetadataRef +LLVMRustDIBuilderCreateEnumerator(LLVMDIBuilderRef Builder, const char *Name, + size_t NameLen, const uint64_t Value[2], + unsigned SizeInBits, bool IsUnsigned) { + return wrap(unwrap(Builder)->createEnumerator( StringRef(Name, NameLen), APSInt(APInt(SizeInBits, ArrayRef<uint64_t>(Value, 2)), IsUnsigned))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef Elements, LLVMMetadataRef ClassTy, bool IsScoped) { - return wrap(Builder->createEnumerationType( + return wrap(unwrap(Builder)->createEnumerationType( unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)), unwrapDI<DIType>(ClassTy), @@ -1176,12 +1259,12 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType( } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, - uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags, LLVMMetadataRef Elements, unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) { - return wrap(Builder->createUnionType( + return wrap(unwrap(Builder)->createUnionType( unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits, fromRust(Flags), DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang, @@ -1189,50 +1272,28 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType( } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef Ty) { bool IsDefault = false; // FIXME: should we ever set this true? - return wrap(Builder->createTemplateTypeParameter( + return wrap(unwrap(Builder)->createTemplateTypeParameter( unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault)); } -extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef Scope, const char *Name, - size_t NameLen, bool ExportSymbols) { - return wrap(Builder->createNameSpace( - unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols)); -} - extern "C" void LLVMRustDICompositeTypeReplaceArrays( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef CompositeTy, + LLVMDIBuilderRef Builder, LLVMMetadataRef CompositeTy, LLVMMetadataRef Elements, LLVMMetadataRef Params) { DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy); - Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)), - DINodeArray(unwrap<MDTuple>(Params))); + unwrap(Builder)->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)), + DINodeArray(unwrap<MDTuple>(Params))); } extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column, - LLVMMetadataRef ScopeRef, - LLVMMetadataRef InlinedAt) { - MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef); - DILocation *Loc = DILocation::get(Scope->getContext(), Line, Column, Scope, - unwrapDIPtr<MDNode>(InlinedAt)); - return wrap(Loc); -} - -extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() { - return dwarf::DW_OP_deref; -} - -extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() { - return dwarf::DW_OP_plus_uconst; -} - -extern "C" int64_t LLVMRustDIBuilderCreateOpLLVMFragment() { - return dwarf::DW_OP_LLVM_fragment; +LLVMRustDILocationCloneWithBaseDiscriminator(LLVMMetadataRef Location, + unsigned BD) { + DILocation *Loc = unwrapDIPtr<DILocation>(Location); + auto NewLoc = Loc->cloneWithBaseDiscriminator(BD); + return wrap(NewLoc.has_value() ? NewLoc.value() : nullptr); } extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) { @@ -1445,7 +1506,7 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef) extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(LLVMDiagnosticInfoRef DI, - unsigned *Cookie) { + uint64_t *Cookie) { llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI)); *Cookie = SM->getLocCookie(); @@ -1484,8 +1545,8 @@ LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, RustStringRef MessageOut, const SourceMgr &LSM = *D.getSourceMgr(); const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); - LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), - LBuf->getBufferSize()); + auto BufferOS = RawRustStringOstream(BufferOut); + BufferOS << LBuf->getBuffer(); *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart(); @@ -1499,38 +1560,6 @@ LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, RustStringRef MessageOut, return true; } -extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name, - LLVMValueRef *Inputs, - unsigned NumInputs) { - return new OperandBundleDef(Name, - ArrayRef<Value *>(unwrap(Inputs), NumInputs)); -} - -extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) { - delete Bundle; -} - -// OpBundlesIndirect is an array of pointers (*not* a pointer to an array). -extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, - LLVMValueRef Fn, LLVMValueRef *Args, - unsigned NumArgs, - OperandBundleDef **OpBundlesIndirect, - unsigned NumOpBundles) { - Value *Callee = unwrap(Fn); - FunctionType *FTy = unwrap<FunctionType>(Ty); - - // FIXME: Is there a way around this? - SmallVector<OperandBundleDef> OpBundles; - OpBundles.reserve(NumOpBundles); - for (unsigned i = 0; i < NumOpBundles; ++i) { - OpBundles.push_back(*OpBundlesIndirect[i]); - } - - return wrap(unwrap(B)->CreateCall(FTy, Callee, - ArrayRef<Value *>(unwrap(Args), NumArgs), - ArrayRef<OperandBundleDef>(OpBundles))); -} - extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, @@ -1558,37 +1587,18 @@ extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst, MaybeAlign(DstAlign), IsVolatile)); } -// OpBundlesIndirect is an array of pointers (*not* a pointer to an array). -extern "C" LLVMValueRef -LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, - LLVMValueRef *Args, unsigned NumArgs, - LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, - OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles, - const char *Name) { - Value *Callee = unwrap(Fn); - FunctionType *FTy = unwrap<FunctionType>(Ty); - - // FIXME: Is there a way around this? - SmallVector<OperandBundleDef> OpBundles; - OpBundles.reserve(NumOpBundles); - for (unsigned i = 0; i < NumOpBundles; ++i) { - OpBundles.push_back(*OpBundlesIndirect[i]); - } - - return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch), - ArrayRef<Value *>(unwrap(Args), NumArgs), - ArrayRef<OperandBundleDef>(OpBundles), - Name)); -} +// Polyfill for `LLVMBuildCallBr`, which was added in LLVM 19. +// <https://github.com/llvm/llvm-project/commit/584253c4e2f788f870488fc32193b52d67ddaccc> +// FIXME: Remove when Rust's minimum supported LLVM version reaches 19. +#if LLVM_VERSION_LT(19, 0) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OperandBundleDef, LLVMOperandBundleRef) -// OpBundlesIndirect is an array of pointers (*not* a pointer to an array). extern "C" LLVMValueRef -LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, - LLVMBasicBlockRef DefaultDest, - LLVMBasicBlockRef *IndirectDests, unsigned NumIndirectDests, - LLVMValueRef *Args, unsigned NumArgs, - OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles, - const char *Name) { +LLVMBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, + LLVMBasicBlockRef DefaultDest, LLVMBasicBlockRef *IndirectDests, + unsigned NumIndirectDests, LLVMValueRef *Args, unsigned NumArgs, + LLVMOperandBundleRef *Bundles, unsigned NumBundles, + const char *Name) { Value *Callee = unwrap(Fn); FunctionType *FTy = unwrap<FunctionType>(Ty); @@ -1601,9 +1611,9 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, // FIXME: Is there a way around this? SmallVector<OperandBundleDef> OpBundles; - OpBundles.reserve(NumOpBundles); - for (unsigned i = 0; i < NumOpBundles; ++i) { - OpBundles.push_back(*OpBundlesIndirect[i]); + OpBundles.reserve(NumBundles); + for (unsigned i = 0; i < NumBundles; ++i) { + OpBundles.push_back(*unwrap(Bundles[i])); } return wrap( @@ -1612,6 +1622,7 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, ArrayRef<Value *>(unwrap(Args), NumArgs), ArrayRef<OperandBundleDef>(OpBundles), Name)); } +#endif extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, LLVMBasicBlockRef BB) { @@ -1756,56 +1767,6 @@ extern "C" LLVMValueRef LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS))); } -// This struct contains all necessary info about a symbol exported from a DLL. -struct LLVMRustCOFFShortExport { - const char *name; - bool ordinal_present; - // The value of `ordinal` is only meaningful if `ordinal_present` is true. - uint16_t ordinal; -}; - -// Machine must be a COFF machine type, as defined in PE specs. -extern "C" LLVMRustResult -LLVMRustWriteImportLibrary(const char *ImportName, const char *Path, - const LLVMRustCOFFShortExport *Exports, - size_t NumExports, uint16_t Machine, bool MinGW) { - std::vector<llvm::object::COFFShortExport> ConvertedExports; - ConvertedExports.reserve(NumExports); - - for (size_t i = 0; i < NumExports; ++i) { - bool ordinal_present = Exports[i].ordinal_present; - uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0; - ConvertedExports.push_back(llvm::object::COFFShortExport{ - Exports[i].name, // Name - std::string{}, // ExtName - std::string{}, // SymbolName - std::string{}, // AliasTarget -#if LLVM_VERSION_GE(19, 0) - std::string{}, // ExportAs -#endif - ordinal, // Ordinal - ordinal_present, // Noname - false, // Data - false, // Private - false // Constant - }); - } - - auto Error = llvm::object::writeImportLibrary( - ImportName, Path, ConvertedExports, - static_cast<llvm::COFF::MachineTypes>(Machine), MinGW); - if (Error) { - std::string errorString; - auto stream = llvm::raw_string_ostream(errorString); - stream << Error; - stream.flush(); - LLVMRustSetLastError(errorString.c_str()); - return LLVMRustResult::Failure; - } else { - return LLVMRustResult::Success; - } -} - // Transfers ownership of DiagnosticHandler unique_ptr to the caller. extern "C" DiagnosticHandler * LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) { @@ -1988,10 +1949,6 @@ extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) { return -1; } -extern "C" bool LLVMRustIsBitcode(char *ptr, size_t len) { - return identify_magic(StringRef(ptr, len)) == file_magic::bitcode; -} - extern "C" bool LLVMRustIsNonGVFunctionPointerTy(LLVMValueRef V) { if (unwrap<Value>(V)->getType()->isPointerTy()) { if (auto *GV = dyn_cast<GlobalValue>(unwrap<Value>(V))) { @@ -2011,6 +1968,25 @@ extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() { return llvm::compression::zstd::isAvailable(); } +extern "C" void LLVMRustSetNoSanitizeAddress(LLVMValueRef Global) { + GlobalValue &GV = *unwrap<GlobalValue>(Global); + GlobalValue::SanitizerMetadata MD; + if (GV.hasSanitizerMetadata()) + MD = GV.getSanitizerMetadata(); + MD.NoAddress = true; + MD.IsDynInit = false; + GV.setSanitizerMetadata(MD); +} + +extern "C" void LLVMRustSetNoSanitizeHWAddress(LLVMValueRef Global) { + GlobalValue &GV = *unwrap<GlobalValue>(Global); + GlobalValue::SanitizerMetadata MD; + if (GV.hasSanitizerMetadata()) + MD = GV.getSanitizerMetadata(); + MD.NoHWAddress = true; + GV.setSanitizerMetadata(MD); +} + // Operations on composite constants. // These are clones of LLVM api functions that will become available in future // releases. They can be removed once Rust's minimum supported LLVM version |
