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