1 //===- CompilerInvocation.h - Compiler Invocation Helper Data ---*- 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_COMPILERINVOCATION_H
14 #define FORTRAN_FRONTEND_COMPILERINVOCATION_H
15 
16 #include "flang/Frontend/CodeGenOptions.h"
17 #include "flang/Frontend/FrontendOptions.h"
18 #include "flang/Frontend/PreprocessorOptions.h"
19 #include "flang/Frontend/TargetOptions.h"
20 #include "flang/Parser/parsing.h"
21 #include "flang/Semantics/semantics.h"
22 #include "clang/Basic/Diagnostic.h"
23 #include "clang/Basic/DiagnosticOptions.h"
24 #include "llvm/Option/ArgList.h"
25 #include <memory>
26 
27 namespace Fortran::frontend {
28 
29 /// Fill out Opts based on the options given in Args.
30 ///
31 /// When errors are encountered, return false and, if Diags is non-null,
32 /// report the error(s).
33 bool parseDiagnosticArgs(clang::DiagnosticOptions &opts,
34                          llvm::opt::ArgList &args);
35 
36 class CompilerInvocationBase {
37 public:
38   /// Options controlling the diagnostic engine.
39   llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagnosticOpts;
40   /// Options for the preprocessor.
41   std::shared_ptr<Fortran::frontend::PreprocessorOptions> preprocessorOpts;
42 
43   CompilerInvocationBase();
44   CompilerInvocationBase(const CompilerInvocationBase &x);
45   ~CompilerInvocationBase();
46 
getDiagnosticOpts()47   clang::DiagnosticOptions &getDiagnosticOpts() {
48     return *diagnosticOpts.get();
49   }
getDiagnosticOpts()50   const clang::DiagnosticOptions &getDiagnosticOpts() const {
51     return *diagnosticOpts.get();
52   }
53 
getPreprocessorOpts()54   PreprocessorOptions &getPreprocessorOpts() { return *preprocessorOpts; }
getPreprocessorOpts()55   const PreprocessorOptions &getPreprocessorOpts() const {
56     return *preprocessorOpts;
57   }
58 };
59 
60 class CompilerInvocation : public CompilerInvocationBase {
61   /// Options for the frontend driver
62   // TODO: Merge with or translate to parserOpts_. We shouldn't need two sets of
63   // options.
64   FrontendOptions frontendOpts;
65 
66   /// Options for Flang parser
67   // TODO: Merge with or translate to frontendOpts. We shouldn't need two sets
68   // of options.
69   Fortran::parser::Options parserOpts;
70 
71   /// Options controlling the target.
72   Fortran::frontend::TargetOptions targetOpts;
73 
74   /// Options controlling IRgen and the backend.
75   Fortran::frontend::CodeGenOptions codeGenOpts;
76 
77   // Semantics context
78   std::unique_ptr<Fortran::semantics::SemanticsContext> semanticsContext;
79 
80   /// Semantic options
81   // TODO: Merge with or translate to frontendOpts. We shouldn't need two sets
82   // of options.
83   std::string moduleDir = ".";
84 
85   std::string moduleFileSuffix = ".mod";
86 
87   bool debugModuleDir = false;
88 
89   bool warnAsErr = false;
90 
91   /// This flag controls the unparsing and is used to decide whether to print out
92   /// the semantically analyzed version of an object or expression or the plain
93   /// version that does not include any information from semantic analysis.
94   bool useAnalyzedObjectsForUnparse = true;
95 
96   // Fortran Dialect options
97   Fortran::common::IntrinsicTypeDefaultKinds defaultKinds;
98 
99   bool enableConformanceChecks = false;
100 
101   /// Used in e.g. unparsing to dump the analyzed rather than the original
102   /// parse-tree objects.
103   Fortran::parser::AnalyzedObjectsAsFortran asFortran{
104       [](llvm::raw_ostream &o, const Fortran::evaluate::GenericExprWrapper &x) {
105         if (x.v) {
106           x.v->AsFortran(o);
107         } else {
108           o << "(bad expression)";
109         }
110       },
111       [](llvm::raw_ostream &o,
112          const Fortran::evaluate::GenericAssignmentWrapper &x) {
113         if (x.v) {
114           x.v->AsFortran(o);
115         } else {
116           o << "(bad assignment)";
117         }
118       },
119       [](llvm::raw_ostream &o, const Fortran::evaluate::ProcedureRef &x) {
120         x.AsFortran(o << "CALL ");
121       },
122   };
123 
124 public:
125   CompilerInvocation() = default;
126 
getFrontendOpts()127   FrontendOptions &getFrontendOpts() { return frontendOpts; }
getFrontendOpts()128   const FrontendOptions &getFrontendOpts() const { return frontendOpts; }
129 
getFortranOpts()130   Fortran::parser::Options &getFortranOpts() { return parserOpts; }
getFortranOpts()131   const Fortran::parser::Options &getFortranOpts() const { return parserOpts; }
132 
getTargetOpts()133   TargetOptions &getTargetOpts() { return targetOpts; }
getTargetOpts()134   const TargetOptions &getTargetOpts() const { return targetOpts; }
135 
getCodeGenOpts()136   CodeGenOptions &getCodeGenOpts() { return codeGenOpts; }
getCodeGenOpts()137   const CodeGenOptions &getCodeGenOpts() const { return codeGenOpts; }
138 
getSemanticsContext()139   Fortran::semantics::SemanticsContext &getSemanticsContext() {
140     return *semanticsContext;
141   }
getSemanticsContext()142   const Fortran::semantics::SemanticsContext &getSemanticsContext() const {
143     return *semanticsContext;
144   }
145 
getModuleDir()146   std::string &getModuleDir() { return moduleDir; }
getModuleDir()147   const std::string &getModuleDir() const { return moduleDir; }
148 
getModuleFileSuffix()149   std::string &getModuleFileSuffix() { return moduleFileSuffix; }
getModuleFileSuffix()150   const std::string &getModuleFileSuffix() const { return moduleFileSuffix; }
151 
getDebugModuleDir()152   bool &getDebugModuleDir() { return debugModuleDir; }
getDebugModuleDir()153   const bool &getDebugModuleDir() const { return debugModuleDir; }
154 
getWarnAsErr()155   bool &getWarnAsErr() { return warnAsErr; }
getWarnAsErr()156   const bool &getWarnAsErr() const { return warnAsErr; }
157 
getUseAnalyzedObjectsForUnparse()158   bool &getUseAnalyzedObjectsForUnparse() {
159     return useAnalyzedObjectsForUnparse;
160   }
getUseAnalyzedObjectsForUnparse()161   const bool &getUseAnalyzedObjectsForUnparse() const {
162     return useAnalyzedObjectsForUnparse;
163   }
164 
getEnableConformanceChecks()165   bool &getEnableConformanceChecks() { return enableConformanceChecks; }
getEnableConformanceChecks()166   const bool &getEnableConformanceChecks() const {
167     return enableConformanceChecks;
168   }
169 
getAsFortran()170   Fortran::parser::AnalyzedObjectsAsFortran &getAsFortran() {
171     return asFortran;
172   }
getAsFortran()173   const Fortran::parser::AnalyzedObjectsAsFortran &getAsFortran() const {
174     return asFortran;
175   }
176 
getDefaultKinds()177   Fortran::common::IntrinsicTypeDefaultKinds &getDefaultKinds() {
178     return defaultKinds;
179   }
getDefaultKinds()180   const Fortran::common::IntrinsicTypeDefaultKinds &getDefaultKinds() const {
181     return defaultKinds;
182   }
183 
184   /// Create a compiler invocation from a list of input options.
185   /// \returns true on success.
186   /// \returns false if an error was encountered while parsing the arguments
187   /// \param [out] res - The resulting invocation.
188   static bool createFromArgs(CompilerInvocation &res,
189                              llvm::ArrayRef<const char *> commandLineArgs,
190                              clang::DiagnosticsEngine &diags);
191 
192   // Enables the std=f2018 conformance check
setEnableConformanceChecks()193   void setEnableConformanceChecks() { enableConformanceChecks = true; }
194 
195   /// Useful setters
setModuleDir(std::string & dir)196   void setModuleDir(std::string &dir) { moduleDir = dir; }
197 
setModuleFileSuffix(const char * suffix)198   void setModuleFileSuffix(const char *suffix) {
199     moduleFileSuffix = std::string(suffix);
200   }
201 
setDebugModuleDir(bool flag)202   void setDebugModuleDir(bool flag) { debugModuleDir = flag; }
203 
setWarnAsErr(bool flag)204   void setWarnAsErr(bool flag) { warnAsErr = flag; }
205 
setUseAnalyzedObjectsForUnparse(bool flag)206   void setUseAnalyzedObjectsForUnparse(bool flag) {
207     useAnalyzedObjectsForUnparse = flag;
208   }
209 
210   /// Set the Fortran options to predefined defaults.
211   // TODO: We should map frontendOpts_ to parserOpts_ instead. For that, we
212   // need to extend frontendOpts_ first. Next, we need to add the corresponding
213   // compiler driver options in libclangDriver.
214   void setDefaultFortranOpts();
215 
216   /// Set the default predefinitions.
217   void setDefaultPredefinitions();
218 
219   /// Collect the macro definitions from preprocessorOpts_ and prepare them for
220   /// the parser (i.e. copy into parserOpts_)
221   void collectMacroDefinitions();
222 
223   /// Set the Fortran options to user-specified values.
224   /// These values are found in the preprocessor options.
225   void setFortranOpts();
226 
227   /// Set the Semantic Options
228   void setSemanticsOpts(Fortran::parser::AllCookedSources &);
229 };
230 
231 } // end namespace Fortran::frontend
232 #endif // FORTRAN_FRONTEND_COMPILERINVOCATION_H
233