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