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/FrontendAction.h" 17 #include "flang/Frontend/FrontendPluginRegistry.h" 18 #include "clang/Driver/Options.h" 19 #include "llvm/Option/OptTable.h" 20 #include "llvm/Option/Option.h" 21 #include "llvm/Support/BuryPointer.h" 22 #include "llvm/Support/CommandLine.h" 23 #include "llvm/Support/DynamicLibrary.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 break; 35 case PrintPreprocessedInput: 36 return std::make_unique<PrintPreprocessedAction>(); 37 break; 38 case ParseSyntaxOnly: 39 return std::make_unique<ParseSyntaxOnlyAction>(); 40 case EmitObj: 41 return std::make_unique<EmitObjAction>(); 42 break; 43 case DebugUnparse: 44 return std::make_unique<DebugUnparseAction>(); 45 break; 46 case DebugUnparseNoSema: 47 return std::make_unique<DebugUnparseNoSemaAction>(); 48 break; 49 case DebugUnparseWithSymbols: 50 return std::make_unique<DebugUnparseWithSymbolsAction>(); 51 break; 52 case DebugDumpSymbols: 53 return std::make_unique<DebugDumpSymbolsAction>(); 54 break; 55 case DebugDumpParseTree: 56 return std::make_unique<DebugDumpParseTreeAction>(); 57 break; 58 case DebugDumpParseTreeNoSema: 59 return std::make_unique<DebugDumpParseTreeNoSemaAction>(); 60 break; 61 case DebugDumpAll: 62 return std::make_unique<DebugDumpAllAction>(); 63 break; 64 case DebugDumpProvenance: 65 return std::make_unique<DebugDumpProvenanceAction>(); 66 break; 67 case DebugDumpParsingLog: 68 return std::make_unique<DebugDumpParsingLogAction>(); 69 break; 70 case DebugMeasureParseTree: 71 return std::make_unique<DebugMeasureParseTreeAction>(); 72 break; 73 case DebugPreFIRTree: 74 return std::make_unique<DebugPreFIRTreeAction>(); 75 break; 76 case GetDefinition: 77 return std::make_unique<GetDefinitionAction>(); 78 break; 79 case GetSymbolsSources: 80 return std::make_unique<GetSymbolsSourcesAction>(); 81 break; 82 case InitOnly: 83 return std::make_unique<InitOnlyAction>(); 84 break; 85 case PluginAction: { 86 llvm::outs() << "---------- (case: PluginAction) --------\n"; 87 llvm::outs() << " Plugin Action: " << ci.frontendOpts().ActionName << "\n"; 88 for (const FrontendPluginRegistry::entry &plugin : FrontendPluginRegistry::entries()) { 89 llvm::outs() << " " << plugin.getName() << "\t-- " << plugin.getDesc() << "\n"; 90 if (plugin.getName() == ci.frontendOpts().ActionName) { 91 llvm::outs() << "We have found the plugin name!! :-)\n"; 92 std::unique_ptr<PluginParseTreeAction> P(plugin.instantiate()); 93 return std::move(P); 94 } 95 } 96 97 unsigned diagID = ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "unable to find plugin '%0'"); 98 ci.diagnostics().Report(diagID) << ci.frontendOpts().ActionName; 99 return nullptr; 100 } 101 default: 102 break; 103 // TODO: 104 // case RunPreprocessor: 105 // case ParserSyntaxOnly: 106 // case EmitLLVM: 107 // case EmitLLVMOnly: 108 // case EmitCodeGenOnly: 109 // (...) 110 } 111 return 0; 112 } 113 114 /// <<< TEMP Plugin Example 115 116 class HelloWorldFlangPlugin : public PluginParseTreeAction 117 { 118 protected: 119 void ExecuteAction() override { 120 llvm::outs() << "Hello World from your new plugin (Hello World)\n"; 121 } 122 }; 123 124 class HelloTwoFlangPlugin : public PluginParseTreeAction 125 { 126 protected: 127 void ExecuteAction() override { 128 llvm::outs() << "Hello World from your new plugin (Hello Two)\n"; 129 } 130 }; 131 132 /// <<<<< TEMP Plugin Example 133 134 std::unique_ptr<FrontendAction> CreateFrontendAction(CompilerInstance &ci) { 135 // Create the underlying action. 136 std::unique_ptr<FrontendAction> act = CreateFrontendBaseAction(ci); 137 if (!act) 138 return nullptr; 139 140 return act; 141 } 142 143 bool ExecuteCompilerInvocation(CompilerInstance *flang) { 144 // Honor -help. 145 if (flang->frontendOpts().showHelp_) { 146 clang::driver::getDriverOptTable().printHelp(llvm::outs(), 147 "flang-new -fc1 [options] file...", "LLVM 'Flang' Compiler", 148 /*Include=*/clang::driver::options::FC1Option, 149 /*Exclude=*/llvm::opt::DriverFlag::HelpHidden, 150 /*ShowAllAliases=*/false); 151 return true; 152 } 153 154 // Honor -version. 155 if (flang->frontendOpts().showVersion_) { 156 llvm::cl::PrintVersionMessage(); 157 return true; 158 } 159 160 llvm::outs() << "------ (ExecuteCompilerInvocation) -----\n"; 161 162 // Load any requested plugins. 163 for (const std::string &Path : flang->frontendOpts().plugins) { 164 llvm::outs() << " Load :: Path >> " << Path << "\n"; 165 std::string Error; 166 if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) { 167 unsigned diagID = flang->diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "unable to load plugin '%0': '%1'"); 168 flang->diagnostics().Report(diagID) << Path << Error; 169 } 170 } 171 172 llvm::outs() << " Plugin Registry List >>\n"; 173 for (const FrontendPluginRegistry::entry &plugin : FrontendPluginRegistry::entries()) { 174 llvm::outs() << plugin.getName() << " -- " << plugin.getDesc() << "\n"; 175 } 176 llvm::outs() << " << Plugin Registry List\n"; 177 178 static FrontendPluginRegistry::Add<HelloWorldFlangPlugin> X("-hello-wor", "simple Plugin example"); 179 static FrontendPluginRegistry::Add<HelloTwoFlangPlugin> Y("hellotwo", "another print plugin example"); 180 181 llvm::outs() << "----- (\\ExecuteCompilerInvocation) -----\n"; 182 183 // If there were errors in processing arguments, don't do anything else. 184 if (flang->diagnostics().hasErrorOccurred()) 185 return false; 186 187 // Create and execute the frontend action. 188 std::unique_ptr<FrontendAction> act(CreateFrontendAction(*flang)); 189 if (!act) 190 return false; 191 192 bool success = flang->ExecuteAction(*act); 193 return success; 194 } 195 196 } // namespace Fortran::frontend 197