xref: /llvm-project/flang/include/flang/Frontend/FrontendOptions.h (revision 23d7a6cedb5198535086a67586487f19effbd411)
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