diff options
| author | Josh Stone <jistone@redhat.com> | 2020-06-25 18:52:41 -0700 | 
|---|---|---|
| committer | Josh Stone <jistone@redhat.com> | 2020-06-25 18:52:41 -0700 | 
| commit | 49f6166ef7825a39e980c0ba0904073379bb01e6 (patch) | |
| tree | 302a88b9f8b6a34b9c37031ffd364cccd655fee9 /src/rustllvm/PassWrapper.cpp | |
| parent | 50fc24d8a172a853b5dfe40702d6550e3b8562ba (diff) | |
| download | rust-49f6166ef7825a39e980c0ba0904073379bb01e6.tar.gz rust-49f6166ef7825a39e980c0ba0904073379bb01e6.zip | |
Prepare for LLVM 11
Diffstat (limited to 'src/rustllvm/PassWrapper.cpp')
| -rw-r--r-- | src/rustllvm/PassWrapper.cpp | 119 | 
1 files changed, 93 insertions, 26 deletions
| diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 9bc111c26ba..41b14714842 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -49,8 +49,10 @@ typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) +#if LLVM_VERSION_LT(11, 0) DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder, LLVMPassManagerBuilderRef) +#endif extern "C" void LLVMInitializePasses() { PassRegistry &Registry = *PassRegistry::getPassRegistry(); @@ -343,17 +345,17 @@ enum class LLVMRustPassBuilderOptLevel { static PassBuilder::OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) { switch (Level) { case LLVMRustPassBuilderOptLevel::O0: - return PassBuilder::O0; + return PassBuilder::OptimizationLevel::O0; case LLVMRustPassBuilderOptLevel::O1: - return PassBuilder::O1; + return PassBuilder::OptimizationLevel::O1; case LLVMRustPassBuilderOptLevel::O2: - return PassBuilder::O2; + return PassBuilder::OptimizationLevel::O2; case LLVMRustPassBuilderOptLevel::O3: - return PassBuilder::O3; + return PassBuilder::OptimizationLevel::O3; case LLVMRustPassBuilderOptLevel::Os: - return PassBuilder::Os; + return PassBuilder::OptimizationLevel::Os; case LLVMRustPassBuilderOptLevel::Oz: - return PassBuilder::Oz; + return PassBuilder::OptimizationLevel::Oz; default: report_fatal_error("Bad PassBuilderOptLevel."); } @@ -796,8 +798,13 @@ 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; +#if LLVM_VERSION_GE(11, 0) + std::vector<std::function<void(ModulePassManager &, PassBuilder::OptimizationLevel)>> + OptimizerLastEPCallbacks; +#else std::vector<std::function<void(FunctionPassManager &, PassBuilder::OptimizationLevel)>> OptimizerLastEPCallbacks; +#endif if (VerifyIR) { PipelineStartEPCallbacks.push_back([VerifyIR](ModulePassManager &MPM) { @@ -811,6 +818,14 @@ LLVMRustOptimizeWithNewPassManager( SanitizerOptions->SanitizeMemoryTrackOrigins, SanitizerOptions->SanitizeMemoryRecover, /*CompileKernel=*/false); +#if LLVM_VERSION_GE(11, 0) + OptimizerLastEPCallbacks.push_back( + [Options](ModulePassManager &MPM, PassBuilder::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)); @@ -821,9 +836,18 @@ LLVMRustOptimizeWithNewPassManager( FPM.addPass(MemorySanitizerPass(Options)); } ); +#endif } if (SanitizerOptions->SanitizeThread) { +#if LLVM_VERSION_GE(11, 0) + OptimizerLastEPCallbacks.push_back( + [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { + MPM.addPass(ThreadSanitizerPass()); + MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); + } + ); +#else #if LLVM_VERSION_GE(10, 0) PipelineStartEPCallbacks.push_back([](ModulePassManager &MPM) { MPM.addPass(ThreadSanitizerPass()); @@ -834,9 +858,22 @@ LLVMRustOptimizeWithNewPassManager( FPM.addPass(ThreadSanitizerPass()); } ); +#endif } if (SanitizerOptions->SanitizeAddress) { +#if LLVM_VERSION_GE(11, 0) + OptimizerLastEPCallbacks.push_back( + [SanitizerOptions](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { + MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>()); + MPM.addPass(ModuleAddressSanitizerPass( + /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); + MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass( + /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover, + /*UseAfterScope=*/true))); + } + ); +#else PipelineStartEPCallbacks.push_back([&](ModulePassManager &MPM) { MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>()); }); @@ -853,21 +890,27 @@ LLVMRustOptimizeWithNewPassManager( /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); } ); +#endif } } ModulePassManager MPM(DebugPassManager); if (!NoPrepopulatePasses) { - if (OptLevel == PassBuilder::O0) { + if (OptLevel == PassBuilder::OptimizationLevel::O0) { for (const auto &C : PipelineStartEPCallbacks) C(MPM); +#if LLVM_VERSION_GE(11, 0) + for (const auto &C : OptimizerLastEPCallbacks) + C(MPM, OptLevel); +#else if (!OptimizerLastEPCallbacks.empty()) { FunctionPassManager FPM(DebugPassManager); for (const auto &C : OptimizerLastEPCallbacks) C(FPM, OptLevel); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } +#endif MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers)); @@ -892,12 +935,17 @@ LLVMRustOptimizeWithNewPassManager( break; case LLVMRustOptStage::PreLinkThinLTO: MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager); +#if LLVM_VERSION_GE(11, 0) + for (const auto &C : OptimizerLastEPCallbacks) + C(MPM, OptLevel); +#else if (!OptimizerLastEPCallbacks.empty()) { FunctionPassManager FPM(DebugPassManager); for (const auto &C : OptimizerLastEPCallbacks) C(FPM, OptLevel); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } +#endif break; case LLVMRustOptStage::PreLinkFatLTO: MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager); @@ -994,10 +1042,10 @@ public: const Value *Value; if (const CallInst *CI = dyn_cast<CallInst>(I)) { Name = "call"; - Value = CI->getCalledValue(); + Value = CI->getCalledOperand(); } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) { Name = "invoke"; - Value = II->getCalledValue(); + Value = II->getCalledOperand(); } else { // Could demangle more operations, e. g. // `store %place, @function`. @@ -1335,10 +1383,33 @@ LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) { // `ProcessThinLTOModule` function. Here they're split up into separate steps // so rustc can save off the intermediate bytecode between each step. +#if LLVM_VERSION_GE(11, 0) +static bool +clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) { + // When linking an ELF shared object, dso_local should be dropped. We + // conservatively do this for -fpic. + bool ClearDSOLocalOnDeclarations = + TM.getTargetTriple().isOSBinFormatELF() && + TM.getRelocationModel() != Reloc::Static && + Mod.getPIELevel() == PIELevel::Default; + return ClearDSOLocalOnDeclarations; +} +#endif + extern "C" bool -LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { +LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M, + LLVMTargetMachineRef TM) { Module &Mod = *unwrap(M); - if (renameModuleForThinLTO(Mod, Data->Index)) { + TargetMachine &Target = *unwrap(TM); + +#if LLVM_VERSION_GE(11, 0) + bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target); + bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal); +#else + bool error = renameModuleForThinLTO(Mod, Data->Index); +#endif + + if (error) { LLVMRustSetLastError("renameModuleForThinLTO failed"); return false; } @@ -1362,8 +1433,10 @@ LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef } extern "C" bool -LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { +LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M, + LLVMTargetMachineRef TM) { Module &Mod = *unwrap(M); + TargetMachine &Target = *unwrap(TM); const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier()); auto Loader = [&](StringRef Identifier) { @@ -1399,7 +1472,12 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { return MOrErr; }; +#if LLVM_VERSION_GE(11, 0) + bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target); + FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal); +#else FunctionImporter Importer(Data->Index, Loader); +#endif Expected<bool> Result = Importer.importFunctions(Mod, ImportList); if (!Result) { LLVMRustSetLastError(toString(Result.takeError()).c_str()); @@ -1558,22 +1636,11 @@ LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { } // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and - // process it recursively. Note that we specifically iterate over instructions - // to ensure we feed everything into it. + // 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); - for (Function &F : M->functions()) { - for (auto &FI : F) { - for (Instruction &BI : FI) { - if (auto Loc = BI.getDebugLoc()) - Finder.processLocation(*M, Loc); - if (auto DVI = dyn_cast<DbgValueInst>(&BI)) - Finder.processValue(*M, DVI); - if (auto DDI = dyn_cast<DbgDeclareInst>(&BI)) - Finder.processDeclare(*M, DDI); - } - } - } // After we've found all our debuginfo, rewrite all subprograms to point to // the same `DICompileUnit`. | 
