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