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