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/TargetLibraryInfo.h" |
18 | #include "llvm/CodeGen/CommandFlags.h" |
19 | #include "llvm/CodeGen/FreeMachineFunction.h" |
20 | #include "llvm/CodeGen/MIRParser/MIRParser.h" |
21 | #include "llvm/CodeGen/MIRPrinter.h" |
22 | #include "llvm/CodeGen/MachineModuleInfo.h" |
23 | #include "llvm/CodeGen/MachinePassManager.h" |
24 | #include "llvm/CodeGen/TargetPassConfig.h" |
25 | #include "llvm/IR/DiagnosticInfo.h" |
26 | #include "llvm/IR/DiagnosticPrinter.h" |
27 | #include "llvm/IR/IRPrintingPasses.h" |
28 | #include "llvm/IR/LLVMContext.h" |
29 | #include "llvm/IR/Module.h" |
30 | #include "llvm/IR/PassManager.h" |
31 | #include "llvm/IR/Verifier.h" |
32 | #include "llvm/IRReader/IRReader.h" |
33 | #include "llvm/Passes/CodeGenPassBuilder.h" // TODO: Include pass headers properly. |
34 | #include "llvm/Passes/PassBuilder.h" |
35 | #include "llvm/Passes/StandardInstrumentations.h" |
36 | #include "llvm/Support/CommandLine.h" |
37 | #include "llvm/Support/Debug.h" |
38 | #include "llvm/Support/Error.h" |
39 | #include "llvm/Support/ErrorHandling.h" |
40 | #include "llvm/Support/FormattedStream.h" |
41 | #include "llvm/Support/ToolOutputFile.h" |
42 | #include "llvm/Support/WithColor.h" |
43 | #include "llvm/Target/CGPassBuilderOption.h" |
44 | #include "llvm/Target/TargetMachine.h" |
45 | #include "llvm/Target/TargetOptions.h" |
46 | #include "llvm/Transforms/Scalar/LoopPassManager.h" |
47 | #include "llvm/Transforms/Utils/Cloning.h" |
48 | |
49 | namespace llvm { |
50 | extern cl::opt<bool> PrintPipelinePasses; |
51 | } // namespace llvm |
52 | |
53 | using namespace llvm; |
54 | |
55 | static cl::opt<std::string> |
56 | RegAlloc("regalloc-npm" , |
57 | cl::desc("Register allocator to use for new pass manager" ), |
58 | cl::Hidden, cl::init(Val: "default" )); |
59 | |
60 | static cl::opt<bool> |
61 | DebugPM("debug-pass-manager" , cl::Hidden, |
62 | cl::desc("Print pass management debugging information" )); |
63 | |
64 | bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { |
65 | DiagnosticHandler::handleDiagnostics(DI); |
66 | if (DI.getKind() == llvm::DK_SrcMgr) { |
67 | const auto &DISM = cast<DiagnosticInfoSrcMgr>(Val: DI); |
68 | const SMDiagnostic &SMD = DISM.getSMDiag(); |
69 | |
70 | SMD.print(ProgName: nullptr, S&: errs()); |
71 | |
72 | // For testing purposes, we print the LocCookie here. |
73 | if (DISM.isInlineAsmDiag() && DISM.getLocCookie()) |
74 | WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n" ; |
75 | |
76 | return true; |
77 | } |
78 | |
79 | if (auto * = dyn_cast<DiagnosticInfoOptimizationBase>(Val: &DI)) |
80 | if (!Remark->isEnabled()) |
81 | return true; |
82 | |
83 | DiagnosticPrinterRawOStream DP(errs()); |
84 | errs() << LLVMContext::getDiagnosticMessagePrefix(Severity: DI.getSeverity()) << ": " ; |
85 | DI.print(DP); |
86 | errs() << "\n" ; |
87 | return true; |
88 | } |
89 | |
90 | static llvm::ExitOnError ExitOnErr; |
91 | |
92 | int llvm::compileModuleWithNewPM( |
93 | StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR, |
94 | std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out, |
95 | std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context, |
96 | const TargetLibraryInfoImpl &TLII, bool NoVerify, StringRef PassPipeline, |
97 | CodeGenFileType FileType) { |
98 | |
99 | if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) { |
100 | WithColor::warning(OS&: errs(), Prefix: Arg0) |
101 | << "--passes cannot be used with " |
102 | << TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n" ; |
103 | return 1; |
104 | } |
105 | |
106 | LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target); |
107 | |
108 | raw_pwrite_stream *OS = &Out->os(); |
109 | |
110 | // Fetch options from TargetPassConfig |
111 | CGPassBuilderOption Opt = getCGPassBuilderOption(); |
112 | Opt.DisableVerify = NoVerify; |
113 | Opt.DebugPM = DebugPM; |
114 | Opt.RegAlloc = RegAlloc; |
115 | |
116 | MachineModuleInfo MMI(&LLVMTM); |
117 | |
118 | PassInstrumentationCallbacks PIC; |
119 | StandardInstrumentations SI(Context, Opt.DebugPM); |
120 | SI.registerCallbacks(PIC); |
121 | registerCodeGenCallback(PIC, LLVMTM); |
122 | |
123 | LoopAnalysisManager LAM; |
124 | FunctionAnalysisManager FAM; |
125 | CGSCCAnalysisManager CGAM; |
126 | ModuleAnalysisManager MAM; |
127 | MachineFunctionAnalysisManager MFAM; |
128 | PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC); |
129 | PB.registerModuleAnalyses(MAM); |
130 | PB.registerCGSCCAnalyses(CGAM); |
131 | PB.registerFunctionAnalyses(FAM); |
132 | PB.registerLoopAnalyses(LAM); |
133 | PB.registerMachineFunctionAnalyses(MFAM); |
134 | PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, MFAM: &MFAM); |
135 | |
136 | FAM.registerPass(PassBuilder: [&] { return TargetLibraryAnalysis(TLII); }); |
137 | MAM.registerPass(PassBuilder: [&] { return MachineModuleAnalysis(MMI); }); |
138 | |
139 | ModulePassManager MPM; |
140 | |
141 | if (!PassPipeline.empty()) { |
142 | // Construct a custom pass pipeline that starts after instruction |
143 | // selection. |
144 | |
145 | if (!MIR) { |
146 | WithColor::warning(OS&: errs(), Prefix: Arg0) << "-passes is for .mir file only.\n" ; |
147 | return 1; |
148 | } |
149 | |
150 | // FIXME: verify that there are no IR passes. |
151 | ExitOnErr(PB.parsePassPipeline(MPM, PipelineText: PassPipeline)); |
152 | MPM.addPass(Pass: PrintMIRPreparePass(*OS)); |
153 | MachineFunctionPassManager MFPM; |
154 | MFPM.addPass(Pass: PrintMIRPass(*OS)); |
155 | MFPM.addPass(Pass: FreeMachineFunctionPass()); |
156 | MPM.addPass(Pass: createModuleToMachineFunctionPassAdaptor(Pass: std::move(MFPM))); |
157 | |
158 | if (MIR->parseMachineFunctions(M&: *M, MMI)) |
159 | return 1; |
160 | } else { |
161 | ExitOnErr(LLVMTM.buildCodeGenPipeline( |
162 | MPM, *OS, DwoOut ? &DwoOut->os() : nullptr, FileType, Opt, &PIC)); |
163 | } |
164 | |
165 | if (PrintPipelinePasses) { |
166 | std::string PipelineStr; |
167 | raw_string_ostream OS(PipelineStr); |
168 | MPM.printPipeline(OS, MapClassName2PassName: [&PIC](StringRef ClassName) { |
169 | auto PassName = PIC.getPassNameForClassName(ClassName); |
170 | return PassName.empty() ? ClassName : PassName; |
171 | }); |
172 | outs() << PipelineStr << '\n'; |
173 | return 0; |
174 | } |
175 | |
176 | // Before executing passes, print the final values of the LLVM options. |
177 | cl::PrintOptionValues(); |
178 | |
179 | MPM.run(IR&: *M, AM&: MAM); |
180 | |
181 | if (Context.getDiagHandlerPtr()->HasErrors) |
182 | exit(status: 1); |
183 | |
184 | // Declare success. |
185 | Out->keep(); |
186 | if (DwoOut) |
187 | DwoOut->keep(); |
188 | |
189 | return 0; |
190 | } |
191 | |