xref: /llvm-project/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp (revision d902dd011c9403ff746613a73c5d83e13db93fe5)
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