1//===- NewPMDriver.cpp - Driver for llc using new PM ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9///
10/// This file is just a split of the code that logically belongs in llc.cpp but
11/// that includes the new pass manager headers.
12///
13//===----------------------------------------------------------------------===//
14
15#include "NewPMDriver.h"
16#include "llvm/Analysis/CGSCCPassManager.h"
17#include "llvm/Analysis/RuntimeLibcallInfo.h"
18#include "llvm/Analysis/TargetLibraryInfo.h"
19#include "llvm/CodeGen/CommandFlags.h"
20#include "llvm/CodeGen/LibcallLoweringInfo.h"
21#include "llvm/CodeGen/MIRParser/MIRParser.h"
22#include "llvm/CodeGen/MIRPrinter.h"
23#include "llvm/CodeGen/MachineFunctionAnalysis.h"
24#include "llvm/CodeGen/MachineModuleInfo.h"
25#include "llvm/CodeGen/MachinePassManager.h"
26#include "llvm/CodeGen/MachineVerifier.h"
27#include "llvm/CodeGen/TargetPassConfig.h"
28#include "llvm/IR/DiagnosticInfo.h"
29#include "llvm/IR/DiagnosticPrinter.h"
30#include "llvm/IR/IRPrintingPasses.h"
31#include "llvm/IR/LLVMContext.h"
32#include "llvm/IR/Module.h"
33#include "llvm/IR/PassManager.h"
34#include "llvm/IR/Verifier.h"
35#include "llvm/IRReader/IRReader.h"
36#include "llvm/Passes/PassBuilder.h"
37#include "llvm/Passes/StandardInstrumentations.h"
38#include "llvm/Plugins/PassPlugin.h"
39#include "llvm/Support/CommandLine.h"
40#include "llvm/Support/Debug.h"
41#include "llvm/Support/Error.h"
42#include "llvm/Support/ErrorHandling.h"
43#include "llvm/Support/FormattedStream.h"
44#include "llvm/Support/ToolOutputFile.h"
45#include "llvm/Support/WithColor.h"
46#include "llvm/Target/CGPassBuilderOption.h"
47#include "llvm/Target/TargetMachine.h"
48#include "llvm/Target/TargetOptions.h"
49#include "llvm/Transforms/Scalar/LoopPassManager.h"
50#include "llvm/Transforms/Utils/Cloning.h"
51
52using namespace llvm;
53
54static cl::opt<RegAllocType, false, RegAllocTypeParser>
55 RegAlloc("regalloc-npm",
56 cl::desc("Register allocator to use for new pass manager"),
57 cl::Hidden, cl::init(Val: RegAllocType::Unset));
58
59static cl::opt<bool>
60 DebugPM("debug-pass-manager", cl::Hidden,
61 cl::desc("Print pass management debugging information"));
62
63bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) {
64 DiagnosticHandler::handleDiagnostics(DI);
65 if (DI.getKind() == llvm::DK_SrcMgr) {
66 const auto &DISM = cast<DiagnosticInfoSrcMgr>(Val: DI);
67 const SMDiagnostic &SMD = DISM.getSMDiag();
68
69 SMD.print(ProgName: nullptr, S&: errs());
70
71 // For testing purposes, we print the LocCookie here.
72 if (DISM.isInlineAsmDiag() && DISM.getLocCookie())
73 WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n";
74
75 return true;
76 }
77
78 if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(Val: &DI))
79 if (!Remark->isEnabled())
80 return true;
81
82 DiagnosticPrinterRawOStream DP(errs());
83 errs() << LLVMContext::getDiagnosticMessagePrefix(Severity: DI.getSeverity()) << ": ";
84 DI.print(DP);
85 errs() << "\n";
86 return true;
87}
88
89static llvm::ExitOnError ExitOnErr;
90
91int llvm::compileModuleWithNewPM(
92 StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR,
93 std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out,
94 std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context,
95 const TargetLibraryInfoImpl &TLII, VerifierKind VK, StringRef PassPipeline,
96 ArrayRef<PassPlugin> PassPlugins, CodeGenFileType FileType) {
97
98
99 raw_pwrite_stream *OS = &Out->os();
100
101 std::unique_ptr<buffer_ostream> BOS;
102 if (codegen::getFileType() != CodeGenFileType::AssemblyFile &&
103 !Out->os().supportsSeeking()) {
104 BOS = std::make_unique<buffer_ostream>(args&: Out->os());
105 OS = BOS.get();
106 }
107
108 // Fetch options from TargetPassConfig
109 CGPassBuilderOption Opt = getCGPassBuilderOption(TM: *Target);
110 Opt.DisableVerify = VK != VerifierKind::InputOutput;
111 if (VK == VerifierKind::EachPass)
112 Opt.VerifyMachineCode = MachineVerifierMode::Each;
113 Opt.DebugPM = DebugPM;
114 Opt.RegAlloc = RegAlloc;
115
116 MachineModuleInfo MMI(Target.get());
117
118 PassInstrumentationCallbacks PIC;
119 if (!PassPipeline.empty()) {
120 auto Info = ExitOnErr(TargetPassConfig::getStartStopInfo(TM: *Target, PIC));
121 if (Info.isLimited()) {
122 WithColor::error(OS&: errs(), Prefix: Arg0)
123 << "--passes cannot be used with " << Info.getLimitReason() << ".\n";
124 return 1;
125 }
126 }
127 StandardInstrumentations SI(Context, Opt.DebugPM,
128 VK == VerifierKind::EachPass);
129 registerCodeGenCallback(PIC, *Target);
130
131 MachineFunctionAnalysisManager MFAM;
132 LoopAnalysisManager LAM;
133 FunctionAnalysisManager FAM;
134 CGSCCAnalysisManager CGAM;
135 ModuleAnalysisManager MAM;
136
137 FAM.registerPass(PassBuilder: [&] { return TargetLibraryAnalysis(TLII); });
138
139 MAM.registerPass(PassBuilder: [&] {
140 const TargetOptions &Options = Target->Options;
141 return RuntimeLibraryAnalysis(Options.MCOptions.ABIName, Options.VecLib);
142 });
143
144 MAM.registerPass(PassBuilder: [&] { return MachineModuleAnalysis(MMI); });
145
146 PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC);
147 for (auto &PassPlugin : PassPlugins)
148 PassPlugin.registerPassBuilderCallbacks(PB);
149 PB.registerModuleAnalyses(MAM);
150 PB.registerCGSCCAnalyses(CGAM);
151 PB.registerFunctionAnalyses(FAM);
152 PB.registerLoopAnalyses(LAM);
153 PB.registerMachineFunctionAnalyses(MFAM);
154 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, MFAM: &MFAM);
155 SI.registerCallbacks(PIC, MAM: &MAM);
156
157 ModulePassManager MPM;
158 FunctionPassManager FPM;
159
160 if (!PassPipeline.empty()) {
161 // Construct a custom pass pipeline that starts after instruction
162 // selection.
163
164 if (!MIR) {
165 WithColor::error(OS&: errs(), Prefix: Arg0) << "-passes is for .mir file only.\n";
166 return 1;
167 }
168
169 // FIXME: verify that there are no IR passes.
170 ExitOnErr(PB.parsePassPipeline(MPM, PipelineText: PassPipeline));
171 MPM.addPass(Pass: PrintMIRPreparePass(*OS));
172 MachineFunctionPassManager MFPM;
173 if (Opt.VerifyMachineCode == MachineVerifierMode::End)
174 MFPM.addPass(Pass: MachineVerifierPass());
175 MFPM.addPass(Pass: PrintMIRPass(*OS));
176 FPM.addPass(Pass: createFunctionToMachineFunctionPassAdaptor(Pass: std::move(MFPM)));
177 MPM.addPass(Pass: createModuleToFunctionPassAdaptor(Pass: std::move(FPM)));
178
179 } else {
180 ExitOnErr(Target->buildCodeGenPipeline(
181 MPM, MAM, Out&: *OS, DwoOut: DwoOut ? &DwoOut->os() : nullptr, FileType, Opt,
182 Ctx&: MMI.getContext(), PIC: &PIC));
183 }
184
185 // If user only wants to print the pipeline, print it before parsing the MIR.
186 if (std::optional<PrintPipelinePassesFormat> Format =
187 PB.getPrintPipelinePasses()) {
188 std::string PipelineStr;
189 raw_string_ostream OS(PipelineStr);
190 MPM.printPipeline(OS, MapClassName2PassName: [&PIC](StringRef ClassName) {
191 auto PassName = PIC.getPassNameForClassName(ClassName);
192 return PassName.empty() ? ClassName : PassName;
193 });
194 printFormattedPipelinePasses(OS&: outs(), Pipeline: PipelineStr, Format: *Format);
195 outs() << '\n';
196 return 0;
197 }
198
199 if (MIR && MIR->parseMachineFunctions(M&: *M, MAM))
200 return 1;
201
202 // Before executing passes, print the final values of the LLVM options.
203 cl::PrintOptionValues();
204
205 MPM.run(IR&: *M, AM&: MAM);
206
207 if (Context.getDiagHandlerPtr()->HasErrors)
208 return 1;
209
210 // Declare success.
211 Out->keep();
212 if (DwoOut)
213 DwoOut->keep();
214
215 return 0;
216}
217