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