diff options
Diffstat (limited to 'compiler/rustc_llvm/llvm-wrapper')
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp | 4 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp | 31 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h | 9 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 348 | ||||
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 301 |
5 files changed, 466 insertions, 227 deletions
diff --git a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp index 2797fe8df4a..97541e615da 100644 --- a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp @@ -91,11 +91,7 @@ extern "C" void LLVMRustDestroyArchive(LLVMRustArchiveRef RustArchive) { extern "C" LLVMRustArchiveIteratorRef LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) { Archive *Archive = RustArchive->getBinary(); -#if LLVM_VERSION_GE(10, 0) std::unique_ptr<Error> Err = std::make_unique<Error>(Error::success()); -#else - std::unique_ptr<Error> Err = llvm::make_unique<Error>(Error::success()); -#endif auto Cur = Archive->child_begin(*Err); if (*Err) { LLVMRustSetLastError(toString(std::move(*Err)).c_str()); diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 25badc3f4e1..35cca04b20f 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -8,14 +8,32 @@ using namespace llvm; +struct LLVMRustCounterMappingRegion { + coverage::Counter Count; + uint32_t FileID; + uint32_t ExpandedFileID; + uint32_t LineStart; + uint32_t ColumnStart; + uint32_t LineEnd; + uint32_t ColumnEnd; + coverage::CounterMappingRegion::RegionKind Kind; +}; + extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( const char* const Filenames[], size_t FilenamesLen, RustStringRef BufferOut) { +#if LLVM_VERSION_GE(13,0) + SmallVector<std::string,32> FilenameRefs; + for (size_t i = 0; i < FilenamesLen; i++) { + FilenameRefs.push_back(std::string(Filenames[i])); + } +#else SmallVector<StringRef,32> FilenameRefs; for (size_t i = 0; i < FilenamesLen; i++) { FilenameRefs.push_back(StringRef(Filenames[i])); } +#endif auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter( makeArrayRef(FilenameRefs)); RawRustStringOstream OS(BufferOut); @@ -27,13 +45,22 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer( unsigned NumVirtualFileMappingIDs, const coverage::CounterExpression *Expressions, unsigned NumExpressions, - coverage::CounterMappingRegion *MappingRegions, + 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)) { + MappingRegions.emplace_back( + Region.Count, Region.FileID, Region.ExpandedFileID, + Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd, + Region.Kind); + } auto CoverageMappingWriter = coverage::CoverageMappingWriter( makeArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs), makeArrayRef(Expressions, NumExpressions), - makeMutableArrayRef(MappingRegions, NumMappingRegions)); + 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 57b8664d3b6..0b1b68d83b7 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -33,13 +33,6 @@ (LLVM_VERSION_MAJOR > (major) || \ LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR >= (minor)) -#define LLVM_VERSION_EQ(major, minor) \ - (LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR == (minor)) - -#define LLVM_VERSION_LE(major, minor) \ - (LLVM_VERSION_MAJOR < (major) || \ - LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR <= (minor)) - #define LLVM_VERSION_LT(major, minor) (!LLVM_VERSION_GE((major), (minor))) #include "llvm/IR/LegacyPassManager.h" @@ -85,6 +78,8 @@ enum LLVMRustAttribute { ReturnsTwice = 25, ReadNone = 26, InaccessibleMemOnly = 27, + SanitizeHWAddress = 28, + WillReturn = 29, }; typedef struct OpaqueRustString *RustStringRef; diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 2264908995b..b3f86f3295a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -5,6 +5,7 @@ #include "LLVMWrapper.h" +#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" @@ -31,8 +32,11 @@ #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Instrumentation/AddressSanitizer.h" #include "llvm/Support/TimeProfiler.h" +#include "llvm/Transforms/Instrumentation/GCOVProfiler.h" +#include "llvm/Transforms/Instrumentation/InstrProfiling.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" +#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" #include "llvm/Transforms/Utils/CanonicalizeAliases.h" #include "llvm/Transforms/Utils/NameAnonGlobals.h" @@ -63,13 +67,9 @@ extern "C" void LLVMInitializePasses() { } extern "C" void LLVMTimeTraceProfilerInitialize() { -#if LLVM_VERSION_GE(10, 0) timeTraceProfilerInitialize( /* TimeTraceGranularity */ 0, /* ProcName */ "rustc"); -#else - timeTraceProfilerInitialize(); -#endif } extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { @@ -133,6 +133,12 @@ extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() { return wrap(createThreadSanitizerLegacyPassPass()); } +extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) { + const bool CompileKernel = false; + + return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover)); +} + extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) { assert(RustPass); Pass *Pass = unwrap(RustPass); @@ -325,20 +331,24 @@ enum class LLVMRustPassBuilderOptLevel { Oz, }; -static PassBuilder::OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) { +#if LLVM_VERSION_LT(14,0) +using OptimizationLevel = PassBuilder::OptimizationLevel; +#endif + +static OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) { switch (Level) { case LLVMRustPassBuilderOptLevel::O0: - return PassBuilder::OptimizationLevel::O0; + return OptimizationLevel::O0; case LLVMRustPassBuilderOptLevel::O1: - return PassBuilder::OptimizationLevel::O1; + return OptimizationLevel::O1; case LLVMRustPassBuilderOptLevel::O2: - return PassBuilder::OptimizationLevel::O2; + return OptimizationLevel::O2; case LLVMRustPassBuilderOptLevel::O3: - return PassBuilder::OptimizationLevel::O3; + return OptimizationLevel::O3; case LLVMRustPassBuilderOptLevel::Os: - return PassBuilder::OptimizationLevel::Os; + return OptimizationLevel::Os; case LLVMRustPassBuilderOptLevel::Oz: - return PassBuilder::OptimizationLevel::Oz; + return OptimizationLevel::Oz; default: report_fatal_error("Bad PassBuilderOptLevel."); } @@ -400,26 +410,21 @@ extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) { printf("\n"); } -extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) { +extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) { const TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable(); - unsigned MaxFeatLen = getLongestEntryLength(FeatTable); - - printf("Available features for this target:\n"); - for (auto &Feature : FeatTable) - printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); - printf("\nRust-specific features:\n"); - printf(" %-*s - %s.\n", - MaxFeatLen, - "crt-static", - "Enables libraries with C Run-time Libraries(CRT) to be statically linked" - ); - printf("\n"); + return FeatTable.size(); +} - printf("Use +feature to enable a feature, or -feature to disable it.\n" - "For example, rustc -C -target-cpu=mycpu -C " - "target-feature=+feature1,-feature2\n\n"); +extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index, + const char** Feature, const char** Desc) { + 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 @@ -428,9 +433,11 @@ extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) { printf("Target CPU help is not supported by this LLVM version.\n\n"); } -extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) { - printf("Target features 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) { @@ -588,7 +595,6 @@ enum class LLVMRustFileType { ObjectFile, }; -#if LLVM_VERSION_GE(10, 0) static CodeGenFileType fromRust(LLVMRustFileType Type) { switch (Type) { case LLVMRustFileType::AssemblyFile: @@ -599,18 +605,6 @@ static CodeGenFileType fromRust(LLVMRustFileType Type) { report_fatal_error("Bad FileType."); } } -#else -static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) { - switch (Type) { - case LLVMRustFileType::AssemblyFile: - return TargetMachine::CGFT_AssemblyFile; - case LLVMRustFileType::ObjectFile: - return TargetMachine::CGFT_ObjectFile; - default: - report_fatal_error("Bad FileType."); - } -} -#endif extern "C" LLVMRustResult LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, @@ -621,7 +615,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, std::string ErrorInfo; std::error_code EC; - raw_fd_ostream OS(Path, EC, sys::fs::F_None); + raw_fd_ostream OS(Path, EC, sys::fs::OF_None); if (EC) ErrorInfo = EC.message(); if (ErrorInfo != "") { @@ -631,7 +625,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, buffer_ostream BOS(OS); if (DwoPath) { - raw_fd_ostream DOS(DwoPath, EC, sys::fs::F_None); + raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None); EC.clear(); if (EC) ErrorInfo = EC.message(); @@ -676,6 +670,25 @@ void LLVMSelfProfileInitializeCallbacks( PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler, LLVMRustSelfProfileBeforePassCallback BeforePassCallback, LLVMRustSelfProfileAfterPassCallback AfterPassCallback) { +#if LLVM_VERSION_GE(12, 0) + PIC.registerBeforeNonSkippedPassCallback([LlvmSelfProfiler, BeforePassCallback]( + StringRef Pass, llvm::Any Ir) { + std::string PassName = Pass.str(); + std::string IrName = LLVMRustwrappedIrGetName(Ir); + BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str()); + }); + + PIC.registerAfterPassCallback( + [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any IR, + const PreservedAnalyses &Preserved) { + AfterPassCallback(LlvmSelfProfiler); + }); + + PIC.registerAfterPassInvalidatedCallback( + [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) { + AfterPassCallback(LlvmSelfProfiler); + }); +#else PIC.registerBeforePassCallback([LlvmSelfProfiler, BeforePassCallback]( StringRef Pass, llvm::Any Ir) { std::string PassName = Pass.str(); @@ -693,6 +706,7 @@ void LLVMSelfProfileInitializeCallbacks( [LlvmSelfProfiler, AfterPassCallback](StringRef Pass) { AfterPassCallback(LlvmSelfProfiler); }); +#endif PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback]( StringRef Pass, llvm::Any Ir) { @@ -722,9 +736,11 @@ struct LLVMRustSanitizerOptions { bool SanitizeMemoryRecover; int SanitizeMemoryTrackOrigins; bool SanitizeThread; + bool SanitizeHWAddress; + bool SanitizeHWAddressRecover; }; -extern "C" void +extern "C" LLVMRustResult LLVMRustOptimizeWithNewPassManager( LLVMModuleRef ModuleRef, LLVMTargetMachineRef TMRef, @@ -735,24 +751,37 @@ LLVMRustOptimizeWithNewPassManager( bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers, LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath, const char *PGOUsePath, + bool InstrumentCoverage, bool InstrumentGCOV, void* LlvmSelfProfiler, LLVMRustSelfProfileBeforePassCallback BeforePassCallback, - LLVMRustSelfProfileAfterPassCallback AfterPassCallback) { + LLVMRustSelfProfileAfterPassCallback AfterPassCallback, + const char *ExtraPasses, size_t ExtraPassesLen) { Module *TheModule = unwrap(ModuleRef); TargetMachine *TM = unwrap(TMRef); - PassBuilder::OptimizationLevel OptLevel = fromRust(OptLevelRust); + OptimizationLevel OptLevel = fromRust(OptLevelRust); - // FIXME: MergeFunctions is not supported by NewPM yet. - (void) MergeFunctions; PipelineTuningOptions PTO; PTO.LoopUnrolling = UnrollLoops; PTO.LoopInterleaving = UnrollLoops; PTO.LoopVectorization = LoopVectorize; PTO.SLPVectorization = SLPVectorize; +#if LLVM_VERSION_GE(12, 0) + PTO.MergeFunctions = MergeFunctions; +#else + // MergeFunctions is not supported by NewPM in older LLVM versions. + (void) MergeFunctions; +#endif + + // FIXME: We may want to expose this as an option. + bool DebugPassManager = false; PassInstrumentationCallbacks PIC; +#if LLVM_VERSION_GE(12, 0) + StandardInstrumentations SI(DebugPassManager); +#else StandardInstrumentations SI; +#endif SI.registerCallbacks(PIC); if (LlvmSelfProfiler){ @@ -768,14 +797,23 @@ LLVMRustOptimizeWithNewPassManager( PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse); } +#if LLVM_VERSION_GE(12, 0) && !LLVM_VERSION_GE(13,0) + PassBuilder PB(DebugPassManager, TM, PTO, PGOOpt, &PIC); +#else PassBuilder PB(TM, PTO, PGOOpt, &PIC); +#endif - // FIXME: We may want to expose this as an option. - bool DebugPassManager = false; +#if LLVM_VERSION_GE(13, 0) + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; +#else LoopAnalysisManager LAM(DebugPassManager); FunctionAnalysisManager FAM(DebugPassManager); CGSCCAnalysisManager CGAM(DebugPassManager); ModuleAnalysisManager MAM(DebugPassManager); +#endif FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); }); @@ -793,19 +831,39 @@ LLVMRustOptimizeWithNewPassManager( // We manually collect pipeline callbacks so we can apply them at O0, where the // PassBuilder does not create a pipeline. - std::vector<std::function<void(ModulePassManager &)>> PipelineStartEPCallbacks; + std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>> + PipelineStartEPCallbacks; #if LLVM_VERSION_GE(11, 0) - std::vector<std::function<void(ModulePassManager &, PassBuilder::OptimizationLevel)>> + std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>> OptimizerLastEPCallbacks; #else - std::vector<std::function<void(FunctionPassManager &, PassBuilder::OptimizationLevel)>> + std::vector<std::function<void(FunctionPassManager &, OptimizationLevel)>> OptimizerLastEPCallbacks; #endif if (VerifyIR) { - PipelineStartEPCallbacks.push_back([VerifyIR](ModulePassManager &MPM) { + PipelineStartEPCallbacks.push_back( + [VerifyIR](ModulePassManager &MPM, OptimizationLevel Level) { MPM.addPass(VerifierPass()); - }); + } + ); + } + + if (InstrumentGCOV) { + PipelineStartEPCallbacks.push_back( + [](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault())); + } + ); + } + + if (InstrumentCoverage) { + PipelineStartEPCallbacks.push_back( + [](ModulePassManager &MPM, OptimizationLevel Level) { + InstrProfOptions Options; + MPM.addPass(InstrProfiling(Options, false)); + } + ); } if (SanitizerOptions) { @@ -816,19 +874,19 @@ LLVMRustOptimizeWithNewPassManager( /*CompileKernel=*/false); #if LLVM_VERSION_GE(11, 0) OptimizerLastEPCallbacks.push_back( - [Options](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { + [Options](ModulePassManager &MPM, OptimizationLevel Level) { MPM.addPass(MemorySanitizerPass(Options)); MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options))); } ); #else -#if LLVM_VERSION_GE(10, 0) - PipelineStartEPCallbacks.push_back([Options](ModulePassManager &MPM) { - MPM.addPass(MemorySanitizerPass(Options)); - }); -#endif + PipelineStartEPCallbacks.push_back( + [Options](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(MemorySanitizerPass(Options)); + } + ); OptimizerLastEPCallbacks.push_back( - [Options](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { + [Options](FunctionPassManager &FPM, OptimizationLevel Level) { FPM.addPass(MemorySanitizerPass(Options)); } ); @@ -838,19 +896,19 @@ LLVMRustOptimizeWithNewPassManager( if (SanitizerOptions->SanitizeThread) { #if LLVM_VERSION_GE(11, 0) OptimizerLastEPCallbacks.push_back( - [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { + [](ModulePassManager &MPM, OptimizationLevel Level) { MPM.addPass(ThreadSanitizerPass()); MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); } ); #else -#if LLVM_VERSION_GE(10, 0) - PipelineStartEPCallbacks.push_back([](ModulePassManager &MPM) { - MPM.addPass(ThreadSanitizerPass()); - }); -#endif + PipelineStartEPCallbacks.push_back( + [](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(ThreadSanitizerPass()); + } + ); OptimizerLastEPCallbacks.push_back( - [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { + [](FunctionPassManager &FPM, OptimizationLevel Level) { FPM.addPass(ThreadSanitizerPass()); } ); @@ -860,57 +918,104 @@ LLVMRustOptimizeWithNewPassManager( if (SanitizerOptions->SanitizeAddress) { #if LLVM_VERSION_GE(11, 0) OptimizerLastEPCallbacks.push_back( - [SanitizerOptions](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { + [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>()); MPM.addPass(ModuleAddressSanitizerPass( /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); +#if LLVM_VERSION_GE(14, 0) + AddressSanitizerOptions opts(/*CompileKernel=*/false, + SanitizerOptions->SanitizeAddressRecover, + /*UseAfterScope=*/true, + AsanDetectStackUseAfterReturnMode::Runtime); + MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(opts))); +#else MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass( /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover, /*UseAfterScope=*/true))); +#endif } ); #else - PipelineStartEPCallbacks.push_back([&](ModulePassManager &MPM) { - MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>()); - }); + PipelineStartEPCallbacks.push_back( + [&](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>()); + } + ); OptimizerLastEPCallbacks.push_back( - [SanitizerOptions](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { + [SanitizerOptions](FunctionPassManager &FPM, OptimizationLevel Level) { FPM.addPass(AddressSanitizerPass( /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover, /*UseAfterScope=*/true)); } ); PipelineStartEPCallbacks.push_back( - [SanitizerOptions](ModulePassManager &MPM) { + [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { MPM.addPass(ModuleAddressSanitizerPass( /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); } ); #endif } + if (SanitizerOptions->SanitizeHWAddress) { +#if LLVM_VERSION_GE(11, 0) + 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 + } + ); +#else + PipelineStartEPCallbacks.push_back( + [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(HWAddressSanitizerPass( + /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover)); + } + ); +#endif + } } +#if LLVM_VERSION_GE(13, 0) + ModulePassManager MPM; +#else ModulePassManager MPM(DebugPassManager); +#endif + bool NeedThinLTOBufferPasses = UseThinLTOBuffers; if (!NoPrepopulatePasses) { - if (OptLevel == PassBuilder::OptimizationLevel::O0) { + if (OptLevel == OptimizationLevel::O0) { +#if LLVM_VERSION_GE(12, 0) for (const auto &C : PipelineStartEPCallbacks) - C(MPM); + PB.registerPipelineStartEPCallback(C); + for (const auto &C : OptimizerLastEPCallbacks) + PB.registerOptimizerLastEPCallback(C); -#if LLVM_VERSION_GE(11, 0) + // Pass false as we manually schedule ThinLTOBufferPasses below. + MPM = PB.buildO0DefaultPipeline(OptLevel, /* PreLinkLTO */ false); +#else + for (const auto &C : PipelineStartEPCallbacks) + C(MPM, OptLevel); + +# if LLVM_VERSION_GE(11, 0) for (const auto &C : OptimizerLastEPCallbacks) C(MPM, OptLevel); -#else +# else if (!OptimizerLastEPCallbacks.empty()) { FunctionPassManager FPM(DebugPassManager); for (const auto &C : OptimizerLastEPCallbacks) C(FPM, OptLevel); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } -#endif +# endif MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers)); -#if LLVM_VERSION_GE(10, 0) if (PGOOpt) { PB.addPGOInstrPassesForO0( MPM, DebugPassManager, PGOOpt->Action == PGOOptions::IRInstr, @@ -918,8 +1023,15 @@ LLVMRustOptimizeWithNewPassManager( } #endif } else { +#if LLVM_VERSION_GE(12, 0) for (const auto &C : PipelineStartEPCallbacks) PB.registerPipelineStartEPCallback(C); +#else + for (const auto &C : PipelineStartEPCallbacks) + PB.registerPipelineStartEPCallback([C, OptLevel](ModulePassManager &MPM) { + C(MPM, OptLevel); + }); +#endif if (OptStage != LLVMRustOptStage::PreLinkThinLTO) { for (const auto &C : OptimizerLastEPCallbacks) PB.registerOptimizerLastEPCallback(C); @@ -930,7 +1042,17 @@ LLVMRustOptimizeWithNewPassManager( MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager); break; case LLVMRustOptStage::PreLinkThinLTO: +#if LLVM_VERSION_GE(12, 0) + MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel); + // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback + // passes may still run afterwards. This means we need to run the buffer passes again. + // FIXME: In LLVM 13, the ThinLTOPreLink pipeline also runs OptimizerLastEPCallbacks + // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks. + if (OptimizerLastEPCallbacks.empty()) + NeedThinLTOBufferPasses = false; +#else MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager); +#endif #if LLVM_VERSION_GE(11, 0) for (const auto &C : OptimizerLastEPCallbacks) C(MPM, OptLevel); @@ -944,21 +1066,42 @@ LLVMRustOptimizeWithNewPassManager( #endif break; case LLVMRustOptStage::PreLinkFatLTO: +#if LLVM_VERSION_GE(12, 0) + MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel); + NeedThinLTOBufferPasses = false; +#else MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager); +#endif break; case LLVMRustOptStage::ThinLTO: // FIXME: Does it make sense to pass the ModuleSummaryIndex? // It only seems to be needed for C++ specific optimizations. +#if LLVM_VERSION_GE(12, 0) + MPM = PB.buildThinLTODefaultPipeline(OptLevel, nullptr); +#else MPM = PB.buildThinLTODefaultPipeline(OptLevel, DebugPassManager, nullptr); +#endif break; case LLVMRustOptStage::FatLTO: +#if LLVM_VERSION_GE(12, 0) + MPM = PB.buildLTODefaultPipeline(OptLevel, nullptr); +#else MPM = PB.buildLTODefaultPipeline(OptLevel, DebugPassManager, nullptr); +#endif break; } } } - if (UseThinLTOBuffers) { + if (ExtraPassesLen) { + if (auto Err = PB.parsePassPipeline(MPM, StringRef(ExtraPasses, ExtraPassesLen))) { + std::string ErrMsg = toString(std::move(Err)); + LLVMRustSetLastError(ErrMsg.c_str()); + return LLVMRustResult::Failure; + } + } + + if (NeedThinLTOBufferPasses) { MPM.addPass(CanonicalizeAliasesPass()); MPM.addPass(NameAnonGlobalPass()); } @@ -968,6 +1111,7 @@ LLVMRustOptimizeWithNewPassManager( UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove MPM.run(*TheModule, MAM); + return LLVMRustResult::Success; } // Callback to demangle function name @@ -1062,7 +1206,7 @@ extern "C" LLVMRustResult LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) { std::string ErrorInfo; std::error_code EC; - raw_fd_ostream OS(Path, EC, sys::fs::F_None); + raw_fd_ostream OS(Path, EC, sys::fs::OF_None); if (EC) ErrorInfo = EC.message(); if (ErrorInfo != "") { @@ -1154,6 +1298,14 @@ extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) { unwrap(M)->setPIELevel(PIELevel::Level::Large); } +extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M, + LLVMRustCodeModel Model) { + auto CM = fromRust(Model); + if (!CM.hasValue()) + return; + unwrap(M)->setCodeModel(*CM); +} + // Here you'll find an implementation of ThinLTO as used by the Rust compiler // right now. This ThinLTO support is only enabled on "recent ish" versions of // LLVM, and otherwise it's just blanket rejected from other compilers. @@ -1248,11 +1400,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, int num_modules, const char **preserved_symbols, int num_symbols) { -#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique<LLVMRustThinLTOData>(); -#else - auto Ret = llvm::make_unique<LLVMRustThinLTOData>(); -#endif // Load each module's summary and merge it into one combined index for (int i = 0; i < num_modules; i++) { @@ -1319,9 +1467,17 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, Ret->ResolvedODR[ModuleIdentifier][GUID] = NewLinkage; }; +#if LLVM_VERSION_GE(13,0) + // Uses FromPrevailing visibility scheme which works for many binary + // formats. We probably could and should use ELF visibility scheme for many of + // our targets, however. + lto::Config conf; + thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage, + Ret->GUIDPreservedSymbols); +#else thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage, Ret->GUIDPreservedSymbols); - +#endif // Here we calculate an `ExportedGUIDs` set for use in the `isExported` // callback below. This callback below will dictate the linkage for all // summaries in the index, and we basically just only want to ensure that dead @@ -1337,7 +1493,6 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, ExportedGUIDs.insert(GUID); } } -#if LLVM_VERSION_GE(10, 0) auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) { const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); return (ExportList != Ret->ExportLists.end() && @@ -1345,15 +1500,6 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, ExportedGUIDs.count(VI.getGUID()); }; thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing); -#else - auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) { - const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); - return (ExportList != Ret->ExportLists.end() && - ExportList->second.count(GUID)) || - ExportedGUIDs.count(GUID); - }; - thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported); -#endif return Ret.release(); } @@ -1510,11 +1656,7 @@ struct LLVMRustThinLTOBuffer { extern "C" LLVMRustThinLTOBuffer* LLVMRustThinLTOBufferCreate(LLVMModuleRef M) { -#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique<LLVMRustThinLTOBuffer>(); -#else - auto Ret = llvm::make_unique<LLVMRustThinLTOBuffer>(); -#endif { raw_string_ostream OS(Ret->data); { diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index c0ff62c17be..4f07a0c67c1 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -6,6 +6,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/Support/Signals.h" @@ -70,17 +71,6 @@ extern "C" void LLVMRustInstallFatalErrorHandler() { install_fatal_error_handler(FatalErrorHandler); } -extern "C" LLVMMemoryBufferRef -LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { - ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr = - MemoryBuffer::getFile(Path, -1, false); - if (!BufOr) { - LLVMRustSetLastError(BufOr.getError().message().c_str()); - return nullptr; - } - return wrap(BufOr.get().release()); -} - extern "C" char *LLVMRustGetLastError(void) { char *Ret = LastError; LastError = nullptr; @@ -205,6 +195,10 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::ReadNone; case InaccessibleMemOnly: return Attribute::InaccessibleMemOnly; + case SanitizeHWAddress: + return Attribute::SanitizeHWAddress; + case WillReturn: + return Attribute::WillReturn; } report_fatal_error("bad AttributeKind"); } @@ -216,6 +210,14 @@ extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index, Call->addAttribute(Index, Attr); } +extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index, + const char *Name) { + CallBase *Call = unwrap<CallBase>(Instr); + Attribute Attr = Attribute::get(Call->getContext(), Name); + Call->addAttribute(Index, Attr); +} + + extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr, unsigned Index, uint32_t Bytes) { @@ -253,38 +255,45 @@ extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index, Call->addAttribute(Index, Attr); } +extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index, + LLVMTypeRef Ty) { + CallBase *Call = unwrap<CallBase>(Instr); +#if LLVM_VERSION_GE(12, 0) + Attribute Attr = Attribute::getWithStructRetType(Call->getContext(), unwrap(Ty)); +#else + Attribute Attr = Attribute::get(Call->getContext(), Attribute::StructRet); +#endif + Call->addAttribute(Index, Attr); +} + extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index, LLVMRustAttribute RustAttr) { Function *A = unwrap<Function>(Fn); Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr)); - AttrBuilder B(Attr); - A->addAttributes(Index, B); + A->addAttribute(Index, Attr); } extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn, unsigned Index, uint32_t Bytes) { Function *A = unwrap<Function>(Fn); - AttrBuilder B; - B.addAlignmentAttr(Bytes); - A->addAttributes(Index, B); + A->addAttribute(Index, Attribute::getWithAlignment( + A->getContext(), llvm::Align(Bytes))); } extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index, uint64_t Bytes) { Function *A = unwrap<Function>(Fn); - AttrBuilder B; - B.addDereferenceableAttr(Bytes); - A->addAttributes(Index, B); + A->addAttribute(Index, Attribute::getWithDereferenceableBytes(A->getContext(), + Bytes)); } extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn, unsigned Index, uint64_t Bytes) { Function *A = unwrap<Function>(Fn); - AttrBuilder B; - B.addDereferenceableOrNullAttr(Bytes); - A->addAttributes(Index, B); + A->addAttribute(Index, Attribute::getWithDereferenceableOrNullBytes( + A->getContext(), Bytes)); } extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index, @@ -294,14 +303,24 @@ extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index, F->addAttribute(Index, Attr); } +extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index, + LLVMTypeRef Ty) { + Function *F = unwrap<Function>(Fn); +#if LLVM_VERSION_GE(12, 0) + Attribute Attr = Attribute::getWithStructRetType(F->getContext(), unwrap(Ty)); +#else + Attribute Attr = Attribute::get(F->getContext(), Attribute::StructRet); +#endif + F->addAttribute(Index, Attr); +} + extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn, unsigned Index, const char *Name, const char *Value) { Function *F = unwrap<Function>(Fn); - AttrBuilder B; - B.addAttribute(Name, Value); - F->addAttributes(Index, B); + F->addAttribute(Index, Attribute::get( + F->getContext(), StringRef(Name), StringRef(Value))); } extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, @@ -315,19 +334,20 @@ extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, F->setAttributes(PALNew); } -// enable fpmath flag UnsafeAlgebra -extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) { +// Enable a fast-math flag +// +// https://llvm.org/docs/LangRef.html#fast-math-flags +extern "C" void LLVMRustSetFastMath(LLVMValueRef V) { if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) { I->setFast(true); } } extern "C" LLVMValueRef -LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef Source, const char *Name, - LLVMAtomicOrdering Order) { +LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source, + const char *Name, LLVMAtomicOrdering Order) { Value *Ptr = unwrap(Source); - Type *Ty = Ptr->getType()->getPointerElementType(); - LoadInst *LI = unwrap(B)->CreateLoad(Ty, Ptr, Name); + LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name); LI->setAtomic(fromRust(Order)); return wrap(LI); } @@ -348,9 +368,18 @@ LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target, LLVMValueRef Old, LLVMValueRef Source, LLVMAtomicOrdering Order, LLVMAtomicOrdering FailureOrder, LLVMBool Weak) { +#if LLVM_VERSION_GE(13,0) + // Rust probably knows the alignment of the target value and should be able to + // specify something more precise than MaybeAlign here. See also + // https://reviews.llvm.org/D97224 which may be a useful reference. + AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg( + unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order), + fromRust(FailureOrder)); +#else AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg( unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order), fromRust(FailureOrder)); +#endif ACXI->setWeak(Weak); return wrap(ACXI); } @@ -498,11 +527,6 @@ static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) { if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) { Result |= DINode::DIFlags::FlagAppleBlock; } -#if LLVM_VERSION_LT(10, 0) - if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) { - Result |= DINode::DIFlags::FlagBlockByrefStruct; - } -#endif if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) { Result |= DINode::DIFlags::FlagVirtual; } @@ -660,6 +684,8 @@ extern "C" uint32_t LLVMRustDebugMetadataVersion() { return DEBUG_METADATA_VERSION; } +extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; } + extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; } extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; } @@ -865,9 +891,7 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen), StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit, -#if LLVM_VERSION_GE(10, 0) /* isDefined */ true, -#endif InitExpr, unwrapDIPtr<MDNode>(Decl), /* templateParams */ nullptr, AlignInBits); @@ -994,15 +1018,20 @@ LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder, } extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateDebugLocation(LLVMContextRef ContextRef, unsigned Line, - unsigned Column, LLVMMetadataRef Scope, +LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column, + LLVMMetadataRef ScopeRef, LLVMMetadataRef InlinedAt) { - LLVMContext &Context = *unwrap(ContextRef); - - DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(Scope), +#if LLVM_VERSION_GE(12, 0) + MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef); + DILocation *Loc = DILocation::get( + Scope->getContext(), Line, Column, Scope, + unwrapDIPtr<MDNode>(InlinedAt)); + return wrap(Loc); +#else + DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(ScopeRef), unwrapDIPtr<MDNode>(InlinedAt)); - return wrap(debug_loc.getAsMDNode()); +#endif } extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() { @@ -1032,38 +1061,6 @@ extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, } } -// Note that the two following functions look quite similar to the -// LLVMGetSectionName function. Sadly, it appears that this function only -// returns a char* pointer, which isn't guaranteed to be null-terminated. The -// function provided by LLVM doesn't return the length, so we've created our own -// function which returns the length as well as the data pointer. -// -// For an example of this not returning a null terminated string, see -// lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the -// branches explicitly creates a StringRef without a null terminator, and then -// that's returned. - -inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { - return reinterpret_cast<section_iterator *>(SI); -} - -extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI, - const char **Ptr) { -#if LLVM_VERSION_GE(10, 0) - auto NameOrErr = (*unwrap(SI))->getName(); - if (!NameOrErr) - report_fatal_error(NameOrErr.takeError()); - *Ptr = NameOrErr->data(); - return NameOrErr->size(); -#else - StringRef Ret; - if (std::error_code EC = (*unwrap(SI))->getName(Ret)) - report_fatal_error(EC.message()); - *Ptr = Ret.data(); - return Ret.size(); -#endif -} - // LLVMArrayType function does not support 64-bit ElementCount extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy, uint64_t ElementCount) { @@ -1112,15 +1109,13 @@ extern "C" void LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, LLVMRustDiagnosticLevel *LevelOut, unsigned *CookieOut, - LLVMTwineRef *MessageOut, - LLVMValueRef *InstructionOut) { + LLVMTwineRef *MessageOut) { // Undefined to call this not on an inline assembly diagnostic! llvm::DiagnosticInfoInlineAsm *IA = static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI)); *CookieOut = IA->getLocCookie(); *MessageOut = wrap(&IA->getMsgStr()); - *InstructionOut = wrap(IA->getInstruction()); switch (IA->getSeverity()) { case DS_Error: @@ -1163,6 +1158,7 @@ enum class LLVMRustDiagnosticKind { PGOProfile, Linker, Unsupported, + SrcMgr, }; static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) { @@ -1191,6 +1187,10 @@ static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) { return LLVMRustDiagnosticKind::Linker; case DK_Unsupported: return LLVMRustDiagnosticKind::Unsupported; +#if LLVM_VERSION_GE(13, 0) + case DK_SrcMgr: + return LLVMRustDiagnosticKind::SrcMgr; +#endif default: return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark) ? LLVMRustDiagnosticKind::OptimizationRemarkOther @@ -1253,15 +1253,40 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { case Type::BFloatTyID: return LLVMBFloatTypeKind; #endif +#if LLVM_VERSION_GE(12, 0) + case Type::X86_AMXTyID: + return LLVMX86_AMXTypeKind; +#endif } report_fatal_error("Unhandled TypeID."); } DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef) +#if LLVM_VERSION_LT(13, 0) +using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy; +#else +using LLVMInlineAsmDiagHandlerTy = void*; +#endif + extern "C" void LLVMRustSetInlineAsmDiagnosticHandler( - LLVMContextRef C, LLVMContext::InlineAsmDiagHandlerTy H, void *CX) { + LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) { + // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting + // with LLVM 13 this function is gone. +#if LLVM_VERSION_LT(13, 0) unwrap(C)->setInlineAsmDiagnosticHandler(H, CX); +#endif +} + +extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic( + LLVMDiagnosticInfoRef DI, unsigned *Cookie) { +#if LLVM_VERSION_GE(13, 0) + llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI)); + *Cookie = SM->getLocCookie(); + return wrap(&SM->getSMDiag()); +#else + report_fatal_error("Shouldn't get called on older versions"); +#endif } extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, @@ -1376,11 +1401,11 @@ extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) { delete Bundle; } -extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, +extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, OperandBundleDef *Bundle) { Value *Callee = unwrap(Fn); - FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType()); + FunctionType *FTy = unwrap<FunctionType>(Ty); unsigned Len = Bundle ? 1 : 0; ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len); return wrap(unwrap(B)->CreateCall( @@ -1396,56 +1421,37 @@ extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemCpy( unwrap(Dst), MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign), unwrap(Size), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemCpy( - unwrap(Dst), DstAlign, - unwrap(Src), SrcAlign, - unwrap(Size), IsVolatile)); -#endif } extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemMove( unwrap(Dst), MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign), unwrap(Size), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemMove( - unwrap(Dst), DstAlign, - unwrap(Src), SrcAlign, - unwrap(Size), IsVolatile)); -#endif } extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Val, LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemSet( unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemSet( - unwrap(Dst), unwrap(Val), unwrap(Size), DstAlign, IsVolatile)); -#endif } extern "C" LLVMValueRef -LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, - unsigned NumArgs, LLVMBasicBlockRef Then, - LLVMBasicBlockRef Catch, OperandBundleDef *Bundle, - const char *Name) { +LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, + OperandBundleDef *Bundle, const char *Name) { Value *Callee = unwrap(Fn); - FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType()); + 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), @@ -1554,6 +1560,16 @@ 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)); +} + // Returns true if both high and low were successfully set. Fails in case constant wasn’t any of // the common sizes (1, 8, 16, 32, 64, 128 bits) extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low) @@ -1616,17 +1632,17 @@ extern "C" void LLVMRustSetVisibility(LLVMValueRef V, LLVMSetVisibility(V, fromRust(RustVisibility)); } +extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) { + unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local); +} + struct LLVMRustModuleBuffer { std::string data; }; extern "C" LLVMRustModuleBuffer* LLVMRustModuleBufferCreate(LLVMModuleRef M) { -#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique<LLVMRustModuleBuffer>(); -#else - auto Ret = llvm::make_unique<LLVMRustModuleBuffer>(); -#endif { raw_string_ostream OS(Ret->data); { @@ -1698,11 +1714,23 @@ LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) } extern "C" LLVMValueRef LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { - return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN)); +#if LLVM_VERSION_GE(12, 0) + Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src)); + I->setHasNoNaNs(NoNaN); + return wrap(I); +#else + return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN)); +#endif } extern "C" LLVMValueRef LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { +#if LLVM_VERSION_GE(12, 0) + Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src)); + I->setHasNoNaNs(NoNaN); + return wrap(I); +#else return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN)); +#endif } extern "C" LLVMValueRef @@ -1713,3 +1741,54 @@ extern "C" LLVMValueRef LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS))); } + +// This struct contains all necessary info about a symbol exported from a DLL. +// At the moment, it's just the symbol's name, but we use a separate struct to +// make it easier to add other information like ordinal later. +struct LLVMRustCOFFShortExport { + const char* name; +}; + +// 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) { + ConvertedExports.push_back(llvm::object::COFFShortExport{ + Exports[i].name, // Name + std::string{}, // ExtName + std::string{}, // SymbolName + std::string{}, // AliasTarget + 0, // Ordinal + false, // 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; + llvm::raw_string_ostream stream(errorString); + stream << Error; + stream.flush(); + LLVMRustSetLastError(errorString.c_str()); + return LLVMRustResult::Failure; + } else { + return LLVMRustResult::Success; + } +} |
