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 47 clang::DiagnosticOptions &getDiagnosticOpts() { 48 return *diagnosticOpts.get(); 49 } 50 const clang::DiagnosticOptions &getDiagnosticOpts() const { 51 return *diagnosticOpts.get(); 52 } 53 54 PreprocessorOptions &getPreprocessorOpts() { return *preprocessorOpts; } 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 127 FrontendOptions &getFrontendOpts() { return frontendOpts; } 128 const FrontendOptions &getFrontendOpts() const { return frontendOpts; } 129 130 Fortran::parser::Options &getFortranOpts() { return parserOpts; } 131 const Fortran::parser::Options &getFortranOpts() const { return parserOpts; } 132 133 TargetOptions &getTargetOpts() { return targetOpts; } 134 const TargetOptions &getTargetOpts() const { return targetOpts; } 135 136 CodeGenOptions &getCodeGenOpts() { return codeGenOpts; } 137 const CodeGenOptions &getCodeGenOpts() const { return codeGenOpts; } 138 139 Fortran::semantics::SemanticsContext &getSemanticsContext() { 140 return *semanticsContext; 141 } 142 const Fortran::semantics::SemanticsContext &getSemanticsContext() const { 143 return *semanticsContext; 144 } 145 146 std::string &getModuleDir() { return moduleDir; } 147 const std::string &getModuleDir() const { return moduleDir; } 148 149 std::string &getModuleFileSuffix() { return moduleFileSuffix; } 150 const std::string &getModuleFileSuffix() const { return moduleFileSuffix; } 151 152 bool &getDebugModuleDir() { return debugModuleDir; } 153 const bool &getDebugModuleDir() const { return debugModuleDir; } 154 155 bool &getWarnAsErr() { return warnAsErr; } 156 const bool &getWarnAsErr() const { return warnAsErr; } 157 158 bool &getUseAnalyzedObjectsForUnparse() { 159 return useAnalyzedObjectsForUnparse; 160 } 161 const bool &getUseAnalyzedObjectsForUnparse() const { 162 return useAnalyzedObjectsForUnparse; 163 } 164 165 bool &getEnableConformanceChecks() { return enableConformanceChecks; } 166 const bool &getEnableConformanceChecks() const { 167 return enableConformanceChecks; 168 } 169 170 Fortran::parser::AnalyzedObjectsAsFortran &getAsFortran() { 171 return asFortran; 172 } 173 const Fortran::parser::AnalyzedObjectsAsFortran &getAsFortran() const { 174 return asFortran; 175 } 176 177 Fortran::common::IntrinsicTypeDefaultKinds &getDefaultKinds() { 178 return defaultKinds; 179 } 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 193 void setEnableConformanceChecks() { enableConformanceChecks = true; } 194 195 /// Useful setters 196 void setModuleDir(std::string &dir) { moduleDir = dir; } 197 198 void setModuleFileSuffix(const char *suffix) { 199 moduleFileSuffix = std::string(suffix); 200 } 201 202 void setDebugModuleDir(bool flag) { debugModuleDir = flag; } 203 204 void setWarnAsErr(bool flag) { warnAsErr = flag; } 205 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