xref: /llvm-project/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp (revision 06eb10dadfaeaadc5d0d95d38bea4bfb5253e077)
1257b2971SCaroline Concatto //===--- ExecuteCompilerInvocation.cpp ------------------------------------===//
2257b2971SCaroline Concatto //
3257b2971SCaroline Concatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4257b2971SCaroline Concatto // See https://llvm.org/LICENSE.txt for license information.
5257b2971SCaroline Concatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6257b2971SCaroline Concatto //
7257b2971SCaroline Concatto //===----------------------------------------------------------------------===//
8257b2971SCaroline Concatto //
9257b2971SCaroline Concatto // This file holds ExecuteCompilerInvocation(). It is split into its own file to
10257b2971SCaroline Concatto // minimize the impact of pulling in essentially everything else in Flang.
11257b2971SCaroline Concatto //
12257b2971SCaroline Concatto //===----------------------------------------------------------------------===//
131e462fafSAndrzej Warzynski //
141e462fafSAndrzej Warzynski // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
151e462fafSAndrzej Warzynski //
161e462fafSAndrzej Warzynski //===----------------------------------------------------------------------===//
17257b2971SCaroline Concatto 
18257b2971SCaroline Concatto #include "flang/Frontend/CompilerInstance.h"
194c5906cfSCaroline Concatto #include "flang/Frontend/FrontendActions.h"
20f52fc591SStuart Ellis #include "flang/Frontend/FrontendPluginRegistry.h"
211e462fafSAndrzej Warzynski 
2279a5ff45SPrabhdeep Singh Soni #include "mlir/IR/AsmState.h"
231e462fafSAndrzej Warzynski #include "mlir/IR/MLIRContext.h"
241e462fafSAndrzej Warzynski #include "mlir/Pass/PassManager.h"
2591989c67SVictor Kingi #include "clang/Basic/DiagnosticFrontend.h"
26257b2971SCaroline Concatto #include "clang/Driver/Options.h"
27257b2971SCaroline Concatto #include "llvm/Option/OptTable.h"
284c5906cfSCaroline Concatto #include "llvm/Option/Option.h"
294c5906cfSCaroline Concatto #include "llvm/Support/BuryPointer.h"
30257b2971SCaroline Concatto #include "llvm/Support/CommandLine.h"
31257b2971SCaroline Concatto 
32257b2971SCaroline Concatto namespace Fortran::frontend {
334c5906cfSCaroline Concatto 
341e462fafSAndrzej Warzynski static std::unique_ptr<FrontendAction>
351e462fafSAndrzej Warzynski createFrontendAction(CompilerInstance &ci) {
364c5906cfSCaroline Concatto 
371e462fafSAndrzej Warzynski   switch (ci.getFrontendOpts().programAction) {
384c5906cfSCaroline Concatto   case InputOutputTest:
394c5906cfSCaroline Concatto     return std::make_unique<InputOutputTestAction>();
40d28de0d7SCaroline Concatto   case PrintPreprocessedInput:
41d28de0d7SCaroline Concatto     return std::make_unique<PrintPreprocessedAction>();
427d246cb1SAndrzej Warzynski   case ParseSyntaxOnly:
437d246cb1SAndrzej Warzynski     return std::make_unique<ParseSyntaxOnlyAction>();
4439ecf9d8STom Eccles   case EmitFIR:
4539ecf9d8STom Eccles     return std::make_unique<EmitFIRAction>();
4639ecf9d8STom Eccles   case EmitHLFIR:
4739ecf9d8STom Eccles     return std::make_unique<EmitHLFIRAction>();
48e993b20cSAndrzej Warzynski   case EmitLLVM:
49e993b20cSAndrzej Warzynski     return std::make_unique<EmitLLVMAction>();
50dd56939aSAndrzej Warzynski   case EmitLLVMBitcode:
51dd56939aSAndrzej Warzynski     return std::make_unique<EmitLLVMBitcodeAction>();
52e5cdb6c5SAndrzej Warzynski   case EmitObj:
53bb177edcSAndrzej Warzynski     return std::make_unique<EmitObjAction>();
5438101b4eSAndrzej Warzynski   case EmitAssembly:
55bb177edcSAndrzej Warzynski     return std::make_unique<EmitAssemblyAction>();
5696d229c9SAndrzej Warzynski   case DebugUnparse:
5796d229c9SAndrzej Warzynski     return std::make_unique<DebugUnparseAction>();
58e81b3401SAndrzej Warzynski   case DebugUnparseNoSema:
59e81b3401SAndrzej Warzynski     return std::make_unique<DebugUnparseNoSemaAction>();
6096d229c9SAndrzej Warzynski   case DebugUnparseWithSymbols:
6196d229c9SAndrzej Warzynski     return std::make_unique<DebugUnparseWithSymbolsAction>();
62e00a3ccfSPeter Klausler   case DebugUnparseWithModules:
63e00a3ccfSPeter Klausler     return std::make_unique<DebugUnparseWithModulesAction>();
644bd08dabSFaris Rehman   case DebugDumpSymbols:
654bd08dabSFaris Rehman     return std::make_unique<DebugDumpSymbolsAction>();
664bd08dabSFaris Rehman   case DebugDumpParseTree:
674bd08dabSFaris Rehman     return std::make_unique<DebugDumpParseTreeAction>();
688321579bSAndrzej Warzynski   case DebugDumpPFT:
698321579bSAndrzej Warzynski     return std::make_unique<DebugDumpPFTAction>();
70e81b3401SAndrzej Warzynski   case DebugDumpParseTreeNoSema:
71e81b3401SAndrzej Warzynski     return std::make_unique<DebugDumpParseTreeNoSemaAction>();
72a6be6e31SAndrzej Warzynski   case DebugDumpAll:
73a6be6e31SAndrzej Warzynski     return std::make_unique<DebugDumpAllAction>();
744bd08dabSFaris Rehman   case DebugDumpProvenance:
754bd08dabSFaris Rehman     return std::make_unique<DebugDumpProvenanceAction>();
76523d7bc6SAndrzej Warzynski   case DebugDumpParsingLog:
77523d7bc6SAndrzej Warzynski     return std::make_unique<DebugDumpParsingLogAction>();
78529f7181SFaris Rehman   case DebugMeasureParseTree:
79529f7181SFaris Rehman     return std::make_unique<DebugMeasureParseTreeAction>();
80529f7181SFaris Rehman   case DebugPreFIRTree:
81529f7181SFaris Rehman     return std::make_unique<DebugPreFIRTreeAction>();
82dc256a44SAndrzej Warzynski   case GetDefinition:
83dc256a44SAndrzej Warzynski     return std::make_unique<GetDefinitionAction>();
84eefda605SAndrzej Warzynski   case GetSymbolsSources:
85eefda605SAndrzej Warzynski     return std::make_unique<GetSymbolsSourcesAction>();
86e1da3297SStuart Ellis   case InitOnly:
87e1da3297SStuart Ellis     return std::make_unique<InitOnlyAction>();
88f52fc591SStuart Ellis   case PluginAction: {
89f52fc591SStuart Ellis     for (const FrontendPluginRegistry::entry &plugin :
90f52fc591SStuart Ellis          FrontendPluginRegistry::entries()) {
911e462fafSAndrzej Warzynski       if (plugin.getName() == ci.getFrontendOpts().actionName) {
92f52fc591SStuart Ellis         std::unique_ptr<PluginParseTreeAction> p(plugin.instantiate());
93f52fc591SStuart Ellis         return std::move(p);
94f52fc591SStuart Ellis       }
95f52fc591SStuart Ellis     }
961e462fafSAndrzej Warzynski     unsigned diagID = ci.getDiagnostics().getCustomDiagID(
97f52fc591SStuart Ellis         clang::DiagnosticsEngine::Error, "unable to find plugin '%0'");
981e462fafSAndrzej Warzynski     ci.getDiagnostics().Report(diagID) << ci.getFrontendOpts().actionName;
99f52fc591SStuart Ellis     return nullptr;
100f52fc591SStuart Ellis   }
1014c5906cfSCaroline Concatto   }
1024c5906cfSCaroline Concatto 
103d902dd01SAndrzej Warzynski   llvm_unreachable("Invalid program action!");
1044c5906cfSCaroline Concatto }
105f52fc591SStuart Ellis 
106e8af2473SVictor Kingi static void emitUnknownDiagWarning(clang::DiagnosticsEngine &diags,
107e8af2473SVictor Kingi                                    clang::diag::Flavor flavor,
108e8af2473SVictor Kingi                                    llvm::StringRef prefix,
109e8af2473SVictor Kingi                                    llvm::StringRef opt) {
110e8af2473SVictor Kingi   llvm::StringRef suggestion =
111e8af2473SVictor Kingi       clang::DiagnosticIDs::getNearestOption(flavor, opt);
112e8af2473SVictor Kingi   diags.Report(clang::diag::warn_unknown_diag_option)
113e8af2473SVictor Kingi       << (flavor == clang::diag::Flavor::WarningOrError ? 0 : 1)
114e8af2473SVictor Kingi       << (prefix.str() += std::string(opt)) << !suggestion.empty()
115e8af2473SVictor Kingi       << (prefix.str() += std::string(suggestion));
116e8af2473SVictor Kingi }
117e8af2473SVictor Kingi 
11891989c67SVictor Kingi // Remarks are ignored by default in Diagnostic.td, hence, we have to
11991989c67SVictor Kingi // enable them here before execution. Clang follows same idea using
12091989c67SVictor Kingi // ProcessWarningOptions in Warnings.cpp
12191989c67SVictor Kingi // This function is also responsible for emitting early warnings for
12291989c67SVictor Kingi // invalid -R options.
12391989c67SVictor Kingi static void
12491989c67SVictor Kingi updateDiagEngineForOptRemarks(clang::DiagnosticsEngine &diagsEng,
12591989c67SVictor Kingi                               const clang::DiagnosticOptions &opts) {
12691989c67SVictor Kingi   llvm::SmallVector<clang::diag::kind, 10> diags;
12791989c67SVictor Kingi   const llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs =
12891989c67SVictor Kingi       diagsEng.getDiagnosticIDs();
12991989c67SVictor Kingi 
13091989c67SVictor Kingi   for (unsigned i = 0; i < opts.Remarks.size(); i++) {
13191989c67SVictor Kingi     llvm::StringRef remarkOpt = opts.Remarks[i];
13291989c67SVictor Kingi     const auto flavor = clang::diag::Flavor::Remark;
13391989c67SVictor Kingi 
13491989c67SVictor Kingi     // Check to see if this opt starts with "no-", if so, this is a
13591989c67SVictor Kingi     // negative form of the option.
13611efcceaSKazu Hirata     bool isPositive = !remarkOpt.starts_with("no-");
13791989c67SVictor Kingi     if (!isPositive)
13891989c67SVictor Kingi       remarkOpt = remarkOpt.substr(3);
13991989c67SVictor Kingi 
140e8af2473SVictor Kingi     // Verify that this is a valid optimization remarks option
141e8af2473SVictor Kingi     if (diagIDs->getDiagnosticsInGroup(flavor, remarkOpt, diags)) {
142e8af2473SVictor Kingi       emitUnknownDiagWarning(diagsEng, flavor, isPositive ? "-R" : "-Rno-",
143e8af2473SVictor Kingi                              remarkOpt);
144e8af2473SVictor Kingi       return;
145e8af2473SVictor Kingi     }
146e8af2473SVictor Kingi 
14791989c67SVictor Kingi     diagsEng.setSeverityForGroup(flavor, remarkOpt,
14891989c67SVictor Kingi                                  isPositive ? clang::diag::Severity::Remark
14991989c67SVictor Kingi                                             : clang::diag::Severity::Ignored);
15091989c67SVictor Kingi   }
15191989c67SVictor Kingi }
15291989c67SVictor Kingi 
1531e462fafSAndrzej Warzynski bool executeCompilerInvocation(CompilerInstance *flang) {
154257b2971SCaroline Concatto   // Honor -help.
1551e462fafSAndrzej Warzynski   if (flang->getFrontendOpts().showHelp) {
15674d5c3c0SPeter Steinfeld     clang::driver::getDriverOptTable().printHelp(
157*06eb10daSBrad Richardson         llvm::outs(), "flang -fc1 [options] file...", "LLVM 'Flang' Compiler",
1589478f661SJustin Bogner         /*ShowHidden=*/false, /*ShowAllAliases=*/false,
1599478f661SJustin Bogner         llvm::opt::Visibility(clang::driver::options::FC1Option));
160257b2971SCaroline Concatto     return true;
161257b2971SCaroline Concatto   }
162257b2971SCaroline Concatto 
163257b2971SCaroline Concatto   // Honor -version.
1641e462fafSAndrzej Warzynski   if (flang->getFrontendOpts().showVersion) {
165257b2971SCaroline Concatto     llvm::cl::PrintVersionMessage();
166257b2971SCaroline Concatto     return true;
167257b2971SCaroline Concatto   }
168257b2971SCaroline Concatto 
169f52fc591SStuart Ellis   // Load any requested plugins.
1701e462fafSAndrzej Warzynski   for (const std::string &path : flang->getFrontendOpts().plugins) {
1711e462fafSAndrzej Warzynski     std::string error;
1721e462fafSAndrzej Warzynski     if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(path.c_str(),
1731e462fafSAndrzej Warzynski                                                           &error)) {
1741e462fafSAndrzej Warzynski       unsigned diagID = flang->getDiagnostics().getCustomDiagID(
175f52fc591SStuart Ellis           clang::DiagnosticsEngine::Error, "unable to load plugin '%0': '%1'");
1761e462fafSAndrzej Warzynski       flang->getDiagnostics().Report(diagID) << path << error;
177f52fc591SStuart Ellis     }
178f52fc591SStuart Ellis   }
179f52fc591SStuart Ellis 
180a7c08bcfSAndrzej Warzynski   // Honor -mllvm. This should happen AFTER plugins have been loaded!
1811e462fafSAndrzej Warzynski   if (!flang->getFrontendOpts().llvmArgs.empty()) {
1821e462fafSAndrzej Warzynski     unsigned numArgs = flang->getFrontendOpts().llvmArgs.size();
183a7c08bcfSAndrzej Warzynski     auto args = std::make_unique<const char *[]>(numArgs + 2);
184a7c08bcfSAndrzej Warzynski     args[0] = "flang (LLVM option parsing)";
185a7c08bcfSAndrzej Warzynski 
186a7c08bcfSAndrzej Warzynski     for (unsigned i = 0; i != numArgs; ++i)
1871e462fafSAndrzej Warzynski       args[i + 1] = flang->getFrontendOpts().llvmArgs[i].c_str();
188a7c08bcfSAndrzej Warzynski 
189a7c08bcfSAndrzej Warzynski     args[numArgs + 1] = nullptr;
190a7c08bcfSAndrzej Warzynski     llvm::cl::ParseCommandLineOptions(numArgs + 1, args.get());
191a7c08bcfSAndrzej Warzynski   }
192a7c08bcfSAndrzej Warzynski 
1936c93e1d3SAndrzej Warzynski   // Honor -mmlir. This should happen AFTER plugins have been loaded!
1941e462fafSAndrzej Warzynski   if (!flang->getFrontendOpts().mlirArgs.empty()) {
1956c93e1d3SAndrzej Warzynski     mlir::registerMLIRContextCLOptions();
1966c93e1d3SAndrzej Warzynski     mlir::registerPassManagerCLOptions();
19779a5ff45SPrabhdeep Singh Soni     mlir::registerAsmPrinterCLOptions();
1981e462fafSAndrzej Warzynski     unsigned numArgs = flang->getFrontendOpts().mlirArgs.size();
1996c93e1d3SAndrzej Warzynski     auto args = std::make_unique<const char *[]>(numArgs + 2);
2006c93e1d3SAndrzej Warzynski     args[0] = "flang (MLIR option parsing)";
2016c93e1d3SAndrzej Warzynski 
2026c93e1d3SAndrzej Warzynski     for (unsigned i = 0; i != numArgs; ++i)
2031e462fafSAndrzej Warzynski       args[i + 1] = flang->getFrontendOpts().mlirArgs[i].c_str();
2046c93e1d3SAndrzej Warzynski 
2056c93e1d3SAndrzej Warzynski     args[numArgs + 1] = nullptr;
2066c93e1d3SAndrzej Warzynski     llvm::cl::ParseCommandLineOptions(numArgs + 1, args.get());
2076c93e1d3SAndrzej Warzynski   }
2086c93e1d3SAndrzej Warzynski 
209f52fc591SStuart Ellis   // If there were errors in processing arguments, don't do anything else.
2101e462fafSAndrzej Warzynski   if (flang->getDiagnostics().hasErrorOccurred()) {
211f52fc591SStuart Ellis     return false;
212f52fc591SStuart Ellis   }
213f52fc591SStuart Ellis 
21491989c67SVictor Kingi   updateDiagEngineForOptRemarks(flang->getDiagnostics(),
21591989c67SVictor Kingi                                 flang->getDiagnosticOpts());
21691989c67SVictor Kingi 
2174c5906cfSCaroline Concatto   // Create and execute the frontend action.
2181e462fafSAndrzej Warzynski   std::unique_ptr<FrontendAction> act(createFrontendAction(*flang));
2194c5906cfSCaroline Concatto   if (!act)
2204c5906cfSCaroline Concatto     return false;
2214c5906cfSCaroline Concatto 
2221e462fafSAndrzej Warzynski   bool success = flang->executeAction(*act);
2234c5906cfSCaroline Concatto   return success;
224257b2971SCaroline Concatto }
225257b2971SCaroline Concatto 
226257b2971SCaroline Concatto } // namespace Fortran::frontend
227