| //===- NewPMDriver.cpp - Driver for llc using new PM ----------------------===// | |
| // | |
| // 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 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| /// \file | |
| /// | |
| /// This file is just a split of the code that logically belongs in llc.cpp but | |
| /// that includes the new pass manager headers. | |
| /// | |
| //===----------------------------------------------------------------------===// | |
| #include "NewPMDriver.h" | |
| #include "llvm/Analysis/CGSCCPassManager.h" | |
| #include "llvm/Analysis/RuntimeLibcallInfo.h" | |
| #include "llvm/Analysis/TargetLibraryInfo.h" | |
| #include "llvm/CodeGen/CommandFlags.h" | |
| #include "llvm/CodeGen/LibcallLoweringInfo.h" | |
| #include "llvm/CodeGen/MIRParser/MIRParser.h" | |
| #include "llvm/CodeGen/MIRPrinter.h" | |
| #include "llvm/CodeGen/MachineFunctionAnalysis.h" | |
| #include "llvm/CodeGen/MachineModuleInfo.h" | |
| #include "llvm/CodeGen/MachinePassManager.h" | |
| #include "llvm/CodeGen/MachineVerifier.h" | |
| #include "llvm/CodeGen/TargetPassConfig.h" | |
| #include "llvm/IR/DiagnosticInfo.h" | |
| #include "llvm/IR/DiagnosticPrinter.h" | |
| #include "llvm/IR/IRPrintingPasses.h" | |
| #include "llvm/IR/LLVMContext.h" | |
| #include "llvm/IR/Module.h" | |
| #include "llvm/IR/PassManager.h" | |
| #include "llvm/IR/Verifier.h" | |
| #include "llvm/IRReader/IRReader.h" | |
| #include "llvm/Passes/PassBuilder.h" | |
| #include "llvm/Passes/StandardInstrumentations.h" | |
| #include "llvm/Plugins/PassPlugin.h" | |
| #include "llvm/Support/CommandLine.h" | |
| #include "llvm/Support/Debug.h" | |
| #include "llvm/Support/Error.h" | |
| #include "llvm/Support/ErrorHandling.h" | |
| #include "llvm/Support/FormattedStream.h" | |
| #include "llvm/Support/ToolOutputFile.h" | |
| #include "llvm/Support/WithColor.h" | |
| #include "llvm/Target/CGPassBuilderOption.h" | |
| #include "llvm/Target/TargetLoweringObjectFile.h" | |
| #include "llvm/Target/TargetMachine.h" | |
| #include "llvm/Target/TargetOptions.h" | |
| #include "llvm/Transforms/Scalar/LoopPassManager.h" | |
| #include "llvm/Transforms/Utils/Cloning.h" | |
| using namespace llvm; | |
| static cl::opt<RegAllocType, false, RegAllocTypeParser> | |
| RegAlloc("regalloc-npm", | |
| cl::desc("Register allocator to use for new pass manager"), | |
| cl::Hidden, cl::init(RegAllocType::Unset)); | |
| static cl::opt<bool> | |
| DebugPM("debug-pass-manager", cl::Hidden, | |
| cl::desc("Print pass management debugging information")); | |
| bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { | |
| DiagnosticHandler::handleDiagnostics(DI); | |
| if (DI.getKind() == llvm::DK_SrcMgr) { | |
| const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI); | |
| const SMDiagnostic &SMD = DISM.getSMDiag(); | |
| SMD.print(nullptr, errs()); | |
| // For testing purposes, we print the LocCookie here. | |
| if (DISM.isInlineAsmDiag() && DISM.getLocCookie()) | |
| WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n"; | |
| return true; | |
| } | |
| if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) | |
| if (!Remark->isEnabled()) | |
| return true; | |
| DiagnosticPrinterRawOStream DP(errs()); | |
| errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; | |
| DI.print(DP); | |
| errs() << "\n"; | |
| return true; | |
| } | |
| static llvm::ExitOnError ExitOnErr; | |
| int llvm::compileModuleWithNewPM( | |
| StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR, | |
| std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out, | |
| std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context, | |
| const TargetLibraryInfoImpl &TLII, VerifierKind VK, StringRef PassPipeline, | |
| ArrayRef<PassPlugin> PassPlugins, CodeGenFileType FileType) { | |
| if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) { | |
| WithColor::error(errs(), Arg0) | |
| << "--passes cannot be used with " | |
| << TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n"; | |
| return 1; | |
| } | |
| raw_pwrite_stream *OS = &Out->os(); | |
| std::unique_ptr<buffer_ostream> BOS; | |
| if (codegen::getFileType() != CodeGenFileType::AssemblyFile && | |
| !Out->os().supportsSeeking()) { | |
| BOS = std::make_unique<buffer_ostream>(Out->os()); | |
| OS = BOS.get(); | |
| } | |
| // Fetch options from TargetPassConfig | |
| CGPassBuilderOption Opt = getCGPassBuilderOption(); | |
| Opt.DisableVerify = VK != VerifierKind::InputOutput; | |
| Opt.DebugPM = DebugPM; | |
| Opt.RegAlloc = RegAlloc; | |
| MachineModuleInfo MMI(Target.get()); | |
| Target->getObjFileLowering()->Initialize(MMI.getContext(), *Target); | |
| PassInstrumentationCallbacks PIC; | |
| StandardInstrumentations SI(Context, Opt.DebugPM, | |
| VK == VerifierKind::EachPass); | |
| registerCodeGenCallback(PIC, *Target); | |
| MachineFunctionAnalysisManager MFAM; | |
| LoopAnalysisManager LAM; | |
| FunctionAnalysisManager FAM; | |
| CGSCCAnalysisManager CGAM; | |
| ModuleAnalysisManager MAM; | |
| FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); | |
| MAM.registerPass([&] { | |
| const TargetOptions &Options = Target->Options; | |
| return RuntimeLibraryAnalysis(Options.MCOptions.ABIName, Options.VecLib); | |
| }); | |
| MAM.registerPass([&] { return MachineModuleAnalysis(MMI); }); | |
| PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC); | |
| for (auto &PassPlugin : PassPlugins) | |
| PassPlugin.registerPassBuilderCallbacks(PB); | |
| PB.registerModuleAnalyses(MAM); | |
| PB.registerCGSCCAnalyses(CGAM); | |
| PB.registerFunctionAnalyses(FAM); | |
| PB.registerLoopAnalyses(LAM); | |
| PB.registerMachineFunctionAnalyses(MFAM); | |
| PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM); | |
| SI.registerCallbacks(PIC, &MAM); | |
| ModulePassManager MPM; | |
| FunctionPassManager FPM; | |
| if (!PassPipeline.empty()) { | |
| // Construct a custom pass pipeline that starts after instruction | |
| // selection. | |
| if (!MIR) { | |
| WithColor::error(errs(), Arg0) << "-passes is for .mir file only.\n"; | |
| return 1; | |
| } | |
| // FIXME: verify that there are no IR passes. | |
| ExitOnErr(PB.parsePassPipeline(MPM, PassPipeline)); | |
| MPM.addPass(PrintMIRPreparePass(*OS)); | |
| MachineFunctionPassManager MFPM; | |
| if (VK == VerifierKind::InputOutput) | |
| MFPM.addPass(MachineVerifierPass()); | |
| MFPM.addPass(PrintMIRPass(*OS)); | |
| FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))); | |
| MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); | |
| } else { | |
| ExitOnErr(Target->buildCodeGenPipeline( | |
| MPM, MAM, *OS, DwoOut ? &DwoOut->os() : nullptr, FileType, Opt, | |
| MMI.getContext(), &PIC)); | |
| } | |
| // If user only wants to print the pipeline, print it before parsing the MIR. | |
| if (PrintPipelinePasses) { | |
| std::string PipelineStr; | |
| raw_string_ostream OS(PipelineStr); | |
| MPM.printPipeline(OS, [&PIC](StringRef ClassName) { | |
| auto PassName = PIC.getPassNameForClassName(ClassName); | |
| return PassName.empty() ? ClassName : PassName; | |
| }); | |
| printFormattedPipelinePasses(outs(), PipelineStr, *PrintPipelinePasses); | |
| outs() << '\n'; | |
| return 0; | |
| } | |
| if (MIR && MIR->parseMachineFunctions(*M, MAM)) | |
| return 1; | |
| // Before executing passes, print the final values of the LLVM options. | |
| cl::PrintOptionValues(); | |
| MPM.run(*M, MAM); | |
| if (Context.getDiagHandlerPtr()->HasErrors) | |
| return 1; | |
| // Declare success. | |
| Out->keep(); | |
| if (DwoOut) | |
| DwoOut->keep(); | |
| return 0; | |
| } |