1 //===- FrontendActions.h -----------------------------------------*- C++-*-===//
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 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef FORTRAN_FRONTEND_FRONTENDACTIONS_H
14 #define FORTRAN_FRONTEND_FRONTENDACTIONS_H
15 
16 #include "flang/Frontend/CodeGenOptions.h"
17 #include "flang/Frontend/FrontendAction.h"
18 #include "flang/Parser/parsing.h"
19 #include "flang/Semantics/semantics.h"
20 
21 #include "mlir/IR/BuiltinOps.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/Target/TargetMachine.h"
25 #include <memory>
26 
27 namespace Fortran::frontend {
28 
29 // TODO: This is a copy from f18.cpp. It doesn't really belong here and should
30 // be moved to a more suitable place in future.
31 struct MeasurementVisitor {
PreMeasurementVisitor32   template <typename A> bool Pre(const A &) { return true; }
PostMeasurementVisitor33   template <typename A> void Post(const A &) {
34     ++objects;
35     bytes += sizeof(A);
36   }
37   size_t objects{0}, bytes{0};
38 };
39 
40 //===----------------------------------------------------------------------===//
41 // Custom Consumer Actions
42 //===----------------------------------------------------------------------===//
43 
44 class InputOutputTestAction : public FrontendAction {
45   void executeAction() override;
46 };
47 
48 class InitOnlyAction : public FrontendAction {
49   void executeAction() override;
50 };
51 
52 //===----------------------------------------------------------------------===//
53 // Prescan Actions
54 //===----------------------------------------------------------------------===//
55 class PrescanAction : public FrontendAction {
56   void executeAction() override = 0;
57   bool beginSourceFileAction() override;
58 };
59 
60 class PrintPreprocessedAction : public PrescanAction {
61   void executeAction() override;
62 };
63 
64 class DebugDumpProvenanceAction : public PrescanAction {
65   void executeAction() override;
66 };
67 
68 class DebugDumpParsingLogAction : public PrescanAction {
69   void executeAction() override;
70 };
71 
72 class DebugMeasureParseTreeAction : public PrescanAction {
73   void executeAction() override;
74 };
75 
76 //===----------------------------------------------------------------------===//
77 // PrescanAndParse Actions
78 //===----------------------------------------------------------------------===//
79 class PrescanAndParseAction : public FrontendAction {
80   void executeAction() override = 0;
81   bool beginSourceFileAction() override;
82 };
83 
84 class DebugUnparseNoSemaAction : public PrescanAndParseAction {
85   void executeAction() override;
86 };
87 
88 class DebugDumpParseTreeNoSemaAction : public PrescanAndParseAction {
89   void executeAction() override;
90 };
91 
92 //===----------------------------------------------------------------------===//
93 // PrescanAndSema Actions
94 //
95 // These actions will parse the input, run the semantic checks and execute
96 // their actions provided that no parsing or semantic errors were found.
97 //===----------------------------------------------------------------------===//
98 class PrescanAndSemaAction : public FrontendAction {
99 
100   void executeAction() override = 0;
101   bool beginSourceFileAction() override;
102 };
103 
104 class DebugUnparseWithSymbolsAction : public PrescanAndSemaAction {
105   void executeAction() override;
106 };
107 
108 class DebugUnparseAction : public PrescanAndSemaAction {
109   void executeAction() override;
110 };
111 
112 class DebugDumpSymbolsAction : public PrescanAndSemaAction {
113   void executeAction() override;
114 };
115 
116 class DebugDumpParseTreeAction : public PrescanAndSemaAction {
117   void executeAction() override;
118 };
119 
120 class DebugDumpPFTAction : public PrescanAndSemaAction {
121   void executeAction() override;
122 };
123 
124 class DebugPreFIRTreeAction : public PrescanAndSemaAction {
125   void executeAction() override;
126 };
127 
128 class GetDefinitionAction : public PrescanAndSemaAction {
129   void executeAction() override;
130 };
131 
132 class GetSymbolsSourcesAction : public PrescanAndSemaAction {
133   void executeAction() override;
134 };
135 
136 class ParseSyntaxOnlyAction : public PrescanAndSemaAction {
137   void executeAction() override;
138 };
139 
140 class PluginParseTreeAction : public PrescanAndSemaAction {
141   void executeAction() override = 0;
142 
143 public:
144   Fortran::parser::Parsing &getParsing();
145   /// Creates an output file. This is just a wrapper for calling
146   /// CreateDefaultOutputFile from CompilerInstance. Use it to make sure that
147   /// your plugin respects driver's `-o` flag.
148   /// \param extension  The extension to use for the output file (ignored when
149   ///                   the user decides to print to stdout via `-o -`)
150   /// \return           Null on error, ostream for the output file otherwise
151   std::unique_ptr<llvm::raw_pwrite_stream> createOutputFile(
152       llvm::StringRef extension);
153 };
154 
155 //===----------------------------------------------------------------------===//
156 // PrescanAndSemaDebug Actions
157 //
158 // These actions will parse the input, run the semantic checks and execute
159 // their actions _regardless of_ whether any semantic errors have been found.
160 // This can be useful when adding new languge feature and when you wish to
161 // investigate compiler output (e.g. the parse tree) despite any semantic
162 // errors.
163 //
164 // NOTE: Use with care and for development only!
165 //===----------------------------------------------------------------------===//
166 class PrescanAndSemaDebugAction : public FrontendAction {
167 
168   void executeAction() override = 0;
169   bool beginSourceFileAction() override;
170 };
171 
172 class DebugDumpAllAction : public PrescanAndSemaDebugAction {
173   void executeAction() override;
174 };
175 
176 //===----------------------------------------------------------------------===//
177 // CodeGen Actions
178 //===----------------------------------------------------------------------===//
179 /// Represents the type of "backend" action to perform by the corresponding
180 /// CodeGenAction. Note that from Flang's perspective, both LLVM and MLIR are
181 /// "backends" that are used for generating LLVM IR/BC, assembly files or
182 /// machine code. This enum captures "what" exactly one of these backends is to
183 /// do. The names are similar to what is used in Clang - this allows us to
184 /// maintain some level of consistency/similarity between the drivers.
185 enum class BackendActionTy {
186   Backend_EmitAssembly, ///< Emit native assembly files
187   Backend_EmitObj, ///< Emit native object files
188   Backend_EmitBC, ///< Emit LLVM bitcode files
189   Backend_EmitLL, ///< Emit human-readable LLVM assembly
190   Backend_EmitMLIR ///< Emit MLIR files
191 };
192 
193 /// Abstract base class for actions that generate code (MLIR, LLVM IR, assembly
194 /// and machine code). Every action that inherits from this class will at
195 /// least run the prescanning, parsing, semantic checks and lower the parse
196 /// tree to an MLIR module.
197 class CodeGenAction : public FrontendAction {
198 
199   void executeAction() override;
200   /// Runs prescan, parsing, sema and lowers to MLIR.
201   bool beginSourceFileAction() override;
202   /// Sets up LLVM's TargetMachine, configures llvmModule accordingly.
203   void setUpTargetMachine();
204   /// Runs the optimization (aka middle-end) pipeline on the LLVM module
205   /// associated with this action.
206   void runOptimizationPipeline(llvm::raw_pwrite_stream &os);
207 
208 protected:
CodeGenAction(BackendActionTy act)209   CodeGenAction(BackendActionTy act) : action{act} {};
210   /// @name MLIR
211   /// {
212   std::unique_ptr<mlir::ModuleOp> mlirModule;
213   std::unique_ptr<mlir::MLIRContext> mlirCtx;
214   /// }
215 
216   /// @name LLVM IR
217   std::unique_ptr<llvm::LLVMContext> llvmCtx;
218   std::unique_ptr<llvm::Module> llvmModule;
219 
220   /// Generates an LLVM IR module from CodeGenAction::mlirModule and saves it
221   /// in CodeGenAction::llvmModule.
222   void generateLLVMIR();
223 
224   BackendActionTy action;
225 
226   std::unique_ptr<llvm::TargetMachine> tm;
227   /// }
228 public:
229   ~CodeGenAction() override;
230 };
231 
232 class EmitMLIRAction : public CodeGenAction {
233 public:
EmitMLIRAction()234   EmitMLIRAction() : CodeGenAction(BackendActionTy::Backend_EmitMLIR) {}
235 };
236 
237 class EmitLLVMAction : public CodeGenAction {
238 public:
EmitLLVMAction()239   EmitLLVMAction() : CodeGenAction(BackendActionTy::Backend_EmitLL) {}
240 };
241 
242 class EmitLLVMBitcodeAction : public CodeGenAction {
243 public:
EmitLLVMBitcodeAction()244   EmitLLVMBitcodeAction() : CodeGenAction(BackendActionTy::Backend_EmitBC) {}
245 };
246 
247 class EmitObjAction : public CodeGenAction {
248 public:
EmitObjAction()249   EmitObjAction() : CodeGenAction(BackendActionTy::Backend_EmitObj) {}
250 };
251 
252 class EmitAssemblyAction : public CodeGenAction {
253 public:
EmitAssemblyAction()254   EmitAssemblyAction() : CodeGenAction(BackendActionTy::Backend_EmitAssembly) {}
255 };
256 
257 } // namespace Fortran::frontend
258 
259 #endif // FORTRAN_FRONTEND_FRONTENDACTIONS_H
260