1 //===- FrontendOptions.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_FRONTENDOPTIONS_H 14 #define FORTRAN_FRONTEND_FRONTENDOPTIONS_H 15 16 #include "flang/Common/Fortran-features.h" 17 #include "flang/Lower/EnvironmentDefault.h" 18 #include "flang/Parser/characters.h" 19 #include "flang/Parser/unparse.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/Support/MemoryBuffer.h" 22 #include <cstdint> 23 #include <string> 24 25 namespace Fortran::frontend { 26 27 enum ActionKind { 28 /// -test-io mode 29 InputOutputTest, 30 31 /// -E mode 32 PrintPreprocessedInput, 33 34 /// -fsyntax-only 35 ParseSyntaxOnly, 36 37 /// Emit FIR mlir file 38 EmitFIR, 39 40 /// Emit HLFIR mlir file 41 EmitHLFIR, 42 43 /// Emit an .ll file 44 EmitLLVM, 45 46 /// Emit a .bc file 47 EmitLLVMBitcode, 48 49 /// Emit a .o file. 50 EmitObj, 51 52 /// Emit a .s file. 53 EmitAssembly, 54 55 /// Parse, unparse the parse-tree and output a Fortran source file 56 DebugUnparse, 57 58 /// Parse, unparse the parse-tree and output a Fortran source file, skip the 59 /// semantic checks 60 DebugUnparseNoSema, 61 62 /// Parse, resolve the sybmols, unparse the parse-tree and then output a 63 /// Fortran source file 64 DebugUnparseWithSymbols, 65 66 /// Parse, run semantics, and output a Fortran source file preceded 67 /// by all the necessary modules (transitively) 68 DebugUnparseWithModules, 69 70 /// Parse, run semantics and then output symbols from semantics 71 DebugDumpSymbols, 72 73 /// Parse, run semantics and then output the parse tree 74 DebugDumpParseTree, 75 76 /// Parse, run semantics and then output the pre-fir parse tree 77 DebugDumpPFT, 78 79 /// Parse, run semantics and then output the parse tree and symbols 80 DebugDumpAll, 81 82 /// Parse and then output the parse tree, skip the semantic checks 83 DebugDumpParseTreeNoSema, 84 85 /// Dump provenance 86 DebugDumpProvenance, 87 88 /// Parse then output the parsing log 89 DebugDumpParsingLog, 90 91 /// Parse then output the number of objects in the parse tree and the overall 92 /// size 93 DebugMeasureParseTree, 94 95 /// Parse, run semantics and then output the pre-FIR tree 96 DebugPreFIRTree, 97 98 /// `-fget-definition` 99 GetDefinition, 100 101 /// Parse, run semantics and then dump symbol sources map 102 GetSymbolsSources, 103 104 /// Only execute frontend initialization 105 InitOnly, 106 107 /// Run a plugin action 108 PluginAction 109 }; 110 111 /// \param suffix The file extension 112 /// \return True if the file extension should be processed as fixed form 113 bool isFixedFormSuffix(llvm::StringRef suffix); 114 115 /// \param suffix The file extension 116 /// \return True if the file extension should be processed as free form 117 bool isFreeFormSuffix(llvm::StringRef suffix); 118 119 /// \param suffix The file extension 120 /// \return True if the file should be preprocessed 121 bool isToBePreprocessed(llvm::StringRef suffix); 122 123 /// \param suffix The file extension 124 /// \return True if the file contains CUDA Fortran 125 bool isCUDAFortranSuffix(llvm::StringRef suffix); 126 127 enum class Language : uint8_t { 128 Unknown, 129 130 /// MLIR: we accept this so that we can run the optimizer on it, and compile 131 /// it to LLVM IR, assembly or object code. 132 MLIR, 133 134 /// LLVM IR: we accept this so that we can run the optimizer on it, 135 /// and compile it to assembly or object code. 136 LLVM_IR, 137 138 /// @{ Languages that the frontend can parse and compile. 139 Fortran, 140 /// @} 141 }; 142 143 // Source file layout 144 enum class FortranForm { 145 /// The user has not specified a form. Base the form off the file extension. 146 Unknown, 147 148 /// -ffree-form 149 FixedForm, 150 151 /// -ffixed-form 152 FreeForm 153 }; 154 155 /// The kind of a file that we've been handed as an input. 156 class InputKind { 157 private: 158 Language lang; 159 160 public: 161 /// The input file format. 162 enum Format { Source, ModuleMap, Precompiled }; 163 164 constexpr InputKind(Language l = Language::Unknown) : lang(l) {} 165 166 Language getLanguage() const { return static_cast<Language>(lang); } 167 168 /// Is the input kind fully-unknown? 169 bool isUnknown() const { return lang == Language::Unknown; } 170 }; 171 172 /// An input file for the front end. 173 class FrontendInputFile { 174 /// The file name, or "-" to read from standard input. 175 std::string file; 176 177 /// The input, if it comes from a buffer rather than a file. This object 178 /// does not own the buffer, and the caller is responsible for ensuring 179 /// that it outlives any users. 180 const llvm::MemoryBuffer *buffer = nullptr; 181 182 /// The kind of input, atm it contains language 183 InputKind kind; 184 185 /// Is this input file in fixed-form format? This is simply derived from the 186 /// file extension and should not be altered by consumers. For input from 187 /// stdin this is never modified. 188 bool isFixedForm = false; 189 190 /// Must this file be preprocessed? Note that in Flang the preprocessor is 191 /// always run. This flag is used to control whether predefined and command 192 /// line preprocessor macros are enabled or not. In practice, this is 193 /// sufficient to implement gfortran`s logic controlled with `-cpp/-nocpp`. 194 unsigned mustBePreprocessed : 1; 195 196 /// Whether to enable CUDA Fortran language extensions 197 bool isCUDAFortran{false}; 198 199 public: 200 FrontendInputFile() = default; 201 FrontendInputFile(llvm::StringRef file, InputKind inKind) 202 : file(file.str()), kind(inKind) { 203 204 // Based on the extension, decide whether this is a fixed or free form 205 // file. 206 auto pathDotIndex{file.rfind(".")}; 207 std::string pathSuffix{file.substr(pathDotIndex + 1)}; 208 isFixedForm = isFixedFormSuffix(pathSuffix); 209 mustBePreprocessed = isToBePreprocessed(pathSuffix); 210 isCUDAFortran = isCUDAFortranSuffix(pathSuffix); 211 } 212 213 FrontendInputFile(const llvm::MemoryBuffer *memBuf, InputKind inKind) 214 : buffer(memBuf), kind(inKind) {} 215 216 InputKind getKind() const { return kind; } 217 218 bool isEmpty() const { return file.empty() && buffer == nullptr; } 219 bool isFile() const { return (buffer == nullptr); } 220 bool getIsFixedForm() const { return isFixedForm; } 221 bool getMustBePreprocessed() const { return mustBePreprocessed; } 222 bool getIsCUDAFortran() const { return isCUDAFortran; } 223 224 llvm::StringRef getFile() const { 225 assert(isFile()); 226 return file; 227 } 228 229 const llvm::MemoryBuffer *getBuffer() const { 230 assert(buffer && "Requested buffer, but it is empty!"); 231 return buffer; 232 } 233 }; 234 235 /// FrontendOptions - Options for controlling the behavior of the frontend. 236 struct FrontendOptions { 237 FrontendOptions() 238 : showHelp(false), showVersion(false), instrumentedParse(false), 239 showColors(false), printSupportedCPUs(false), 240 needProvenanceRangeToCharBlockMappings(false) {} 241 242 /// Show the -help text. 243 unsigned showHelp : 1; 244 245 /// Show the -version text. 246 unsigned showVersion : 1; 247 248 /// Instrument the parse to get a more verbose log 249 unsigned instrumentedParse : 1; 250 251 /// Enable color diagnostics. 252 unsigned showColors : 1; 253 254 /// Print the supported cpus for the current target 255 unsigned printSupportedCPUs : 1; 256 257 /// Enable Provenance to character-stream mapping. Allows e.g. IDEs to find 258 /// symbols based on source-code location. This is not needed in regular 259 /// compilation. 260 unsigned needProvenanceRangeToCharBlockMappings : 1; 261 262 /// Input values from `-fget-definition` 263 struct GetDefinitionVals { 264 unsigned line; 265 unsigned startColumn; 266 unsigned endColumn; 267 }; 268 GetDefinitionVals getDefVals; 269 270 /// The input files and their types. 271 std::vector<FrontendInputFile> inputs; 272 273 /// The output file, if any. 274 std::string outputFile; 275 276 /// The frontend action to perform. 277 frontend::ActionKind programAction = ParseSyntaxOnly; 278 279 // The form to process files in, if specified. 280 FortranForm fortranForm = FortranForm::Unknown; 281 282 // Default values for environment variables to be set by the runtime. 283 std::vector<Fortran::lower::EnvironmentDefault> envDefaults; 284 285 // The column after which characters are ignored in fixed form lines in the 286 // source file. 287 int fixedFormColumns = 72; 288 289 /// The input kind, either specified via -x argument or deduced from the input 290 /// file name. 291 InputKind dashX; 292 293 // Language features 294 common::LanguageFeatureControl features; 295 296 // Source file encoding 297 Fortran::parser::Encoding encoding{Fortran::parser::Encoding::UTF_8}; 298 299 /// The list of plugins to load. 300 std::vector<std::string> plugins; 301 302 /// The name of the action to run when using a plugin action. 303 std::string actionName; 304 305 /// A list of arguments to forward to LLVM's option processing; this 306 /// should only be used for debugging and experimental features. 307 std::vector<std::string> llvmArgs; 308 309 /// A list of arguments to forward to MLIR's option processing; this 310 /// should only be used for debugging and experimental features. 311 std::vector<std::string> mlirArgs; 312 313 // Return the appropriate input kind for a file extension. For example, 314 /// "*.f" would return Language::Fortran. 315 /// 316 /// \return The input kind for the extension, or Language::Unknown if the 317 /// extension is not recognized. 318 static InputKind getInputKindForExtension(llvm::StringRef extension); 319 }; 320 } // namespace Fortran::frontend 321 322 #endif // FORTRAN_FRONTEND_FRONTENDOPTIONS_H 323