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