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