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