1 | //===--- ExecuteCompilerInvocation.cpp ------------------------------------===// |
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 | // |
9 | // This file holds ExecuteCompilerInvocation(). It is split into its own file to |
10 | // minimize the impact of pulling in essentially everything else in Clang. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "clang/CodeGen/CodeGenAction.h" |
15 | #include "clang/Config/config.h" |
16 | #include "clang/Driver/Options.h" |
17 | #include "clang/ExtractAPI/FrontendActions.h" |
18 | #include "clang/Frontend/CompilerInstance.h" |
19 | #include "clang/Frontend/CompilerInvocation.h" |
20 | #include "clang/Frontend/FrontendActions.h" |
21 | #include "clang/Frontend/FrontendDiagnostic.h" |
22 | #include "clang/Frontend/FrontendPluginRegistry.h" |
23 | #include "clang/Frontend/Utils.h" |
24 | #include "clang/FrontendTool/Utils.h" |
25 | #include "clang/Rewrite/Frontend/FrontendActions.h" |
26 | #include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h" |
27 | #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" |
28 | #include "llvm/Option/OptTable.h" |
29 | #include "llvm/Option/Option.h" |
30 | #include "llvm/Support/BuryPointer.h" |
31 | #include "llvm/Support/DynamicLibrary.h" |
32 | #include "llvm/Support/ErrorHandling.h" |
33 | |
34 | #if CLANG_ENABLE_CIR |
35 | #include "mlir/IR/AsmState.h" |
36 | #include "mlir/IR/MLIRContext.h" |
37 | #include "mlir/Pass/PassManager.h" |
38 | #include "clang/CIR/Dialect/Passes.h" |
39 | #include "clang/CIR/FrontendAction/CIRGenAction.h" |
40 | #endif |
41 | |
42 | using namespace clang; |
43 | using namespace llvm::opt; |
44 | |
45 | namespace clang { |
46 | |
47 | static std::unique_ptr<FrontendAction> |
48 | CreateFrontendBaseAction(CompilerInstance &CI) { |
49 | using namespace clang::frontend; |
50 | StringRef Action("unknown" ); |
51 | (void)Action; |
52 | |
53 | unsigned UseCIR = CI.getFrontendOpts().UseClangIRPipeline; |
54 | frontend::ActionKind Act = CI.getFrontendOpts().ProgramAction; |
55 | bool EmitsCIR = Act == EmitCIR; |
56 | |
57 | if (!UseCIR && EmitsCIR) |
58 | llvm::report_fatal_error(reason: "-emit-cir and only valid when using -fclangir" ); |
59 | |
60 | switch (CI.getFrontendOpts().ProgramAction) { |
61 | case ASTDeclList: return std::make_unique<ASTDeclListAction>(); |
62 | case ASTDump: return std::make_unique<ASTDumpAction>(); |
63 | case ASTPrint: return std::make_unique<ASTPrintAction>(); |
64 | case ASTView: return std::make_unique<ASTViewAction>(); |
65 | case DumpCompilerOptions: |
66 | return std::make_unique<DumpCompilerOptionsAction>(); |
67 | case DumpRawTokens: return std::make_unique<DumpRawTokensAction>(); |
68 | case DumpTokens: return std::make_unique<DumpTokensAction>(); |
69 | case EmitAssembly: |
70 | #if CLANG_ENABLE_CIR |
71 | if (UseCIR) |
72 | return std::make_unique<cir::EmitAssemblyAction>(); |
73 | #endif |
74 | return std::make_unique<EmitAssemblyAction>(); |
75 | case EmitBC: |
76 | #if CLANG_ENABLE_CIR |
77 | if (UseCIR) |
78 | return std::make_unique<cir::EmitBCAction>(); |
79 | #endif |
80 | return std::make_unique<EmitBCAction>(); |
81 | case EmitCIR: |
82 | #if CLANG_ENABLE_CIR |
83 | return std::make_unique<cir::EmitCIRAction>(); |
84 | #else |
85 | llvm_unreachable("CIR suppport not built into clang" ); |
86 | #endif |
87 | case EmitHTML: return std::make_unique<HTMLPrintAction>(); |
88 | case EmitLLVM: { |
89 | #if CLANG_ENABLE_CIR |
90 | if (UseCIR) |
91 | return std::make_unique<cir::EmitLLVMAction>(); |
92 | #endif |
93 | return std::make_unique<EmitLLVMAction>(); |
94 | } |
95 | case EmitLLVMOnly: return std::make_unique<EmitLLVMOnlyAction>(); |
96 | case EmitCodeGenOnly: return std::make_unique<EmitCodeGenOnlyAction>(); |
97 | case EmitObj: |
98 | #if CLANG_ENABLE_CIR |
99 | if (UseCIR) |
100 | return std::make_unique<cir::EmitObjAction>(); |
101 | #endif |
102 | return std::make_unique<EmitObjAction>(); |
103 | case ExtractAPI: |
104 | return std::make_unique<ExtractAPIAction>(); |
105 | case FixIt: return std::make_unique<FixItAction>(); |
106 | case GenerateModule: |
107 | return std::make_unique<GenerateModuleFromModuleMapAction>(); |
108 | case GenerateModuleInterface: |
109 | return std::make_unique<GenerateModuleInterfaceAction>(); |
110 | case GenerateReducedModuleInterface: |
111 | return std::make_unique<GenerateReducedModuleInterfaceAction>(); |
112 | case GenerateHeaderUnit: |
113 | return std::make_unique<GenerateHeaderUnitAction>(); |
114 | case GeneratePCH: return std::make_unique<GeneratePCHAction>(); |
115 | case GenerateInterfaceStubs: |
116 | return std::make_unique<GenerateInterfaceStubsAction>(); |
117 | case InitOnly: return std::make_unique<InitOnlyAction>(); |
118 | case ParseSyntaxOnly: return std::make_unique<SyntaxOnlyAction>(); |
119 | case ModuleFileInfo: return std::make_unique<DumpModuleInfoAction>(); |
120 | case VerifyPCH: return std::make_unique<VerifyPCHAction>(); |
121 | case TemplightDump: return std::make_unique<TemplightDumpAction>(); |
122 | |
123 | case PluginAction: { |
124 | for (const FrontendPluginRegistry::entry &Plugin : |
125 | FrontendPluginRegistry::entries()) { |
126 | if (Plugin.getName() == CI.getFrontendOpts().ActionName) { |
127 | std::unique_ptr<PluginASTAction> P(Plugin.instantiate()); |
128 | if ((P->getActionType() != PluginASTAction::ReplaceAction && |
129 | P->getActionType() != PluginASTAction::CmdlineAfterMainAction) || |
130 | !P->ParseArgs( |
131 | CI, |
132 | arg: CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())])) |
133 | return nullptr; |
134 | return std::move(P); |
135 | } |
136 | } |
137 | |
138 | CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) |
139 | << CI.getFrontendOpts().ActionName; |
140 | return nullptr; |
141 | } |
142 | |
143 | case PrintPreamble: return std::make_unique<PrintPreambleAction>(); |
144 | case PrintPreprocessedInput: { |
145 | if (CI.getPreprocessorOutputOpts().RewriteIncludes || |
146 | CI.getPreprocessorOutputOpts().RewriteImports) |
147 | return std::make_unique<RewriteIncludesAction>(); |
148 | return std::make_unique<PrintPreprocessedAction>(); |
149 | } |
150 | |
151 | case RewriteMacros: return std::make_unique<RewriteMacrosAction>(); |
152 | case RewriteTest: return std::make_unique<RewriteTestAction>(); |
153 | #if CLANG_ENABLE_OBJC_REWRITER |
154 | case RewriteObjC: return std::make_unique<RewriteObjCAction>(); |
155 | #else |
156 | case RewriteObjC: Action = "RewriteObjC" ; break; |
157 | #endif |
158 | #if CLANG_ENABLE_STATIC_ANALYZER |
159 | case RunAnalysis: return std::make_unique<ento::AnalysisAction>(); |
160 | #else |
161 | case RunAnalysis: Action = "RunAnalysis" ; break; |
162 | #endif |
163 | case RunPreprocessorOnly: return std::make_unique<PreprocessOnlyAction>(); |
164 | case PrintDependencyDirectivesSourceMinimizerOutput: |
165 | return std::make_unique<PrintDependencyDirectivesSourceMinimizerAction>(); |
166 | } |
167 | |
168 | #if !CLANG_ENABLE_STATIC_ANALYZER || !CLANG_ENABLE_OBJC_REWRITER |
169 | CI.getDiagnostics().Report(diag::err_fe_action_not_available) << Action; |
170 | return 0; |
171 | #else |
172 | llvm_unreachable("Invalid program action!" ); |
173 | #endif |
174 | } |
175 | |
176 | std::unique_ptr<FrontendAction> |
177 | CreateFrontendAction(CompilerInstance &CI) { |
178 | // Create the underlying action. |
179 | std::unique_ptr<FrontendAction> Act = CreateFrontendBaseAction(CI); |
180 | if (!Act) |
181 | return nullptr; |
182 | |
183 | const FrontendOptions &FEOpts = CI.getFrontendOpts(); |
184 | |
185 | if (FEOpts.FixAndRecompile) { |
186 | Act = std::make_unique<FixItRecompile>(args: std::move(Act)); |
187 | } |
188 | |
189 | // Wrap the base FE action in an extract api action to generate |
190 | // symbol graph as a biproduct of compilation (enabled with |
191 | // --emit-symbol-graph option) |
192 | if (FEOpts.EmitSymbolGraph) { |
193 | if (FEOpts.SymbolGraphOutputDir.empty()) { |
194 | CI.getDiagnostics().Report(diag::warn_missing_symbol_graph_dir); |
195 | CI.getFrontendOpts().SymbolGraphOutputDir = "." ; |
196 | } |
197 | CI.getCodeGenOpts().ClearASTBeforeBackend = false; |
198 | Act = std::make_unique<WrappingExtractAPIAction>(args: std::move(Act)); |
199 | } |
200 | |
201 | // If there are any AST files to merge, create a frontend action |
202 | // adaptor to perform the merge. |
203 | if (!FEOpts.ASTMergeFiles.empty()) |
204 | Act = std::make_unique<ASTMergeAction>(args: std::move(Act), |
205 | args: FEOpts.ASTMergeFiles); |
206 | |
207 | return Act; |
208 | } |
209 | |
210 | bool ExecuteCompilerInvocation(CompilerInstance *Clang) { |
211 | // Honor -help. |
212 | if (Clang->getFrontendOpts().ShowHelp) { |
213 | driver::getDriverOptTable().printHelp( |
214 | OS&: llvm::outs(), Usage: "clang -cc1 [options] file..." , |
215 | Title: "LLVM 'Clang' Compiler: http://clang.llvm.org" , |
216 | /*ShowHidden=*/false, /*ShowAllAliases=*/false, |
217 | VisibilityMask: llvm::opt::Visibility(driver::options::CC1Option)); |
218 | return true; |
219 | } |
220 | |
221 | // Honor -version. |
222 | // |
223 | // FIXME: Use a better -version message? |
224 | if (Clang->getFrontendOpts().ShowVersion) { |
225 | llvm::cl::PrintVersionMessage(); |
226 | return true; |
227 | } |
228 | |
229 | Clang->LoadRequestedPlugins(); |
230 | |
231 | // Honor -mllvm. |
232 | // |
233 | // FIXME: Remove this, one day. |
234 | // This should happen AFTER plugins have been loaded! |
235 | if (!Clang->getFrontendOpts().LLVMArgs.empty()) { |
236 | unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); |
237 | auto Args = std::make_unique<const char*[]>(num: NumArgs + 2); |
238 | Args[0] = "clang (LLVM option parsing)" ; |
239 | for (unsigned i = 0; i != NumArgs; ++i) |
240 | Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); |
241 | Args[NumArgs + 1] = nullptr; |
242 | llvm::cl::ParseCommandLineOptions(argc: NumArgs + 1, argv: Args.get()); |
243 | } |
244 | |
245 | #if CLANG_ENABLE_STATIC_ANALYZER |
246 | // These should happen AFTER plugins have been loaded! |
247 | |
248 | AnalyzerOptions &AnOpts = Clang->getAnalyzerOpts(); |
249 | |
250 | // Honor -analyzer-checker-help and -analyzer-checker-help-hidden. |
251 | if (AnOpts.ShowCheckerHelp || AnOpts.ShowCheckerHelpAlpha || |
252 | AnOpts.ShowCheckerHelpDeveloper) { |
253 | ento::printCheckerHelp(OS&: llvm::outs(), CI&: *Clang); |
254 | return true; |
255 | } |
256 | |
257 | // Honor -analyzer-checker-option-help. |
258 | if (AnOpts.ShowCheckerOptionList || AnOpts.ShowCheckerOptionAlphaList || |
259 | AnOpts.ShowCheckerOptionDeveloperList) { |
260 | ento::printCheckerConfigList(OS&: llvm::outs(), CI&: *Clang); |
261 | return true; |
262 | } |
263 | |
264 | // Honor -analyzer-list-enabled-checkers. |
265 | if (AnOpts.ShowEnabledCheckerList) { |
266 | ento::printEnabledCheckerList(OS&: llvm::outs(), CI&: *Clang); |
267 | return true; |
268 | } |
269 | |
270 | // Honor -analyzer-config-help. |
271 | if (AnOpts.ShowConfigOptionsList) { |
272 | ento::printAnalyzerConfigList(OS&: llvm::outs()); |
273 | return true; |
274 | } |
275 | #endif |
276 | |
277 | #if CLANG_ENABLE_CIR |
278 | if (!Clang->getFrontendOpts().MLIRArgs.empty()) { |
279 | mlir::registerCIRPasses(); |
280 | mlir::registerMLIRContextCLOptions(); |
281 | mlir::registerPassManagerCLOptions(); |
282 | mlir::registerAsmPrinterCLOptions(); |
283 | unsigned NumArgs = Clang->getFrontendOpts().MLIRArgs.size(); |
284 | auto Args = std::make_unique<const char *[]>(NumArgs + 2); |
285 | Args[0] = "clang (MLIR option parsing)" ; |
286 | for (unsigned i = 0; i != NumArgs; ++i) |
287 | Args[i + 1] = Clang->getFrontendOpts().MLIRArgs[i].c_str(); |
288 | Args[NumArgs + 1] = nullptr; |
289 | llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get()); |
290 | } |
291 | #endif |
292 | |
293 | // If there were errors in processing arguments, don't do anything else. |
294 | if (Clang->getDiagnostics().hasErrorOccurred()) |
295 | return false; |
296 | // Create and execute the frontend action. |
297 | std::unique_ptr<FrontendAction> Act(CreateFrontendAction(CI&: *Clang)); |
298 | if (!Act) |
299 | return false; |
300 | bool Success = Clang->ExecuteAction(Act&: *Act); |
301 | if (Clang->getFrontendOpts().DisableFree) |
302 | llvm::BuryPointer(Ptr: std::move(Act)); |
303 | return Success; |
304 | } |
305 | |
306 | } // namespace clang |
307 | |