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