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 Flang.
11 //
12 //===----------------------------------------------------------------------===//
13 //
14 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
15 //
16 //===----------------------------------------------------------------------===//
17
18 #include "flang/Frontend/CompilerInstance.h"
19 #include "flang/Frontend/FrontendActions.h"
20 #include "flang/Frontend/FrontendPluginRegistry.h"
21
22 #include "mlir/IR/MLIRContext.h"
23 #include "mlir/Pass/PassManager.h"
24 #include "clang/Driver/Options.h"
25 #include "llvm/Option/OptTable.h"
26 #include "llvm/Option/Option.h"
27 #include "llvm/Support/BuryPointer.h"
28 #include "llvm/Support/CommandLine.h"
29
30 namespace Fortran::frontend {
31
32 static std::unique_ptr<FrontendAction>
createFrontendAction(CompilerInstance & ci)33 createFrontendAction(CompilerInstance &ci) {
34
35 switch (ci.getFrontendOpts().programAction) {
36 case InputOutputTest:
37 return std::make_unique<InputOutputTestAction>();
38 case PrintPreprocessedInput:
39 return std::make_unique<PrintPreprocessedAction>();
40 case ParseSyntaxOnly:
41 return std::make_unique<ParseSyntaxOnlyAction>();
42 case EmitMLIR:
43 return std::make_unique<EmitMLIRAction>();
44 case EmitLLVM:
45 return std::make_unique<EmitLLVMAction>();
46 case EmitLLVMBitcode:
47 return std::make_unique<EmitLLVMBitcodeAction>();
48 case EmitObj:
49 return std::make_unique<EmitObjAction>();
50 case EmitAssembly:
51 return std::make_unique<EmitAssemblyAction>();
52 case DebugUnparse:
53 return std::make_unique<DebugUnparseAction>();
54 case DebugUnparseNoSema:
55 return std::make_unique<DebugUnparseNoSemaAction>();
56 case DebugUnparseWithSymbols:
57 return std::make_unique<DebugUnparseWithSymbolsAction>();
58 case DebugDumpSymbols:
59 return std::make_unique<DebugDumpSymbolsAction>();
60 case DebugDumpParseTree:
61 return std::make_unique<DebugDumpParseTreeAction>();
62 case DebugDumpPFT:
63 return std::make_unique<DebugDumpPFTAction>();
64 case DebugDumpParseTreeNoSema:
65 return std::make_unique<DebugDumpParseTreeNoSemaAction>();
66 case DebugDumpAll:
67 return std::make_unique<DebugDumpAllAction>();
68 case DebugDumpProvenance:
69 return std::make_unique<DebugDumpProvenanceAction>();
70 case DebugDumpParsingLog:
71 return std::make_unique<DebugDumpParsingLogAction>();
72 case DebugMeasureParseTree:
73 return std::make_unique<DebugMeasureParseTreeAction>();
74 case DebugPreFIRTree:
75 return std::make_unique<DebugPreFIRTreeAction>();
76 case GetDefinition:
77 return std::make_unique<GetDefinitionAction>();
78 case GetSymbolsSources:
79 return std::make_unique<GetSymbolsSourcesAction>();
80 case InitOnly:
81 return std::make_unique<InitOnlyAction>();
82 case PluginAction: {
83 for (const FrontendPluginRegistry::entry &plugin :
84 FrontendPluginRegistry::entries()) {
85 if (plugin.getName() == ci.getFrontendOpts().actionName) {
86 std::unique_ptr<PluginParseTreeAction> p(plugin.instantiate());
87 return std::move(p);
88 }
89 }
90 unsigned diagID = ci.getDiagnostics().getCustomDiagID(
91 clang::DiagnosticsEngine::Error, "unable to find plugin '%0'");
92 ci.getDiagnostics().Report(diagID) << ci.getFrontendOpts().actionName;
93 return nullptr;
94 }
95 }
96
97 llvm_unreachable("Invalid program action!");
98 }
99
executeCompilerInvocation(CompilerInstance * flang)100 bool executeCompilerInvocation(CompilerInstance *flang) {
101 // Honor -help.
102 if (flang->getFrontendOpts().showHelp) {
103 clang::driver::getDriverOptTable().printHelp(llvm::outs(),
104 "flang-new -fc1 [options] file...", "LLVM 'Flang' Compiler",
105 /*Include=*/clang::driver::options::FC1Option,
106 /*Exclude=*/llvm::opt::DriverFlag::HelpHidden,
107 /*ShowAllAliases=*/false);
108 return true;
109 }
110
111 // Honor -version.
112 if (flang->getFrontendOpts().showVersion) {
113 llvm::cl::PrintVersionMessage();
114 return true;
115 }
116
117 // Load any requested plugins.
118 for (const std::string &path : flang->getFrontendOpts().plugins) {
119 std::string error;
120 if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(path.c_str(),
121 &error)) {
122 unsigned diagID = flang->getDiagnostics().getCustomDiagID(
123 clang::DiagnosticsEngine::Error, "unable to load plugin '%0': '%1'");
124 flang->getDiagnostics().Report(diagID) << path << error;
125 }
126 }
127
128 // Honor -mllvm. This should happen AFTER plugins have been loaded!
129 if (!flang->getFrontendOpts().llvmArgs.empty()) {
130 unsigned numArgs = flang->getFrontendOpts().llvmArgs.size();
131 auto args = std::make_unique<const char *[]>(numArgs + 2);
132 args[0] = "flang (LLVM option parsing)";
133
134 for (unsigned i = 0; i != numArgs; ++i)
135 args[i + 1] = flang->getFrontendOpts().llvmArgs[i].c_str();
136
137 args[numArgs + 1] = nullptr;
138 llvm::cl::ParseCommandLineOptions(numArgs + 1, args.get());
139 }
140
141 // Honor -mmlir. This should happen AFTER plugins have been loaded!
142 if (!flang->getFrontendOpts().mlirArgs.empty()) {
143 mlir::registerMLIRContextCLOptions();
144 mlir::registerPassManagerCLOptions();
145 unsigned numArgs = flang->getFrontendOpts().mlirArgs.size();
146 auto args = std::make_unique<const char *[]>(numArgs + 2);
147 args[0] = "flang (MLIR option parsing)";
148
149 for (unsigned i = 0; i != numArgs; ++i)
150 args[i + 1] = flang->getFrontendOpts().mlirArgs[i].c_str();
151
152 args[numArgs + 1] = nullptr;
153 llvm::cl::ParseCommandLineOptions(numArgs + 1, args.get());
154 }
155
156 // If there were errors in processing arguments, don't do anything else.
157 if (flang->getDiagnostics().hasErrorOccurred()) {
158 return false;
159 }
160
161 // Honor color diagnostics.
162 flang->getDiagnosticOpts().ShowColors = flang->getFrontendOpts().showColors;
163
164 // Create and execute the frontend action.
165 std::unique_ptr<FrontendAction> act(createFrontendAction(*flang));
166 if (!act)
167 return false;
168
169 bool success = flang->executeAction(*act);
170 return success;
171 }
172
173 } // namespace Fortran::frontend
174