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/MIRParser/MIRParser.h" |
20 | #include "llvm/CodeGen/MIRPrinter.h" |
21 | #include "llvm/CodeGen/MachineModuleInfo.h" |
22 | #include "llvm/CodeGen/MachinePassManager.h" |
23 | #include "llvm/CodeGen/TargetPassConfig.h" |
24 | #include "llvm/IR/DiagnosticInfo.h" |
25 | #include "llvm/IR/DiagnosticPrinter.h" |
26 | #include "llvm/IR/IRPrintingPasses.h" |
27 | #include "llvm/IR/LLVMContext.h" |
28 | #include "llvm/IR/Module.h" |
29 | #include "llvm/IR/PassManager.h" |
30 | #include "llvm/IR/Verifier.h" |
31 | #include "llvm/IRReader/IRReader.h" |
32 | #include "llvm/Passes/CodeGenPassBuilder.h" // TODO: Include pass headers properly. |
33 | #include "llvm/Passes/PassBuilder.h" |
34 | #include "llvm/Passes/StandardInstrumentations.h" |
35 | #include "llvm/Support/CommandLine.h" |
36 | #include "llvm/Support/Debug.h" |
37 | #include "llvm/Support/Error.h" |
38 | #include "llvm/Support/ErrorHandling.h" |
39 | #include "llvm/Support/FormattedStream.h" |
40 | #include "llvm/Support/ToolOutputFile.h" |
41 | #include "llvm/Support/WithColor.h" |
42 | #include "llvm/Target/CGPassBuilderOption.h" |
43 | #include "llvm/Target/TargetMachine.h" |
44 | #include "llvm/Target/TargetOptions.h" |
45 | #include "llvm/Transforms/Scalar/LoopPassManager.h" |
46 | #include "llvm/Transforms/Utils/Cloning.h" |
47 | |
48 | namespace llvm { |
49 | extern cl::opt<bool> PrintPipelinePasses; |
50 | } // namespace llvm |
51 | |
52 | using namespace llvm; |
53 | |
54 | static cl::opt<std::string> |
55 | RegAlloc("regalloc-npm" , |
56 | cl::desc("Register allocator to use for new pass manager" ), |
57 | cl::Hidden, cl::init(Val: "default" )); |
58 | |
59 | static cl::opt<bool> |
60 | DebugPM("debug-pass-manager" , cl::Hidden, |
61 | cl::desc("Print pass management debugging information" )); |
62 | |
63 | bool 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 * = 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 | |
89 | static llvm::ExitOnError ExitOnErr; |
90 | |
91 | int 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, bool NoVerify, StringRef PassPipeline, |
96 | CodeGenFileType FileType) { |
97 | |
98 | if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) { |
99 | WithColor::warning(OS&: errs(), Prefix: Arg0) |
100 | << "--passes cannot be used with " |
101 | << TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n" ; |
102 | return 1; |
103 | } |
104 | |
105 | LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target); |
106 | |
107 | raw_pwrite_stream *OS = &Out->os(); |
108 | |
109 | // Fetch options from TargetPassConfig |
110 | CGPassBuilderOption Opt = getCGPassBuilderOption(); |
111 | Opt.DisableVerify = NoVerify; |
112 | Opt.DebugPM = DebugPM; |
113 | Opt.RegAlloc = RegAlloc; |
114 | |
115 | MachineModuleInfo MMI(&LLVMTM); |
116 | |
117 | PassInstrumentationCallbacks PIC; |
118 | StandardInstrumentations SI(Context, Opt.DebugPM, !NoVerify); |
119 | registerCodeGenCallback(PIC, LLVMTM); |
120 | |
121 | MachineFunctionAnalysisManager MFAM; |
122 | LoopAnalysisManager LAM; |
123 | FunctionAnalysisManager FAM; |
124 | CGSCCAnalysisManager CGAM; |
125 | ModuleAnalysisManager MAM; |
126 | PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC); |
127 | PB.registerModuleAnalyses(MAM); |
128 | PB.registerCGSCCAnalyses(CGAM); |
129 | PB.registerFunctionAnalyses(FAM); |
130 | PB.registerLoopAnalyses(LAM); |
131 | PB.registerMachineFunctionAnalyses(MFAM); |
132 | PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, MFAM: &MFAM); |
133 | SI.registerCallbacks(PIC, MAM: &MAM); |
134 | |
135 | FAM.registerPass(PassBuilder: [&] { return TargetLibraryAnalysis(TLII); }); |
136 | MAM.registerPass(PassBuilder: [&] { return MachineModuleAnalysis(MMI); }); |
137 | |
138 | ModulePassManager MPM; |
139 | FunctionPassManager FPM; |
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 | FPM.addPass(Pass: createFunctionToMachineFunctionPassAdaptor(Pass: std::move(MFPM))); |
156 | MPM.addPass(Pass: createModuleToFunctionPassAdaptor(Pass: std::move(FPM))); |
157 | |
158 | if (MIR->parseMachineFunctions(M&: *M, MAM)) |
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 | |