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 EmitObj: 41 return std::make_unique<BackendAction>( 42 BackendAction::BackendActionTy::Backend_EmitObj); 43 case EmitAssembly: 44 return std::make_unique<BackendAction>( 45 BackendAction::BackendActionTy::Backend_EmitAssembly); 46 case DebugUnparse: 47 return std::make_unique<DebugUnparseAction>(); 48 case DebugUnparseNoSema: 49 return std::make_unique<DebugUnparseNoSemaAction>(); 50 case DebugUnparseWithSymbols: 51 return std::make_unique<DebugUnparseWithSymbolsAction>(); 52 case DebugDumpSymbols: 53 return std::make_unique<DebugDumpSymbolsAction>(); 54 case DebugDumpParseTree: 55 return std::make_unique<DebugDumpParseTreeAction>(); 56 case DebugDumpPFT: 57 return std::make_unique<DebugDumpPFTAction>(); 58 case DebugDumpParseTreeNoSema: 59 return std::make_unique<DebugDumpParseTreeNoSemaAction>(); 60 case DebugDumpAll: 61 return std::make_unique<DebugDumpAllAction>(); 62 case DebugDumpProvenance: 63 return std::make_unique<DebugDumpProvenanceAction>(); 64 case DebugDumpParsingLog: 65 return std::make_unique<DebugDumpParsingLogAction>(); 66 case DebugMeasureParseTree: 67 return std::make_unique<DebugMeasureParseTreeAction>(); 68 case DebugPreFIRTree: 69 return std::make_unique<DebugPreFIRTreeAction>(); 70 case GetDefinition: 71 return std::make_unique<GetDefinitionAction>(); 72 case GetSymbolsSources: 73 return std::make_unique<GetSymbolsSourcesAction>(); 74 case InitOnly: 75 return std::make_unique<InitOnlyAction>(); 76 case PluginAction: { 77 for (const FrontendPluginRegistry::entry &plugin : 78 FrontendPluginRegistry::entries()) { 79 if (plugin.getName() == ci.frontendOpts().ActionName) { 80 std::unique_ptr<PluginParseTreeAction> p(plugin.instantiate()); 81 return std::move(p); 82 } 83 } 84 unsigned diagID = ci.diagnostics().getCustomDiagID( 85 clang::DiagnosticsEngine::Error, "unable to find plugin '%0'"); 86 ci.diagnostics().Report(diagID) << ci.frontendOpts().ActionName; 87 return nullptr; 88 } 89 default: 90 break; 91 // TODO: 92 // case ParserSyntaxOnly: 93 // case EmitLLVM: 94 // case EmitLLVMOnly: 95 // case EmitCodeGenOnly: 96 // (...) 97 } 98 return 0; 99 } 100 101 std::unique_ptr<FrontendAction> CreateFrontendAction(CompilerInstance &ci) { 102 // Create the underlying action. 103 std::unique_ptr<FrontendAction> act = CreateFrontendBaseAction(ci); 104 if (!act) 105 return nullptr; 106 107 return act; 108 } 109 110 bool ExecuteCompilerInvocation(CompilerInstance *flang) { 111 // Honor -help. 112 if (flang->frontendOpts().showHelp) { 113 clang::driver::getDriverOptTable().printHelp(llvm::outs(), 114 "flang-new -fc1 [options] file...", "LLVM 'Flang' Compiler", 115 /*Include=*/clang::driver::options::FC1Option, 116 /*Exclude=*/llvm::opt::DriverFlag::HelpHidden, 117 /*ShowAllAliases=*/false); 118 return true; 119 } 120 121 // Honor -version. 122 if (flang->frontendOpts().showVersion) { 123 llvm::cl::PrintVersionMessage(); 124 return true; 125 } 126 127 // Load any requested plugins. 128 for (const std::string &Path : flang->frontendOpts().plugins) { 129 std::string Error; 130 if (llvm::sys::DynamicLibrary::LoadLibraryPermanently( 131 Path.c_str(), &Error)) { 132 unsigned diagID = flang->diagnostics().getCustomDiagID( 133 clang::DiagnosticsEngine::Error, "unable to load plugin '%0': '%1'"); 134 flang->diagnostics().Report(diagID) << Path << Error; 135 } 136 } 137 138 // If there were errors in processing arguments, don't do anything else. 139 if (flang->diagnostics().hasErrorOccurred()) { 140 return false; 141 } 142 143 // Create and execute the frontend action. 144 std::unique_ptr<FrontendAction> act(CreateFrontendAction(*flang)); 145 if (!act) 146 return false; 147 148 bool success = flang->ExecuteAction(*act); 149 return success; 150 } 151 152 } // namespace Fortran::frontend 153