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