//===- 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/TargetLibraryInfo.h" #include "llvm/CodeGen/CommandFlags.h" #include "llvm/CodeGen/MIRParser/MIRParser.h" #include "llvm/CodeGen/MIRPrinter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachinePassManager.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/CodeGenPassBuilder.h" // TODO: Include pass headers properly. #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/StandardInstrumentations.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/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Transforms/Scalar/LoopPassManager.h" #include "llvm/Transforms/Utils/Cloning.h" namespace llvm { extern cl::opt PrintPipelinePasses; } // namespace llvm using namespace llvm; static cl::opt RegAlloc("regalloc-npm", cl::desc("Register allocator to use for new pass manager"), cl::Hidden, cl::init("default")); static cl::opt 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(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(&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 M, std::unique_ptr MIR, std::unique_ptr Target, std::unique_ptr Out, std::unique_ptr DwoOut, LLVMContext &Context, const TargetLibraryInfoImpl &TLII, bool NoVerify, StringRef PassPipeline, CodeGenFileType FileType) { if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) { WithColor::warning(errs(), Arg0) << "--passes cannot be used with " << TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n"; return 1; } LLVMTargetMachine &LLVMTM = static_cast(*Target); raw_pwrite_stream *OS = &Out->os(); // Fetch options from TargetPassConfig CGPassBuilderOption Opt = getCGPassBuilderOption(); Opt.DisableVerify = NoVerify; Opt.DebugPM = DebugPM; Opt.RegAlloc = RegAlloc; MachineModuleInfo MMI(&LLVMTM); PassInstrumentationCallbacks PIC; StandardInstrumentations SI(Context, Opt.DebugPM, !NoVerify); registerCodeGenCallback(PIC, LLVMTM); MachineFunctionAnalysisManager MFAM; LoopAnalysisManager LAM; FunctionAnalysisManager FAM; CGSCCAnalysisManager CGAM; ModuleAnalysisManager MAM; PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC); 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); FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); MAM.registerPass([&] { return MachineModuleAnalysis(MMI); }); ModulePassManager MPM; FunctionPassManager FPM; if (!PassPipeline.empty()) { // Construct a custom pass pipeline that starts after instruction // selection. if (!MIR) { WithColor::warning(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; MFPM.addPass(PrintMIRPass(*OS)); FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); if (MIR->parseMachineFunctions(*M, MAM)) return 1; } else { ExitOnErr(LLVMTM.buildCodeGenPipeline( MPM, *OS, DwoOut ? &DwoOut->os() : nullptr, FileType, Opt, &PIC)); } 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; }); outs() << PipelineStr << '\n'; return 0; } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); MPM.run(*M, MAM); if (Context.getDiagHandlerPtr()->HasErrors) exit(1); // Declare success. Out->keep(); if (DwoOut) DwoOut->keep(); return 0; }