diff options
Diffstat (limited to 'compiler/rustc_llvm/llvm-wrapper')
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp | 3 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp | 118 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h | 10 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 320 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 381 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp | 95 |
6 files changed, 597 insertions, 330 deletions
diff --git a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp index 448a1f62f69..35d6b9ed7a4 100644 --- a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp @@ -39,6 +39,7 @@ enum class LLVMRustArchiveKind { BSD, DARWIN, COFF, + AIX_BIG, }; static Archive::Kind fromRust(LLVMRustArchiveKind Kind) { @@ -51,6 +52,8 @@ static Archive::Kind fromRust(LLVMRustArchiveKind Kind) { return Archive::K_DARWIN; case LLVMRustArchiveKind::COFF: return Archive::K_COFF; + case LLVMRustArchiveKind::AIX_BIG: + return Archive::K_AIXBIG; default: report_fatal_error("Bad ArchiveKind."); } diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 7da6ab71309..87906dee4d3 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -8,18 +8,100 @@ using namespace llvm; +// FFI equivalent of enum `llvm::coverage::Counter::CounterKind` +// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L97-L99 +enum class LLVMRustCounterKind { + Zero = 0, + CounterValueReference = 1, + Expression = 2, +}; + +// FFI equivalent of struct `llvm::coverage::Counter` +// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L94-L149 +struct LLVMRustCounter { + LLVMRustCounterKind CounterKind; + uint32_t ID; +}; + +static coverage::Counter fromRust(LLVMRustCounter Counter) { + switch (Counter.CounterKind) { + case LLVMRustCounterKind::Zero: + return coverage::Counter::getZero(); + case LLVMRustCounterKind::CounterValueReference: + return coverage::Counter::getCounter(Counter.ID); + case LLVMRustCounterKind::Expression: + return coverage::Counter::getExpression(Counter.ID); + } + report_fatal_error("Bad LLVMRustCounterKind!"); +} + +// FFI equivalent of enum `llvm::coverage::CounterMappingRegion::RegionKind` +// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L213-L234 +enum class LLVMRustCounterMappingRegionKind { + CodeRegion = 0, + ExpansionRegion = 1, + SkippedRegion = 2, + GapRegion = 3, + BranchRegion = 4, +}; + +static coverage::CounterMappingRegion::RegionKind +fromRust(LLVMRustCounterMappingRegionKind Kind) { + switch (Kind) { + case LLVMRustCounterMappingRegionKind::CodeRegion: + return coverage::CounterMappingRegion::CodeRegion; + case LLVMRustCounterMappingRegionKind::ExpansionRegion: + return coverage::CounterMappingRegion::ExpansionRegion; + case LLVMRustCounterMappingRegionKind::SkippedRegion: + return coverage::CounterMappingRegion::SkippedRegion; + case LLVMRustCounterMappingRegionKind::GapRegion: + return coverage::CounterMappingRegion::GapRegion; + case LLVMRustCounterMappingRegionKind::BranchRegion: + return coverage::CounterMappingRegion::BranchRegion; + } + report_fatal_error("Bad LLVMRustCounterMappingRegionKind!"); +} + +// FFI equivalent of struct `llvm::coverage::CounterMappingRegion` +// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L211-L304 struct LLVMRustCounterMappingRegion { - coverage::Counter Count; - coverage::Counter FalseCount; + LLVMRustCounter Count; + LLVMRustCounter FalseCount; uint32_t FileID; uint32_t ExpandedFileID; uint32_t LineStart; uint32_t ColumnStart; uint32_t LineEnd; uint32_t ColumnEnd; - coverage::CounterMappingRegion::RegionKind Kind; + LLVMRustCounterMappingRegionKind Kind; +}; + +// FFI equivalent of enum `llvm::coverage::CounterExpression::ExprKind` +// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L154 +enum class LLVMRustCounterExprKind { + Subtract = 0, + Add = 1, }; +// FFI equivalent of struct `llvm::coverage::CounterExpression` +// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L151-L160 +struct LLVMRustCounterExpression { + LLVMRustCounterExprKind Kind; + LLVMRustCounter LHS; + LLVMRustCounter RHS; +}; + +static coverage::CounterExpression::ExprKind +fromRust(LLVMRustCounterExprKind Kind) { + switch (Kind) { + case LLVMRustCounterExprKind::Subtract: + return coverage::CounterExpression::Subtract; + case LLVMRustCounterExprKind::Add: + return coverage::CounterExpression::Add; + } + report_fatal_error("Bad LLVMRustCounterExprKind!"); +} + extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( const char* const Filenames[], size_t FilenamesLen, @@ -28,8 +110,8 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( for (size_t i = 0; i < FilenamesLen; i++) { FilenameRefs.push_back(std::string(Filenames[i])); } - auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter( - makeArrayRef(FilenameRefs)); + auto FilenamesWriter = + coverage::CoverageFilenamesSectionWriter(ArrayRef<std::string>(FilenameRefs)); RawRustStringOstream OS(BufferOut); FilenamesWriter.write(OS); } @@ -37,23 +119,35 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( extern "C" void LLVMRustCoverageWriteMappingToBuffer( const unsigned *VirtualFileMappingIDs, unsigned NumVirtualFileMappingIDs, - const coverage::CounterExpression *Expressions, + const LLVMRustCounterExpression *RustExpressions, unsigned NumExpressions, - LLVMRustCounterMappingRegion *RustMappingRegions, + const LLVMRustCounterMappingRegion *RustMappingRegions, unsigned NumMappingRegions, RustStringRef BufferOut) { // Convert from FFI representation to LLVM representation. SmallVector<coverage::CounterMappingRegion, 0> MappingRegions; MappingRegions.reserve(NumMappingRegions); - for (const auto &Region : makeArrayRef(RustMappingRegions, NumMappingRegions)) { + for (const auto &Region : ArrayRef<LLVMRustCounterMappingRegion>( + RustMappingRegions, NumMappingRegions)) { MappingRegions.emplace_back( - Region.Count, Region.FalseCount, Region.FileID, Region.ExpandedFileID, + fromRust(Region.Count), fromRust(Region.FalseCount), + Region.FileID, Region.ExpandedFileID, Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd, - Region.Kind); + fromRust(Region.Kind)); } + + std::vector<coverage::CounterExpression> Expressions; + Expressions.reserve(NumExpressions); + for (const auto &Expression : + ArrayRef<LLVMRustCounterExpression>(RustExpressions, NumExpressions)) { + Expressions.emplace_back(fromRust(Expression.Kind), + fromRust(Expression.LHS), + fromRust(Expression.RHS)); + } + auto CoverageMappingWriter = coverage::CoverageMappingWriter( - makeArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs), - makeArrayRef(Expressions, NumExpressions), + ArrayRef<unsigned>(VirtualFileMappingIDs, NumVirtualFileMappingIDs), + Expressions, MappingRegions); RawRustStringOstream OS(BufferOut); CoverageMappingWriter.write(OS); diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 015c1c52bef..af6f4d5eaf9 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -4,7 +4,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" #include "llvm/Analysis/Lint.h" #include "llvm/Analysis/Passes.h" #include "llvm/IR/IRBuilder.h" @@ -15,6 +14,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/JSON.h" #include "llvm/Support/Host.h" #include "llvm/Support/Memory.h" #include "llvm/Support/SourceMgr.h" @@ -44,6 +44,12 @@ #include "llvm/IR/IRPrintingPasses.h" #include "llvm/Linker/Linker.h" +#if LLVM_VERSION_GE(16, 0) +#include "llvm/TargetParser/Triple.h" +#else +#include "llvm/ADT/Triple.h" +#endif + extern "C" void LLVMRustSetLastError(const char *); enum class LLVMRustResult { Success, Failure }; @@ -76,7 +82,6 @@ enum LLVMRustAttribute { OptimizeNone = 24, ReturnsTwice = 25, ReadNone = 26, - InaccessibleMemOnly = 27, SanitizeHWAddress = 28, WillReturn = 29, StackProtectReq = 30, @@ -91,6 +96,7 @@ enum LLVMRustAttribute { AllocatedPointer = 38, AllocAlign = 39, #endif + SanitizeSafeStack = 40, }; typedef struct OpaqueRustString *RustStringRef; diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 18d37d95a83..c43a0272477 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -9,11 +9,11 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/InitializePasses.h" #include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Verifier.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Passes/PassBuilder.h" @@ -21,14 +21,11 @@ #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/Host.h" -#if LLVM_VERSION_LT(14, 0) -#include "llvm/Support/TargetRegistry.h" -#else -#include "llvm/MC/TargetRegistry.h" +#if LLVM_VERSION_GE(17, 0) +#include "llvm/Support/VirtualFileSystem.h" #endif +#include "llvm/Support/Host.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/FunctionImport.h" #include "llvm/Transforms/IPO/Internalize.h" @@ -37,7 +34,6 @@ #include "llvm/Transforms/Utils/FunctionImportUtils.h" #include "llvm/LTO/LTO.h" #include "llvm/Bitcode/BitcodeWriter.h" -#include "llvm-c/Transforms/PassManagerBuilder.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Instrumentation/AddressSanitizer.h" @@ -59,22 +55,6 @@ typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) -extern "C" void LLVMInitializePasses() { - PassRegistry &Registry = *PassRegistry::getPassRegistry(); - initializeCore(Registry); - initializeCodeGen(Registry); - initializeScalarOpts(Registry); - initializeVectorization(Registry); - initializeIPO(Registry); - initializeAnalysis(Registry); - initializeTransformUtils(Registry); - initializeInstCombine(Registry); -#if LLVM_VERSION_LT(16, 0) - initializeInstrumentation(Registry); -#endif - initializeTarget(Registry); -} - extern "C" void LLVMTimeTraceProfilerInitialize() { timeTraceProfilerInitialize( /* TimeTraceGranularity */ 0, @@ -166,6 +146,12 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { #define SUBTARGET_HEXAGON #endif +#ifdef LLVM_COMPONENT_LOONGARCH +#define SUBTARGET_LOONGARCH SUBTARGET(LoongArch) +#else +#define SUBTARGET_LOONGARCH +#endif + #define GEN_SUBTARGETS \ SUBTARGET_X86 \ SUBTARGET_ARM \ @@ -179,6 +165,7 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { SUBTARGET_SPARC \ SUBTARGET_HEXAGON \ SUBTARGET_RISCV \ + SUBTARGET_LOONGARCH \ #define SUBTARGET(x) \ namespace llvm { \ @@ -205,7 +192,12 @@ enum class LLVMRustCodeModel { None, }; -static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) { +#if LLVM_VERSION_LT(16, 0) +static Optional<CodeModel::Model> +#else +static std::optional<CodeModel::Model> +#endif +fromRust(LLVMRustCodeModel Model) { switch (Model) { case LLVMRustCodeModel::Tiny: return CodeModel::Tiny; @@ -218,7 +210,11 @@ static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) { case LLVMRustCodeModel::Large: return CodeModel::Large; case LLVMRustCodeModel::None: +#if LLVM_VERSION_LT(16, 0) return None; +#else + return std::nullopt; +#endif default: report_fatal_error("Bad CodeModel."); } @@ -255,10 +251,6 @@ enum class LLVMRustPassBuilderOptLevel { Oz, }; -#if LLVM_VERSION_LT(14,0) -using OptimizationLevel = PassBuilder::OptimizationLevel; -#endif - static OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) { switch (Level) { case LLVMRustPassBuilderOptLevel::O0: @@ -305,7 +297,6 @@ static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) { report_fatal_error("Bad RelocModel."); } -#ifdef LLVM_RUSTLLVM /// getLongestEntryLength - Return the length of the longest entry in the table. template<typename KV> static size_t getLongestEntryLength(ArrayRef<KV> Table) { @@ -315,54 +306,68 @@ static size_t getLongestEntryLength(ArrayRef<KV> Table) { return MaxLen; } -extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) { +extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM, const char* TargetCPU) { const TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); - const Triple::ArchType HostArch = Triple(sys::getProcessTriple()).getArch(); + const Triple::ArchType HostArch = Triple(sys::getDefaultTargetTriple()).getArch(); const Triple::ArchType TargetArch = Target->getTargetTriple().getArch(); + +#if LLVM_VERSION_GE(17, 0) + const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getAllProcessorDescriptions(); +#elif defined(LLVM_RUSTLLVM) const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getCPUTable(); +#else + printf("Full target CPU help is not supported by this LLVM version.\n\n"); + SubtargetSubTypeKV TargetCPUKV = { TargetCPU, {{}}, {{}} }; + const ArrayRef<SubtargetSubTypeKV> CPUTable = TargetCPUKV; +#endif unsigned MaxCPULen = getLongestEntryLength(CPUTable); printf("Available CPUs for this target:\n"); + // Don't print the "native" entry when the user specifies --target with a + // different arch since that could be wrong or misleading. if (HostArch == TargetArch) { + MaxCPULen = std::max(MaxCPULen, (unsigned) std::strlen("native")); const StringRef HostCPU = sys::getHostCPUName(); printf(" %-*s - Select the CPU of the current host (currently %.*s).\n", MaxCPULen, "native", (int)HostCPU.size(), HostCPU.data()); } - for (auto &CPU : CPUTable) - printf(" %-*s\n", MaxCPULen, CPU.Key); - printf("\n"); + for (auto &CPU : CPUTable) { + // Compare cpu against current target to label the default + if (strcmp(CPU.Key, TargetCPU) == 0) { + printf(" %-*s - This is the default target CPU" + " for the current build target (currently %s).", + MaxCPULen, CPU.Key, Target->getTargetTriple().str().c_str()); + } + else { + printf(" %-*s", MaxCPULen, CPU.Key); + } + printf("\n"); + } } extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) { +#ifdef LLVM_RUSTLLVM const TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable(); return FeatTable.size(); +#else + return 0; +#endif } extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index, const char** Feature, const char** Desc) { +#ifdef LLVM_RUSTLLVM const TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable(); const SubtargetFeatureKV Feat = FeatTable[Index]; *Feature = Feat.Key; *Desc = Feat.Desc; -} - -#else - -extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) { - printf("Target CPU help is not supported by this LLVM version.\n\n"); -} - -extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef) { - return 0; -} - -extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef, const char**, const char**) {} #endif +} extern "C" const char* LLVMRustGetHostCPUName(size_t *len) { StringRef Name = sys::getHostCPUName(); @@ -383,7 +388,8 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray, - const char *SplitDwarfFile) { + const char *SplitDwarfFile, + bool ForceEmulatedTls) { auto OptLevel = fromRust(RustOptLevel); auto RM = fromRust(RustReloc); @@ -416,6 +422,15 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( Options.RelaxELFRelocations = RelaxELFRelocations; Options.UseInitArray = UseInitArray; +#if LLVM_VERSION_LT(17, 0) + if (ForceEmulatedTls) { + Options.ExplicitEmulatedTLS = true; + Options.EmulatedTLS = true; + } +#else + Options.EmulatedTLS = ForceEmulatedTls || Trip.hasDefaultEmulatedTLS(); +#endif + if (TrapUnreachable) { // Tell LLVM to codegen `unreachable` into an explicit trap instruction. // This limits the extent of possible undefined behavior in some cases, as @@ -452,7 +467,7 @@ extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M, extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) { // Initializing the command-line options more than once is not allowed. So, - // check if they've already been initialized. (This could happen if we're + // check if they've already been initialized. (This could happen if we're // being called from rustpkg, for example). If the arguments change, then // that's just kinda unfortunate. static bool Initialized = false; @@ -526,14 +541,14 @@ extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmS extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) { - if (any_isa<const Module *>(WrappedIr)) - return any_cast<const Module *>(WrappedIr)->getName().str(); - if (any_isa<const Function *>(WrappedIr)) - return any_cast<const Function *>(WrappedIr)->getName().str(); - if (any_isa<const Loop *>(WrappedIr)) - return any_cast<const Loop *>(WrappedIr)->getName().str(); - if (any_isa<const LazyCallGraph::SCC *>(WrappedIr)) - return any_cast<const LazyCallGraph::SCC *>(WrappedIr)->getName(); + if (const auto *Cast = any_cast<const Module *>(&WrappedIr)) + return (*Cast)->getName().str(); + if (const auto *Cast = any_cast<const Function *>(&WrappedIr)) + return (*Cast)->getName().str(); + if (const auto *Cast = any_cast<const Loop *>(&WrappedIr)) + return (*Cast)->getName().str(); + if (const auto *Cast = any_cast<const LazyCallGraph::SCC *>(&WrappedIr)) + return (*Cast)->getName(); return "<UNKNOWN>"; } @@ -590,6 +605,8 @@ struct LLVMRustSanitizerOptions { bool SanitizeThread; bool SanitizeHWAddress; bool SanitizeHWAddressRecover; + bool SanitizeKernelAddress; + bool SanitizeKernelAddressRecover; }; extern "C" LLVMRustResult @@ -627,28 +644,55 @@ LLVMRustOptimize( bool DebugPassManager = false; PassInstrumentationCallbacks PIC; +#if LLVM_VERSION_LT(16, 0) StandardInstrumentations SI(DebugPassManager); +#else + StandardInstrumentations SI(TheModule->getContext(), DebugPassManager); +#endif SI.registerCallbacks(PIC); if (LlvmSelfProfiler){ LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback); } +#if LLVM_VERSION_LT(16, 0) Optional<PGOOptions> PGOOpt; +#else + std::optional<PGOOptions> PGOOpt; +#endif +#if LLVM_VERSION_GE(17, 0) + auto FS = vfs::getRealFileSystem(); +#endif if (PGOGenPath) { assert(!PGOUsePath && !PGOSampleUsePath); - PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr, - PGOOptions::NoCSAction, DebugInfoForProfiling); + PGOOpt = PGOOptions(PGOGenPath, "", "", +#if LLVM_VERSION_GE(17, 0) + FS, +#endif + PGOOptions::IRInstr, PGOOptions::NoCSAction, + DebugInfoForProfiling); } else if (PGOUsePath) { assert(!PGOSampleUsePath); - PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse, - PGOOptions::NoCSAction, DebugInfoForProfiling); + PGOOpt = PGOOptions(PGOUsePath, "", "", +#if LLVM_VERSION_GE(17, 0) + FS, +#endif + PGOOptions::IRUse, PGOOptions::NoCSAction, + DebugInfoForProfiling); } else if (PGOSampleUsePath) { - PGOOpt = PGOOptions(PGOSampleUsePath, "", "", PGOOptions::SampleUse, - PGOOptions::NoCSAction, DebugInfoForProfiling); + PGOOpt = PGOOptions(PGOSampleUsePath, "", "", +#if LLVM_VERSION_GE(17, 0) + FS, +#endif + PGOOptions::SampleUse, PGOOptions::NoCSAction, + DebugInfoForProfiling); } else if (DebugInfoForProfiling) { - PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction, - PGOOptions::NoCSAction, DebugInfoForProfiling); + PGOOpt = PGOOptions("", "", "", +#if LLVM_VERSION_GE(17, 0) + FS, +#endif + PGOOptions::NoAction, PGOOptions::NoCSAction, + DebugInfoForProfiling); } PassBuilder PB(TM, PTO, PGOOpt, &PIC); @@ -701,6 +745,9 @@ LLVMRustOptimize( if (InstrProfileOutput) { Options.InstrProfileOutput = InstrProfileOutput; } + // cargo run tests in multhreading mode by default + // so use atomics for coverage counters + Options.Atomic = true; MPM.addPass(InstrProfiling(Options, false)); } ); @@ -708,28 +755,19 @@ LLVMRustOptimize( if (SanitizerOptions) { if (SanitizerOptions->SanitizeMemory) { -#if LLVM_VERSION_GE(14, 0) MemorySanitizerOptions Options( SanitizerOptions->SanitizeMemoryTrackOrigins, SanitizerOptions->SanitizeMemoryRecover, /*CompileKernel=*/false, /*EagerChecks=*/true); -#else - MemorySanitizerOptions Options( - SanitizerOptions->SanitizeMemoryTrackOrigins, - SanitizerOptions->SanitizeMemoryRecover, - /*CompileKernel=*/false); -#endif OptimizerLastEPCallbacks.push_back( [Options](ModulePassManager &MPM, OptimizationLevel Level) { -#if LLVM_VERSION_GE(14, 0) && LLVM_VERSION_LT(16, 0) +#if LLVM_VERSION_LT(16, 0) MPM.addPass(ModuleMemorySanitizerPass(Options)); + MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options))); #else MPM.addPass(MemorySanitizerPass(Options)); #endif -#if LLVM_VERSION_LT(16, 0) - MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options))); -#endif } ); } @@ -737,26 +775,23 @@ LLVMRustOptimize( if (SanitizerOptions->SanitizeThread) { OptimizerLastEPCallbacks.push_back( [](ModulePassManager &MPM, OptimizationLevel Level) { -#if LLVM_VERSION_GE(14, 0) MPM.addPass(ModuleThreadSanitizerPass()); -#else - MPM.addPass(ThreadSanitizerPass()); -#endif MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); } ); } - if (SanitizerOptions->SanitizeAddress) { + if (SanitizerOptions->SanitizeAddress || SanitizerOptions->SanitizeKernelAddress) { OptimizerLastEPCallbacks.push_back( [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { + auto CompileKernel = SanitizerOptions->SanitizeKernelAddress; #if LLVM_VERSION_LT(15, 0) MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>()); #endif -#if LLVM_VERSION_GE(14, 0) AddressSanitizerOptions opts = AddressSanitizerOptions{ - /*CompileKernel=*/false, - SanitizerOptions->SanitizeAddressRecover, + CompileKernel, + SanitizerOptions->SanitizeAddressRecover + || SanitizerOptions->SanitizeKernelAddressRecover, /*UseAfterScope=*/true, AsanDetectStackUseAfterReturnMode::Runtime, }; @@ -765,28 +800,16 @@ LLVMRustOptimize( #else MPM.addPass(AddressSanitizerPass(opts)); #endif -#else - MPM.addPass(ModuleAddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); - MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover, - /*UseAfterScope=*/true))); -#endif } ); } if (SanitizerOptions->SanitizeHWAddress) { OptimizerLastEPCallbacks.push_back( [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { -#if LLVM_VERSION_GE(14, 0) HWAddressSanitizerOptions opts( /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover, /*DisableOptimization=*/false); MPM.addPass(HWAddressSanitizerPass(opts)); -#else - MPM.addPass(HWAddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover)); -#endif } ); } @@ -800,7 +823,7 @@ LLVMRustOptimize( auto Plugin = PassPlugin::Load(PluginPath.str()); if (!Plugin) { LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str()); - continue; + return LLVMRustResult::Failure; } Plugin->registerPassBuilderCallbacks(PB); } @@ -809,7 +832,7 @@ LLVMRustOptimize( ModulePassManager MPM; bool NeedThinLTOBufferPasses = UseThinLTOBuffers; if (!NoPrepopulatePasses) { - // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead. + // The pre-link pipelines don't support O0 and require using buildO0DefaultPipeline() instead. // At the same time, the LTO pipelines do support O0 and using them is required. bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO; if (OptLevel == OptimizationLevel::O0 && !IsLTO) { @@ -995,23 +1018,8 @@ LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) { } extern "C" void LLVMRustPrintPasses() { - LLVMInitializePasses(); - struct MyListener : PassRegistrationListener { - void passEnumerate(const PassInfo *Info) { - StringRef PassArg = Info->getPassArgument(); - StringRef PassName = Info->getPassName(); - if (!PassArg.empty()) { - // These unsigned->signed casts could theoretically overflow, but - // realistically never will (and even if, the result is implementation - // defined rather plain UB). - printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(), - (int)PassName.size(), PassName.data()); - } - } - } Listener; - - PassRegistry *PR = PassRegistry::getPassRegistry(); - PR->enumerateWith(&Listener); + PassBuilder PB; + PB.printPassNames(outs()); } extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, @@ -1183,13 +1191,6 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, // Otherwise, we sometimes lose `static` values -- see #60184. computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols, deadIsPrevailing, /* ImportEnabled = */ false); - ComputeCrossModuleImport( - Ret->Index, - Ret->ModuleToDefinedGVSummaries, - Ret->ImportLists, - Ret->ExportLists - ); - // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it // impacts the caching. // @@ -1206,6 +1207,16 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, return true; return Prevailing->second == S; }; + ComputeCrossModuleImport( + Ret->Index, + Ret->ModuleToDefinedGVSummaries, +#if LLVM_VERSION_GE(17, 0) + isPrevailing, +#endif + Ret->ImportLists, + Ret->ExportLists + ); + auto recordNewLinkage = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID, GlobalValue::LinkageTypes NewLinkage) { @@ -1289,11 +1300,7 @@ extern "C" bool LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { Module &Mod = *unwrap(M); const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); -#if LLVM_VERSION_GE(14, 0) thinLTOFinalizeInModule(Mod, DefinedGlobals, /*PropagateAttrs=*/true); -#else - thinLTOResolvePrevailingInModule(Mod, DefinedGlobals); -#endif return true; } @@ -1411,7 +1418,7 @@ LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) { } // This is what we used to parse upstream bitcode for actual ThinLTO -// processing. We'll call this once per module optimized through ThinLTO, and +// processing. We'll call this once per module optimized through ThinLTO, and // it'll be called concurrently on many threads. extern "C" LLVMModuleRef LLVMRustParseBitcodeForLTO(LLVMContextRef Context, @@ -1456,63 +1463,6 @@ LLVMRustGetBitcodeSliceFromObjectData(const char *data, return BitcodeOrError->getBufferStart(); } -// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See -// the comment in `back/lto.rs` for why this exists. -extern "C" void -LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod, - DICompileUnit **A, - DICompileUnit **B) { - Module *M = unwrap(Mod); - DICompileUnit **Cur = A; - DICompileUnit **Next = B; - for (DICompileUnit *CU : M->debug_compile_units()) { - *Cur = CU; - Cur = Next; - Next = nullptr; - if (Cur == nullptr) - break; - } -} - -// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See -// the comment in `back/lto.rs` for why this exists. -extern "C" void -LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { - Module *M = unwrap(Mod); - - // If the original source module didn't have a `DICompileUnit` then try to - // merge all the existing compile units. If there aren't actually any though - // then there's not much for us to do so return. - if (Unit == nullptr) { - for (DICompileUnit *CU : M->debug_compile_units()) { - Unit = CU; - break; - } - if (Unit == nullptr) - return; - } - - // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and - // process it recursively. Note that we used to specifically iterate over - // instructions to ensure we feed everything into it, but `processModule` - // started doing this the same way in LLVM 7 (commit d769eb36ab2b8). - DebugInfoFinder Finder; - Finder.processModule(*M); - - // After we've found all our debuginfo, rewrite all subprograms to point to - // the same `DICompileUnit`. - for (auto &F : Finder.subprograms()) { - F->replaceUnit(Unit); - } - - // Erase any other references to other `DICompileUnit` instances, the verifier - // will later ensure that we don't actually have any other stale references to - // worry about. - auto *MD = M->getNamedMetadata("llvm.dbg.cu"); - MD->clearOperands(); - MD->addOperand(Unit); -} - // Computes the LTO cache key for the provided 'ModId' in the given 'Data', // storing the result in 'KeyOut'. // Currently, this cache key is a SHA-1 hash of anything that could affect diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 6f36281af23..ab5fa961b95 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -7,14 +7,24 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsARM.h" +#include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/IR/Mangler.h" +#include "llvm/Remarks/RemarkStreamer.h" +#include "llvm/Remarks/RemarkSerializer.h" +#include "llvm/Remarks/RemarkFormat.h" +#include "llvm/Support/ToolOutputFile.h" +#if LLVM_VERSION_GE(16, 0) +#include "llvm/Support/ModRef.h" +#endif #include "llvm/Object/Archive.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Pass.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Support/Signals.h" +#if LLVM_VERSION_LT(16, 0) #include "llvm/ADT/Optional.h" +#endif #include <iostream> @@ -58,11 +68,7 @@ static LLVM_THREAD_LOCAL char *LastError; // // Notably it exits the process with code 101, unlike LLVM's default of 1. static void FatalErrorHandler(void *UserData, -#if LLVM_VERSION_LT(14, 0) - const std::string& Reason, -#else const char* Reason, -#endif bool GenCrashDiag) { // Do the same thing that the default error handler does. std::cerr << "LLVM ERROR: " << Reason << std::endl; @@ -115,6 +121,32 @@ extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name, return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen))); } +enum class LLVMRustTailCallKind { + None, + Tail, + MustTail, + NoTail, +}; + +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."); + } +} + +extern "C" void LLVMRustSetTailCallKind(LLVMValueRef Call, LLVMRustTailCallKind TCK) { + unwrap<CallInst>(Call)->setTailCallKind(fromRust(TCK)); +} + extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, const char *Name, size_t NameLen, @@ -151,10 +183,6 @@ LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) { nullptr)); } -extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) { - return wrap(Type::getMetadataTy(*unwrap(C))); -} - static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { switch (Kind) { case AlwaysInline: @@ -213,8 +241,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::ReturnsTwice; case ReadNone: return Attribute::ReadNone; - case InaccessibleMemOnly: - return Attribute::InaccessibleMemOnly; case SanitizeHWAddress: return Attribute::SanitizeHWAddress; case WillReturn: @@ -239,6 +265,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { case AllocAlign: return Attribute::AllocAlign; #endif + case SanitizeSafeStack: + return Attribute::SafeStack; } report_fatal_error("bad AttributeKind"); } @@ -246,18 +274,10 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { template<typename T> static inline void AddAttributes(T *t, unsigned Index, LLVMAttributeRef *Attrs, size_t AttrsLen) { AttributeList PAL = t->getAttributes(); - AttributeList PALNew; -#if LLVM_VERSION_LT(14, 0) - AttrBuilder B; - for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen)) - B.addAttribute(unwrap(Attr)); - PALNew = PAL.addAttributes(t->getContext(), Index, B); -#else AttrBuilder B(t->getContext()); - for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen)) + for (LLVMAttributeRef Attr : ArrayRef<LLVMAttributeRef>(Attrs, AttrsLen)) B.addAttribute(unwrap(Attr)); - PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B); -#endif + AttributeList PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B); t->setAttributes(PALNew); } @@ -319,7 +339,13 @@ extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Asy } extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) { - return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, None)); + return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, +#if LLVM_VERSION_LT(16, 0) + None +#else + std::nullopt +#endif + )); } #if LLVM_VERSION_GE(15, 0) @@ -379,6 +405,43 @@ extern "C" LLVMAttributeRef LLVMRustCreateAllocKindAttr(LLVMContextRef C, uint64 #endif } +// Simplified representation of `MemoryEffects` across the FFI boundary. +// +// Each variant corresponds to one of the static factory methods on `MemoryEffects`. +enum class LLVMRustMemoryEffects { + None, + ReadOnly, + InaccessibleMemOnly, +}; + +extern "C" LLVMAttributeRef LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C, + LLVMRustMemoryEffects Effects) { +#if LLVM_VERSION_GE(16, 0) + switch (Effects) { + case LLVMRustMemoryEffects::None: + return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::none())); + case LLVMRustMemoryEffects::ReadOnly: + return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::readOnly())); + case LLVMRustMemoryEffects::InaccessibleMemOnly: + return wrap(Attribute::getWithMemoryEffects(*unwrap(C), + MemoryEffects::inaccessibleMemOnly())); + default: + report_fatal_error("bad MemoryEffects."); + } +#else + switch (Effects) { + case LLVMRustMemoryEffects::None: + return wrap(Attribute::get(*unwrap(C), Attribute::ReadNone)); + case LLVMRustMemoryEffects::ReadOnly: + return wrap(Attribute::get(*unwrap(C), Attribute::ReadOnly)); + case LLVMRustMemoryEffects::InaccessibleMemOnly: + return wrap(Attribute::get(*unwrap(C), Attribute::InaccessibleMemOnly)); + default: + report_fatal_error("bad MemoryEffects."); + } +#endif +} + // Enable a fast-math flag // // https://llvm.org/docs/LangRef.html#fast-math-flags @@ -446,11 +509,6 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints, #endif } -extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm, - size_t AsmLen) { - unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen)); -} - typedef DIBuilder *LLVMRustDIBuilderRef; template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) { @@ -648,6 +706,7 @@ enum class LLVMRustDebugEmissionKind { NoDebug, FullDebug, LineTablesOnly, + DebugDirectivesOnly, }; static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) { @@ -658,6 +717,8 @@ static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) return DICompileUnit::DebugEmissionKind::FullDebug; case LLVMRustDebugEmissionKind::LineTablesOnly: return DICompileUnit::DebugEmissionKind::LineTablesOnly; + case LLVMRustDebugEmissionKind::DebugDirectivesOnly: + return DICompileUnit::DebugEmissionKind::DebugDirectivesOnly; default: report_fatal_error("bad DebugEmissionKind."); } @@ -670,10 +731,18 @@ enum class LLVMRustChecksumKind { SHA256, }; +#if LLVM_VERSION_LT(16, 0) static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) { +#else +static std::optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) { +#endif switch (Kind) { case LLVMRustChecksumKind::None: +#if LLVM_VERSION_LT(16, 0) return None; +#else + return std::nullopt; +#endif case LLVMRustChecksumKind::MD5: return DIFile::ChecksumKind::CSK_MD5; case LLVMRustChecksumKind::SHA1: @@ -708,10 +777,6 @@ extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name, return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr; } -extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) { - return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD))); -} - extern "C" void LLVMRustGlobalAddMetadata( LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) { unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD)); @@ -749,8 +814,18 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile( const char *Filename, size_t FilenameLen, const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind, const char *Checksum, size_t ChecksumLen) { + +#if LLVM_VERSION_LT(16, 0) Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind); +#else + std::optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind); +#endif + +#if LLVM_VERSION_LT(16, 0) Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{}; +#else + std::optional<DIFile::ChecksumInfo<StringRef>> CSInfo{}; +#endif if (llvmCSKind) CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen}); return wrap(Builder->createFile(StringRef(Filename, FilenameLen), @@ -789,6 +864,28 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( return wrap(Sub); } +extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod( + LLVMRustDIBuilderRef 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) { + DITemplateParameterArray TParams = + DITemplateParameterArray(unwrap<MDTuple>(TParam)); + DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags); + DINode::DIFlags llvmFlags = fromRust(Flags); + DISubprogram *Sub = Builder->createMethod( + unwrapDI<DIScope>(Scope), + StringRef(Name, NameLen), + StringRef(LinkageName, LinkageNameLen), + unwrapDI<DIFile>(File), LineNo, + unwrapDI<DISubroutineType>(Ty), + 0, 0, nullptr, // VTable params aren't used + llvmFlags, llvmSPFlags, TParams); + return wrap(Sub); +} + extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType( LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen, uint64_t SizeInBits, unsigned Encoding) { @@ -998,8 +1095,9 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator( LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen, - int64_t Value, bool IsUnsigned) { - return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned)); + const uint64_t Value[2], unsigned SizeInBits, bool IsUnsigned) { + return wrap(Builder->createEnumerator(StringRef(Name, NameLen), + APSInt(APInt(SizeInBits, ArrayRef<uint64_t>(Value, 2)), IsUnsigned))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType( @@ -1073,6 +1171,10 @@ extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() { return dwarf::DW_OP_plus_uconst; } +extern "C" int64_t LLVMRustDIBuilderCreateOpLLVMFragment() { + return dwarf::DW_OP_LLVM_fragment; +} + extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) { RawRustStringOstream OS(Str); unwrap<llvm::Type>(Ty)->print(OS); @@ -1093,6 +1195,8 @@ extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, } // LLVMArrayType function does not support 64-bit ElementCount +// FIXME: replace with LLVMArrayType2 when bumped minimal version to llvm-17 +// https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy, uint64_t ElementCount) { return wrap(ArrayType::get(unwrap(ElementTy), ElementCount)); @@ -1280,18 +1384,16 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { return LLVMBFloatTypeKind; case Type::X86_AMXTyID: return LLVMX86_AMXTypeKind; -#if LLVM_VERSION_GE(15, 0) && LLVM_VERSION_LT(16, 0) - case Type::DXILPointerTyID: - report_fatal_error("Rust does not support DirectX typed pointers."); - break; -#endif -#if LLVM_VERSION_GE(16, 0) - case Type::TypedPointerTyID: - report_fatal_error("Rust does not support typed pointers."); - break; -#endif + default: + { + std::string error; + llvm::raw_string_ostream stream(error); + stream << "Rust does not support the TypeID: " << unwrap(Ty)->getTypeID() + << " for the type: " << *unwrap(Ty); + stream.flush(); + report_fatal_error(error.c_str()); + } } - report_fatal_error("Unhandled TypeID."); } DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef) @@ -1350,65 +1452,10 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, return true; } -extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B, - LLVMValueRef ParentPad, - unsigned ArgCount, - LLVMValueRef *LLArgs, - const char *Name) { - Value **Args = unwrap(LLArgs); - if (ParentPad == nullptr) { - Type *Ty = Type::getTokenTy(unwrap(B)->getContext()); - ParentPad = wrap(Constant::getNullValue(Ty)); - } - return wrap(unwrap(B)->CreateCleanupPad( - unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name)); -} - -extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B, - LLVMValueRef CleanupPad, - LLVMBasicBlockRef UnwindBB) { - CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad)); - return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB))); -} - -extern "C" LLVMValueRef -LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad, - unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) { - Value **Args = unwrap(LLArgs); - return wrap(unwrap(B)->CreateCatchPad( - unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name)); -} - -extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B, - LLVMValueRef Pad, - LLVMBasicBlockRef BB) { - return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)), - unwrap(BB))); -} - -extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B, - LLVMValueRef ParentPad, - LLVMBasicBlockRef BB, - unsigned NumHandlers, - const char *Name) { - if (ParentPad == nullptr) { - Type *Ty = Type::getTokenTy(unwrap(B)->getContext()); - ParentPad = wrap(Constant::getNullValue(Ty)); - } - return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB), - NumHandlers, Name)); -} - -extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef, - LLVMBasicBlockRef Handler) { - Value *CatchSwitch = unwrap(CatchSwitchRef); - cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler)); -} - extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name, LLVMValueRef *Inputs, unsigned NumInputs) { - return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs)); + return new OperandBundleDef(Name, ArrayRef<Value*>(unwrap(Inputs), NumInputs)); } extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) { @@ -1417,13 +1464,13 @@ extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) { extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, - OperandBundleDef *Bundle) { + OperandBundleDef **OpBundles, + unsigned NumOpBundles) { Value *Callee = unwrap(Fn); FunctionType *FTy = unwrap<FunctionType>(Ty); - unsigned Len = Bundle ? 1 : 0; - ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len); return wrap(unwrap(B)->CreateCall( - FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles)); + FTy, Callee, ArrayRef<Value*>(unwrap(Args), NumArgs), + ArrayRef<OperandBundleDef>(*OpBundles, NumOpBundles))); } extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) { @@ -1463,14 +1510,14 @@ extern "C" LLVMValueRef LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, - OperandBundleDef *Bundle, const char *Name) { + OperandBundleDef **OpBundles, unsigned NumOpBundles, + const char *Name) { Value *Callee = unwrap(Fn); FunctionType *FTy = unwrap<FunctionType>(Ty); - unsigned Len = Bundle ? 1 : 0; - ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len); return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch), - makeArrayRef(unwrap(Args), NumArgs), - Bundles, Name)); + ArrayRef<Value*>(unwrap(Args), NumArgs), + ArrayRef<OperandBundleDef>(*OpBundles, NumOpBundles), + Name)); } extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, @@ -1569,16 +1616,6 @@ extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMSetLinkage(V, fromRust(RustLinkage)); } -extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty, - LLVMValueRef ConstantVal, - LLVMValueRef *ConstantIndices, - unsigned NumIndices) { - ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices), - NumIndices); - Constant *Val = unwrap<Constant>(ConstantVal); - return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList)); -} - extern "C" bool LLVMRustConstIntGetZExtValue(LLVMValueRef CV, uint64_t *value) { auto C = unwrap<llvm::ConstantInt>(CV); if (C->getBitWidth() > 64) @@ -1646,12 +1683,6 @@ extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) { return toRust(LLVMGetVisibility(V)); } -// Oh hey, a binding that makes sense for once? (because LLVM’s own do not) -extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val, - LLVMTypeRef DestTy, bool isSigned) { - return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, "")); -} - extern "C" void LLVMRustSetVisibility(LLVMValueRef V, LLVMRustVisibility RustVisibility) { LLVMSetVisibility(V, fromRust(RustVisibility)); @@ -1696,6 +1727,19 @@ LLVMRustModuleCost(LLVMModuleRef M) { return std::distance(std::begin(f), std::end(f)); } +extern "C" void +LLVMRustModuleInstructionStats(LLVMModuleRef M, RustStringRef Str) +{ + RawRustStringOstream OS(Str); + llvm::json::OStream JOS(OS); + auto Module = unwrap(M); + + JOS.object([&] { + JOS.attribute("module", Module->getName()); + JOS.attribute("total", Module->getInstructionCount()); + }); +} + // Vector reductions: extern "C" LLVMValueRef LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { @@ -1831,23 +1875,44 @@ using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy; // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise // the RemarkPasses array specifies individual passes for which remarks will be // enabled. +// +// If RemarkFilePath is not NULL, optimization remarks will be streamed directly into this file, +// bypassing the diagnostics handler. extern "C" void LLVMRustContextConfigureDiagnosticHandler( LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, void *DiagnosticHandlerContext, bool RemarkAllPasses, - const char * const * RemarkPasses, size_t RemarkPassesLen) { + const char * const * RemarkPasses, size_t RemarkPassesLen, + const char * RemarkFilePath +) { class RustDiagnosticHandler final : public DiagnosticHandler { public: - RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, - void *DiagnosticHandlerContext, - bool RemarkAllPasses, - std::vector<std::string> RemarkPasses) + RustDiagnosticHandler( + LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, + void *DiagnosticHandlerContext, + bool RemarkAllPasses, + std::vector<std::string> RemarkPasses, + std::unique_ptr<ToolOutputFile> RemarksFile, + std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer, + std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer + ) : DiagnosticHandlerCallback(DiagnosticHandlerCallback), DiagnosticHandlerContext(DiagnosticHandlerContext), RemarkAllPasses(RemarkAllPasses), - RemarkPasses(RemarkPasses) {} + RemarkPasses(std::move(RemarkPasses)), + RemarksFile(std::move(RemarksFile)), + RemarkStreamer(std::move(RemarkStreamer)), + LlvmRemarkStreamer(std::move(LlvmRemarkStreamer)) {} virtual bool handleDiagnostics(const DiagnosticInfo &DI) override { + if (this->LlvmRemarkStreamer) { + if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) { + if (OptDiagBase->isEnabled()) { + this->LlvmRemarkStreamer->emit(*OptDiagBase); + return true; + } + } + } if (DiagnosticHandlerCallback) { DiagnosticHandlerCallback(DI, DiagnosticHandlerContext); return true; @@ -1888,14 +1953,64 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler( bool RemarkAllPasses = false; std::vector<std::string> RemarkPasses; + + // Since LlvmRemarkStreamer contains a pointer to RemarkStreamer, the ordering of the three + // members below is important. + std::unique_ptr<ToolOutputFile> RemarksFile; + std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer; + std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer; }; std::vector<std::string> Passes; for (size_t I = 0; I != RemarkPassesLen; ++I) + { Passes.push_back(RemarkPasses[I]); + } + + // We need to hold onto both the streamers and the opened file + std::unique_ptr<ToolOutputFile> RemarkFile; + std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer; + std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer; + + if (RemarkFilePath != nullptr) { + std::error_code EC; + RemarkFile = std::make_unique<ToolOutputFile>( + RemarkFilePath, + EC, + llvm::sys::fs::OF_TextWithCRLF + ); + if (EC) { + std::string Error = std::string("Cannot create remark file: ") + + toString(errorCodeToError(EC)); + report_fatal_error(Twine(Error)); + } + + // Do not delete the file after we gather remarks + RemarkFile->keep(); + + auto RemarkSerializer = remarks::createRemarkSerializer( + llvm::remarks::Format::YAML, + remarks::SerializerMode::Separate, + RemarkFile->os() + ); + if (Error E = RemarkSerializer.takeError()) + { + std::string Error = std::string("Cannot create remark serializer: ") + toString(std::move(E)); + report_fatal_error(Twine(Error)); + } + RemarkStreamer = std::make_unique<llvm::remarks::RemarkStreamer>(std::move(*RemarkSerializer)); + LlvmRemarkStreamer = std::make_unique<LLVMRemarkStreamer>(*RemarkStreamer); + } unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>( - DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes)); + DiagnosticHandlerCallback, + DiagnosticHandlerContext, + RemarkAllPasses, + Passes, + std::move(RemarkFile), + std::move(RemarkStreamer), + std::move(LlvmRemarkStreamer) + )); } extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) { @@ -1924,3 +2039,7 @@ extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) { #endif return -1; } + +extern "C" bool LLVMRustIsBitcode(char *ptr, size_t len) { + return identify_magic(StringRef(ptr, len)) == file_magic::bitcode; +} diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp new file mode 100644 index 00000000000..0493d6b05d0 --- /dev/null +++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp @@ -0,0 +1,95 @@ +// Derived from code in LLVM, which is: +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Derived from: +// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h +// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp + +#include "llvm/IR/LLVMContext.h" +#include "llvm/Object/ObjectFile.h" + +using namespace llvm; +using namespace llvm::sys; +using namespace llvm::object; + +static bool isArchiveSymbol(const object::BasicSymbolRef &S) { + Expected<uint32_t> SymFlagsOrErr = S.getFlags(); + if (!SymFlagsOrErr) + // FIXME: Actually report errors helpfully. + report_fatal_error(SymFlagsOrErr.takeError()); + if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific) + return false; + if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global)) + return false; + if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined) + return false; + return true; +} + +typedef void *(*LLVMRustGetSymbolsCallback)(void *, const char *); +typedef void *(*LLVMRustGetSymbolsErrorCallback)(const char *); + +// Note: This is implemented in C++ instead of using the C api from Rust as IRObjectFile doesn't +// implement getSymbolName, only printSymbolName, which is inaccessible from the C api. +extern "C" void *LLVMRustGetSymbols( + char *BufPtr, size_t BufLen, void *State, LLVMRustGetSymbolsCallback Callback, + LLVMRustGetSymbolsErrorCallback ErrorCallback) { + std::unique_ptr<MemoryBuffer> Buf = + MemoryBuffer::getMemBuffer(StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), + false); + SmallString<0> SymNameBuf; + raw_svector_ostream SymName(SymNameBuf); + + // In the scenario when LLVMContext is populated SymbolicFile will contain a + // reference to it, thus SymbolicFile should be destroyed first. + LLVMContext Context; + std::unique_ptr<object::SymbolicFile> Obj; + + const file_magic Type = identify_magic(Buf->getBuffer()); + if (!object::SymbolicFile::isSymbolicFile(Type, &Context)) { + return 0; + } + + if (Type == file_magic::bitcode) { + auto ObjOrErr = object::SymbolicFile::createSymbolicFile( + Buf->getMemBufferRef(), file_magic::bitcode, &Context); + if (!ObjOrErr) { + Error E = ObjOrErr.takeError(); + SmallString<0> ErrorBuf; + raw_svector_ostream Error(ErrorBuf); + Error << E << '\0'; + return ErrorCallback(Error.str().data()); + } + Obj = std::move(*ObjOrErr); + } else { + auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf->getMemBufferRef()); + if (!ObjOrErr) { + Error E = ObjOrErr.takeError(); + SmallString<0> ErrorBuf; + raw_svector_ostream Error(ErrorBuf); + Error << E << '\0'; + return ErrorCallback(Error.str().data()); + } + Obj = std::move(*ObjOrErr); + } + + + for (const object::BasicSymbolRef &S : Obj->symbols()) { + if (!isArchiveSymbol(S)) + continue; + if (Error E = S.printName(SymName)) { + SmallString<0> ErrorBuf; + raw_svector_ostream Error(ErrorBuf); + Error << E << '\0'; + return ErrorCallback(Error.str().data()); + } + SymName << '\0'; + if (void *E = Callback(State, SymNameBuf.str().data())) { + return E; + } + SymNameBuf.clear(); + } + return 0; +} |
