xref: /llvm-project/flang/lib/Frontend/CompilerInvocation.cpp (revision 7211bf48a62bfe3a181013f412f2fa6e112ae99f)
1257b2971SCaroline Concatto //===- CompilerInvocation.cpp ---------------------------------------------===//
2257b2971SCaroline Concatto //
3257b2971SCaroline Concatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4257b2971SCaroline Concatto // See https://llvm.org/LICENSE.txt for license information.
5257b2971SCaroline Concatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6257b2971SCaroline Concatto //
7257b2971SCaroline Concatto //===----------------------------------------------------------------------===//
81e462fafSAndrzej Warzynski //
91e462fafSAndrzej Warzynski // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
101e462fafSAndrzej Warzynski //
111e462fafSAndrzej Warzynski //===----------------------------------------------------------------------===//
12257b2971SCaroline Concatto 
13257b2971SCaroline Concatto #include "flang/Frontend/CompilerInvocation.h"
146d48a1a5SFaris Rehman #include "flang/Common/Fortran-features.h"
154a5ac14eSDominik Adamski #include "flang/Common/OpenMP-features.h"
16541f5c4aSHussain Kadhem #include "flang/Common/Version.h"
17869385b1SAndrzej Warzynski #include "flang/Frontend/CodeGenOptions.h"
187809fa20SFaris Rehman #include "flang/Frontend/PreprocessorOptions.h"
192e9439e4SAndrzej Warzynski #include "flang/Frontend/TargetOptions.h"
206d48a1a5SFaris Rehman #include "flang/Semantics/semantics.h"
21e59e8488SjeanPerier #include "flang/Tools/TargetSetup.h"
22197d9a55SFaris Rehman #include "flang/Version.inc"
23257b2971SCaroline Concatto #include "clang/Basic/AllDiagnostics.h"
24257b2971SCaroline Concatto #include "clang/Basic/DiagnosticDriver.h"
25257b2971SCaroline Concatto #include "clang/Basic/DiagnosticOptions.h"
26257b2971SCaroline Concatto #include "clang/Driver/DriverDiagnostic.h"
27869385b1SAndrzej Warzynski #include "clang/Driver/OptionUtils.h"
28257b2971SCaroline Concatto #include "clang/Driver/Options.h"
29257b2971SCaroline Concatto #include "llvm/ADT/StringRef.h"
30257b2971SCaroline Concatto #include "llvm/ADT/StringSwitch.h"
31e2b7424dSSacha Ballantyne #include "llvm/Frontend/Debug/Options.h"
32257b2971SCaroline Concatto #include "llvm/Option/Arg.h"
33257b2971SCaroline Concatto #include "llvm/Option/ArgList.h"
34257b2971SCaroline Concatto #include "llvm/Option/OptTable.h"
359e6b46a9SDavid Truby #include "llvm/Support/CodeGen.h"
36cd4abc52SArnamoy Bhattacharyya #include "llvm/Support/FileSystem.h"
37cd4abc52SArnamoy Bhattacharyya #include "llvm/Support/FileUtilities.h"
385597ec2dSserge-sans-paille #include "llvm/Support/Path.h"
398d51d37eSAndrzej Warzynski #include "llvm/Support/Process.h"
40257b2971SCaroline Concatto #include "llvm/Support/raw_ostream.h"
41d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h"
4262c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h"
4384a0a3d3SPaul Osmialowski #include <algorithm>
44541f5c4aSHussain Kadhem #include <cstdlib>
456d48a1a5SFaris Rehman #include <memory>
464d4d4785SKazu Hirata #include <optional>
47257b2971SCaroline Concatto 
48257b2971SCaroline Concatto using namespace Fortran::frontend;
49257b2971SCaroline Concatto 
50257b2971SCaroline Concatto //===----------------------------------------------------------------------===//
51257b2971SCaroline Concatto // Initialization.
52257b2971SCaroline Concatto //===----------------------------------------------------------------------===//
53257b2971SCaroline Concatto CompilerInvocationBase::CompilerInvocationBase()
541e462fafSAndrzej Warzynski     : diagnosticOpts(new clang::DiagnosticOptions()),
551e462fafSAndrzej Warzynski       preprocessorOpts(new PreprocessorOptions()) {}
56257b2971SCaroline Concatto 
57257b2971SCaroline Concatto CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &x)
581e462fafSAndrzej Warzynski     : diagnosticOpts(new clang::DiagnosticOptions(x.getDiagnosticOpts())),
591e462fafSAndrzej Warzynski       preprocessorOpts(new PreprocessorOptions(x.getPreprocessorOpts())) {}
60257b2971SCaroline Concatto 
61257b2971SCaroline Concatto CompilerInvocationBase::~CompilerInvocationBase() = default;
62257b2971SCaroline Concatto 
63257b2971SCaroline Concatto //===----------------------------------------------------------------------===//
64257b2971SCaroline Concatto // Deserialization (from args)
65257b2971SCaroline Concatto //===----------------------------------------------------------------------===//
6643084160SPeixin Qiao static bool parseShowColorsArgs(const llvm::opt::ArgList &args,
6743084160SPeixin Qiao                                 bool defaultColor = true) {
6843084160SPeixin Qiao   // Color diagnostics default to auto ("on" if terminal supports) in the
6906eb10daSBrad Richardson   // compiler driver `flang` but default to off in the frontend driver
7006eb10daSBrad Richardson   // `flang -fc1`, needing an explicit OPT_fdiagnostics_color.
718d51d37eSAndrzej Warzynski   // Support both clang's -f[no-]color-diagnostics and gcc's
728d51d37eSAndrzej Warzynski   // -f[no-]diagnostics-colors[=never|always|auto].
738d51d37eSAndrzej Warzynski   enum {
748d51d37eSAndrzej Warzynski     Colors_On,
758d51d37eSAndrzej Warzynski     Colors_Off,
768d51d37eSAndrzej Warzynski     Colors_Auto
771e462fafSAndrzej Warzynski   } showColors = defaultColor ? Colors_Auto : Colors_Off;
788d51d37eSAndrzej Warzynski 
798d51d37eSAndrzej Warzynski   for (auto *a : args) {
801e462fafSAndrzej Warzynski     const llvm::opt::Option &opt = a->getOption();
811e462fafSAndrzej Warzynski     if (opt.matches(clang::driver::options::OPT_fcolor_diagnostics)) {
821e462fafSAndrzej Warzynski       showColors = Colors_On;
831e462fafSAndrzej Warzynski     } else if (opt.matches(clang::driver::options::OPT_fno_color_diagnostics)) {
841e462fafSAndrzej Warzynski       showColors = Colors_Off;
851e462fafSAndrzej Warzynski     } else if (opt.matches(clang::driver::options::OPT_fdiagnostics_color_EQ)) {
868d51d37eSAndrzej Warzynski       llvm::StringRef value(a->getValue());
878d51d37eSAndrzej Warzynski       if (value == "always")
881e462fafSAndrzej Warzynski         showColors = Colors_On;
898d51d37eSAndrzej Warzynski       else if (value == "never")
901e462fafSAndrzej Warzynski         showColors = Colors_Off;
918d51d37eSAndrzej Warzynski       else if (value == "auto")
921e462fafSAndrzej Warzynski         showColors = Colors_Auto;
938d51d37eSAndrzej Warzynski     }
948d51d37eSAndrzej Warzynski   }
958d51d37eSAndrzej Warzynski 
961e462fafSAndrzej Warzynski   return showColors == Colors_On ||
971e462fafSAndrzej Warzynski          (showColors == Colors_Auto &&
981e462fafSAndrzej Warzynski           llvm::sys::Process::StandardErrHasColors());
998d51d37eSAndrzej Warzynski }
1008d51d37eSAndrzej Warzynski 
101bbdf5c37SAndrzej Warzynski /// Extracts the optimisation level from \a args.
102bbdf5c37SAndrzej Warzynski static unsigned getOptimizationLevel(llvm::opt::ArgList &args,
103bbdf5c37SAndrzej Warzynski                                      clang::DiagnosticsEngine &diags) {
1040a1aa6cdSArthur Eubanks   unsigned defaultOpt = 0;
105bbdf5c37SAndrzej Warzynski 
106bbdf5c37SAndrzej Warzynski   if (llvm::opt::Arg *a =
107bbdf5c37SAndrzej Warzynski           args.getLastArg(clang::driver::options::OPT_O_Group)) {
108bbdf5c37SAndrzej Warzynski     if (a->getOption().matches(clang::driver::options::OPT_O0))
1090a1aa6cdSArthur Eubanks       return 0;
110bbdf5c37SAndrzej Warzynski 
111bbdf5c37SAndrzej Warzynski     assert(a->getOption().matches(clang::driver::options::OPT_O));
112bbdf5c37SAndrzej Warzynski 
113bbdf5c37SAndrzej Warzynski     return getLastArgIntValue(args, clang::driver::options::OPT_O, defaultOpt,
114bbdf5c37SAndrzej Warzynski                               diags);
115bbdf5c37SAndrzej Warzynski   }
116bbdf5c37SAndrzej Warzynski 
117bbdf5c37SAndrzej Warzynski   return defaultOpt;
118bbdf5c37SAndrzej Warzynski }
119bbdf5c37SAndrzej Warzynski 
1201e462fafSAndrzej Warzynski bool Fortran::frontend::parseDiagnosticArgs(clang::DiagnosticOptions &opts,
12143084160SPeixin Qiao                                             llvm::opt::ArgList &args) {
12243084160SPeixin Qiao   opts.ShowColors = parseShowColorsArgs(args);
1238d51d37eSAndrzej Warzynski 
1248d51d37eSAndrzej Warzynski   return true;
1258d51d37eSAndrzej Warzynski }
1268d51d37eSAndrzej Warzynski 
127e2b7424dSSacha Ballantyne static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
128e2b7424dSSacha Ballantyne                            llvm::opt::ArgList &args,
129e2b7424dSSacha Ballantyne                            clang::DiagnosticsEngine &diags) {
130e2b7424dSSacha Ballantyne   using DebugInfoKind = llvm::codegenoptions::DebugInfoKind;
131e2b7424dSSacha Ballantyne   if (llvm::opt::Arg *arg =
132e2b7424dSSacha Ballantyne           args.getLastArg(clang::driver::options::OPT_debug_info_kind_EQ)) {
133e2b7424dSSacha Ballantyne     std::optional<DebugInfoKind> val =
134e2b7424dSSacha Ballantyne         llvm::StringSwitch<std::optional<DebugInfoKind>>(arg->getValue())
135e2b7424dSSacha Ballantyne             .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly)
136e2b7424dSSacha Ballantyne             .Case("line-directives-only",
137e2b7424dSSacha Ballantyne                   llvm::codegenoptions::DebugDirectivesOnly)
138e2b7424dSSacha Ballantyne             .Case("constructor", llvm::codegenoptions::DebugInfoConstructor)
139e2b7424dSSacha Ballantyne             .Case("limited", llvm::codegenoptions::LimitedDebugInfo)
140e2b7424dSSacha Ballantyne             .Case("standalone", llvm::codegenoptions::FullDebugInfo)
141e2b7424dSSacha Ballantyne             .Case("unused-types", llvm::codegenoptions::UnusedTypeInfo)
142e2b7424dSSacha Ballantyne             .Default(std::nullopt);
143e2b7424dSSacha Ballantyne     if (!val.has_value()) {
144e2b7424dSSacha Ballantyne       diags.Report(clang::diag::err_drv_invalid_value)
145e2b7424dSSacha Ballantyne           << arg->getAsString(args) << arg->getValue();
146e2b7424dSSacha Ballantyne       return false;
147e2b7424dSSacha Ballantyne     }
148e2b7424dSSacha Ballantyne     opts.setDebugInfo(val.value());
149e2b7424dSSacha Ballantyne     if (val != llvm::codegenoptions::DebugLineTablesOnly &&
150087b33bbSabidh         val != llvm::codegenoptions::FullDebugInfo &&
151e2b7424dSSacha Ballantyne         val != llvm::codegenoptions::NoDebugInfo) {
152e2b7424dSSacha Ballantyne       const auto debugWarning = diags.getCustomDiagID(
153e2b7424dSSacha Ballantyne           clang::DiagnosticsEngine::Warning, "Unsupported debug option: %0");
154e2b7424dSSacha Ballantyne       diags.Report(debugWarning) << arg->getValue();
155e2b7424dSSacha Ballantyne     }
156e2b7424dSSacha Ballantyne   }
157e2b7424dSSacha Ballantyne   return true;
158e2b7424dSSacha Ballantyne }
159e2b7424dSSacha Ballantyne 
160a207e630STom Eccles static bool parseVectorLibArg(Fortran::frontend::CodeGenOptions &opts,
161a207e630STom Eccles                               llvm::opt::ArgList &args,
162a207e630STom Eccles                               clang::DiagnosticsEngine &diags) {
163a207e630STom Eccles   llvm::opt::Arg *arg = args.getLastArg(clang::driver::options::OPT_fveclib);
164a207e630STom Eccles   if (!arg)
165a207e630STom Eccles     return true;
166a207e630STom Eccles 
167a207e630STom Eccles   using VectorLibrary = llvm::driver::VectorLibrary;
168a207e630STom Eccles   std::optional<VectorLibrary> val =
169a207e630STom Eccles       llvm::StringSwitch<std::optional<VectorLibrary>>(arg->getValue())
170a207e630STom Eccles           .Case("Accelerate", VectorLibrary::Accelerate)
171a207e630STom Eccles           .Case("LIBMVEC", VectorLibrary::LIBMVEC)
172a207e630STom Eccles           .Case("MASSV", VectorLibrary::MASSV)
173a207e630STom Eccles           .Case("SVML", VectorLibrary::SVML)
174a207e630STom Eccles           .Case("SLEEF", VectorLibrary::SLEEF)
175a207e630STom Eccles           .Case("Darwin_libsystem_m", VectorLibrary::Darwin_libsystem_m)
176a207e630STom Eccles           .Case("ArmPL", VectorLibrary::ArmPL)
177a207e630STom Eccles           .Case("NoLibrary", VectorLibrary::NoLibrary)
178a207e630STom Eccles           .Default(std::nullopt);
179a207e630STom Eccles   if (!val.has_value()) {
180a207e630STom Eccles     diags.Report(clang::diag::err_drv_invalid_value)
181a207e630STom Eccles         << arg->getAsString(args) << arg->getValue();
182a207e630STom Eccles     return false;
183a207e630STom Eccles   }
184a207e630STom Eccles   opts.setVecLib(val.value());
185a207e630STom Eccles   return true;
186a207e630STom Eccles }
187a207e630STom Eccles 
18891989c67SVictor Kingi // Generate an OptRemark object containing info on if the -Rgroup
18991989c67SVictor Kingi // specified is enabled or not.
19091989c67SVictor Kingi static CodeGenOptions::OptRemark
1918e315c6cSVictor Kingi parseOptimizationRemark(clang::DiagnosticsEngine &diags,
1928e315c6cSVictor Kingi                         llvm::opt::ArgList &args, llvm::opt::OptSpecifier optEq,
19391989c67SVictor Kingi                         llvm::StringRef remarkOptName) {
19491989c67SVictor Kingi   assert((remarkOptName == "pass" || remarkOptName == "pass-missed" ||
19591989c67SVictor Kingi           remarkOptName == "pass-analysis") &&
1968e315c6cSVictor Kingi          "Unsupported remark option name provided.");
19791989c67SVictor Kingi   CodeGenOptions::OptRemark result;
19891989c67SVictor Kingi 
19991989c67SVictor Kingi   for (llvm::opt::Arg *a : args) {
20091989c67SVictor Kingi     if (a->getOption().matches(clang::driver::options::OPT_R_Joined)) {
20191989c67SVictor Kingi       llvm::StringRef value = a->getValue();
20291989c67SVictor Kingi 
20391989c67SVictor Kingi       if (value == remarkOptName) {
20491989c67SVictor Kingi         result.Kind = CodeGenOptions::RemarkKind::RK_Enabled;
20591989c67SVictor Kingi         // Enable everything
20691989c67SVictor Kingi         result.Pattern = ".*";
20791989c67SVictor Kingi         result.Regex = std::make_shared<llvm::Regex>(result.Pattern);
20891989c67SVictor Kingi 
20991989c67SVictor Kingi       } else if (value.split('-') ==
21091989c67SVictor Kingi                  std::make_pair(llvm::StringRef("no"), remarkOptName)) {
21191989c67SVictor Kingi         result.Kind = CodeGenOptions::RemarkKind::RK_Disabled;
21291989c67SVictor Kingi         // Disable everything
21391989c67SVictor Kingi         result.Pattern = "";
21491989c67SVictor Kingi         result.Regex = nullptr;
21591989c67SVictor Kingi       }
2168e315c6cSVictor Kingi     } else if (a->getOption().matches(optEq)) {
2178e315c6cSVictor Kingi       result.Kind = CodeGenOptions::RemarkKind::RK_WithPattern;
2188e315c6cSVictor Kingi       result.Pattern = a->getValue();
2198e315c6cSVictor Kingi       result.Regex = std::make_shared<llvm::Regex>(result.Pattern);
2208e315c6cSVictor Kingi       std::string regexError;
2218e315c6cSVictor Kingi 
2228e315c6cSVictor Kingi       if (!result.Regex->isValid(regexError)) {
2238e315c6cSVictor Kingi         diags.Report(clang::diag::err_drv_optimization_remark_pattern)
2248e315c6cSVictor Kingi             << regexError << a->getAsString(args);
2258e315c6cSVictor Kingi         return CodeGenOptions::OptRemark();
2268e315c6cSVictor Kingi       }
22791989c67SVictor Kingi     }
22891989c67SVictor Kingi   }
22991989c67SVictor Kingi   return result;
23091989c67SVictor Kingi }
23191989c67SVictor Kingi 
232869385b1SAndrzej Warzynski static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
233869385b1SAndrzej Warzynski                              llvm::opt::ArgList &args,
234869385b1SAndrzej Warzynski                              clang::DiagnosticsEngine &diags) {
235bbdf5c37SAndrzej Warzynski   opts.OptimizationLevel = getOptimizationLevel(args, diags);
236869385b1SAndrzej Warzynski 
237869385b1SAndrzej Warzynski   if (args.hasFlag(clang::driver::options::OPT_fdebug_pass_manager,
238869385b1SAndrzej Warzynski                    clang::driver::options::OPT_fno_debug_pass_manager, false))
239869385b1SAndrzej Warzynski     opts.DebugPassManager = 1;
240ef5ede52SUsman Nadeem 
241bf81ba37STom Eccles   if (args.hasFlag(clang::driver::options::OPT_fstack_arrays,
242f04ccadfSVictor Kingi                    clang::driver::options::OPT_fno_stack_arrays, false))
243bf81ba37STom Eccles     opts.StackArrays = 1;
244f04ccadfSVictor Kingi 
245efae695dSMats Petersson   if (args.hasFlag(clang::driver::options::OPT_floop_versioning,
246f04ccadfSVictor Kingi                    clang::driver::options::OPT_fno_loop_versioning, false))
247efae695dSMats Petersson     opts.LoopVersioning = 1;
248bf81ba37STom Eccles 
2490195ec45SDavid Truby   opts.UnrollLoops = args.hasFlag(clang::driver::options::OPT_funroll_loops,
2500195ec45SDavid Truby                                   clang::driver::options::OPT_fno_unroll_loops,
2510195ec45SDavid Truby                                   (opts.OptimizationLevel > 1));
2520195ec45SDavid Truby 
253374e8288STom Eccles   opts.AliasAnalysis = opts.OptimizationLevel > 0;
254ac0015feSTom Eccles 
25504873773SRadu Salavat   // -mframe-pointer=none/non-leaf/all option.
25604873773SRadu Salavat   if (const llvm::opt::Arg *a =
25704873773SRadu Salavat           args.getLastArg(clang::driver::options::OPT_mframe_pointer_EQ)) {
25804873773SRadu Salavat     std::optional<llvm::FramePointerKind> val =
25904873773SRadu Salavat         llvm::StringSwitch<std::optional<llvm::FramePointerKind>>(a->getValue())
26004873773SRadu Salavat             .Case("none", llvm::FramePointerKind::None)
26104873773SRadu Salavat             .Case("non-leaf", llvm::FramePointerKind::NonLeaf)
26204873773SRadu Salavat             .Case("all", llvm::FramePointerKind::All)
26304873773SRadu Salavat             .Default(std::nullopt);
26404873773SRadu Salavat 
26504873773SRadu Salavat     if (!val.has_value()) {
26604873773SRadu Salavat       diags.Report(clang::diag::err_drv_invalid_value)
26704873773SRadu Salavat           << a->getAsString(args) << a->getValue();
26804873773SRadu Salavat     } else
26904873773SRadu Salavat       opts.setFramePointer(val.value());
27004873773SRadu Salavat   }
27104873773SRadu Salavat 
272c3821b8dSTarun Prabhu   for (auto *a : args.filtered(clang::driver::options::OPT_fpass_plugin_EQ))
273c3821b8dSTarun Prabhu     opts.LLVMPassPlugins.push_back(a->getValue());
274c3821b8dSTarun Prabhu 
27540d8c066SJan Sjodin   // -fembed-offload-object option
27640d8c066SJan Sjodin   for (auto *a :
27740d8c066SJan Sjodin        args.filtered(clang::driver::options::OPT_fembed_offload_object_EQ))
27840d8c066SJan Sjodin     opts.OffloadObjects.push_back(a->getValue());
27940d8c066SJan Sjodin 
2800fdfb65eSNadeem, Usman   // -flto=full/thin option.
2810fdfb65eSNadeem, Usman   if (const llvm::opt::Arg *a =
2820fdfb65eSNadeem, Usman           args.getLastArg(clang::driver::options::OPT_flto_EQ)) {
2830fdfb65eSNadeem, Usman     llvm::StringRef s = a->getValue();
2840fdfb65eSNadeem, Usman     assert((s == "full" || s == "thin") && "Unknown LTO mode.");
2850fdfb65eSNadeem, Usman     if (s == "full")
2860fdfb65eSNadeem, Usman       opts.PrepareForFullLTO = true;
2870fdfb65eSNadeem, Usman     else
2880fdfb65eSNadeem, Usman       opts.PrepareForThinLTO = true;
2890fdfb65eSNadeem, Usman   }
2900fdfb65eSNadeem, Usman 
29195943d2fSDominik Adamski   if (const llvm::opt::Arg *a = args.getLastArg(
29295943d2fSDominik Adamski           clang::driver::options::OPT_mcode_object_version_EQ)) {
29395943d2fSDominik Adamski     llvm::StringRef s = a->getValue();
294500846d2SPierre van Houtryve     if (s == "6")
295500846d2SPierre van Houtryve       opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_6;
29695943d2fSDominik Adamski     if (s == "5")
29795943d2fSDominik Adamski       opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_5;
29895943d2fSDominik Adamski     if (s == "4")
29995943d2fSDominik Adamski       opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_4;
30095943d2fSDominik Adamski     if (s == "none")
30195943d2fSDominik Adamski       opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_None;
30295943d2fSDominik Adamski   }
30395943d2fSDominik Adamski 
304f04ccadfSVictor Kingi   // -f[no-]save-optimization-record[=<format>]
305f04ccadfSVictor Kingi   if (const llvm::opt::Arg *a =
306f04ccadfSVictor Kingi           args.getLastArg(clang::driver::options::OPT_opt_record_file))
307f04ccadfSVictor Kingi     opts.OptRecordFile = a->getValue();
308f04ccadfSVictor Kingi 
30991989c67SVictor Kingi   // Optimization file format. Defaults to yaml
310f04ccadfSVictor Kingi   if (const llvm::opt::Arg *a =
311f04ccadfSVictor Kingi           args.getLastArg(clang::driver::options::OPT_opt_record_format))
312f04ccadfSVictor Kingi     opts.OptRecordFormat = a->getValue();
313f04ccadfSVictor Kingi 
31491989c67SVictor Kingi   // Specifies, using a regex, which successful optimization passes(middle and
31591989c67SVictor Kingi   // backend), to include in the final optimization record file generated. If
31691989c67SVictor Kingi   // not provided -fsave-optimization-record will include all passes.
317f04ccadfSVictor Kingi   if (const llvm::opt::Arg *a =
318f04ccadfSVictor Kingi           args.getLastArg(clang::driver::options::OPT_opt_record_passes))
319f04ccadfSVictor Kingi     opts.OptRecordPasses = a->getValue();
320f04ccadfSVictor Kingi 
32191989c67SVictor Kingi   // Create OptRemark that allows printing of all successful optimization
32291989c67SVictor Kingi   // passes applied.
3238e315c6cSVictor Kingi   opts.OptimizationRemark =
3248e315c6cSVictor Kingi       parseOptimizationRemark(diags, args, clang::driver::options::OPT_Rpass_EQ,
3258e315c6cSVictor Kingi                               /*remarkOptName=*/"pass");
32691989c67SVictor Kingi 
32791989c67SVictor Kingi   // Create OptRemark that allows all missed optimization passes to be printed.
3288e315c6cSVictor Kingi   opts.OptimizationRemarkMissed = parseOptimizationRemark(
3298e315c6cSVictor Kingi       diags, args, clang::driver::options::OPT_Rpass_missed_EQ,
3308e315c6cSVictor Kingi       /*remarkOptName=*/"pass-missed");
33191989c67SVictor Kingi 
33291989c67SVictor Kingi   // Create OptRemark that allows all optimization decisions made by LLVM
33391989c67SVictor Kingi   // to be printed.
3348e315c6cSVictor Kingi   opts.OptimizationRemarkAnalysis = parseOptimizationRemark(
3358e315c6cSVictor Kingi       diags, args, clang::driver::options::OPT_Rpass_analysis_EQ,
3368e315c6cSVictor Kingi       /*remarkOptName=*/"pass-analysis");
33791989c67SVictor Kingi 
33812da8ef0SVictor Kingi   if (opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo) {
33912da8ef0SVictor Kingi     // If the user requested a flag that requires source locations available in
34012da8ef0SVictor Kingi     // the backend, make sure that the backend tracks source location
34112da8ef0SVictor Kingi     // information.
34212da8ef0SVictor Kingi     bool needLocTracking = !opts.OptRecordFile.empty() ||
34312da8ef0SVictor Kingi                            !opts.OptRecordPasses.empty() ||
34412da8ef0SVictor Kingi                            !opts.OptRecordFormat.empty() ||
34512da8ef0SVictor Kingi                            opts.OptimizationRemark.hasValidPattern() ||
34612da8ef0SVictor Kingi                            opts.OptimizationRemarkMissed.hasValidPattern() ||
34712da8ef0SVictor Kingi                            opts.OptimizationRemarkAnalysis.hasValidPattern();
34812da8ef0SVictor Kingi 
34912da8ef0SVictor Kingi     if (needLocTracking)
35012da8ef0SVictor Kingi       opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);
35112da8ef0SVictor Kingi   }
35212da8ef0SVictor Kingi 
35333be8341SSergio Afonso   if (auto *a = args.getLastArg(clang::driver::options::OPT_save_temps_EQ))
35433be8341SSergio Afonso     opts.SaveTempsDir = a->getValue();
35533be8341SSergio Afonso 
356839344f0STarun Prabhu   // -record-command-line option.
357839344f0STarun Prabhu   if (const llvm::opt::Arg *a =
358839344f0STarun Prabhu           args.getLastArg(clang::driver::options::OPT_record_command_line)) {
359839344f0STarun Prabhu     opts.RecordCommandLine = a->getValue();
360839344f0STarun Prabhu   }
361839344f0STarun Prabhu 
362b75e7c61SJan Leyonberg   // -mlink-builtin-bitcode
363b75e7c61SJan Leyonberg   for (auto *a :
364b75e7c61SJan Leyonberg        args.filtered(clang::driver::options::OPT_mlink_builtin_bitcode))
365b75e7c61SJan Leyonberg     opts.BuiltinBCLibs.push_back(a->getValue());
366b75e7c61SJan Leyonberg 
367ef5ede52SUsman Nadeem   // -mrelocation-model option.
3680fdfb65eSNadeem, Usman   if (const llvm::opt::Arg *a =
369ef5ede52SUsman Nadeem           args.getLastArg(clang::driver::options::OPT_mrelocation_model)) {
3700fdfb65eSNadeem, Usman     llvm::StringRef modelName = a->getValue();
3710fdfb65eSNadeem, Usman     auto relocModel =
3720fdfb65eSNadeem, Usman         llvm::StringSwitch<std::optional<llvm::Reloc::Model>>(modelName)
373ef5ede52SUsman Nadeem             .Case("static", llvm::Reloc::Static)
374ef5ede52SUsman Nadeem             .Case("pic", llvm::Reloc::PIC_)
375ef5ede52SUsman Nadeem             .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC)
376ef5ede52SUsman Nadeem             .Case("ropi", llvm::Reloc::ROPI)
377ef5ede52SUsman Nadeem             .Case("rwpi", llvm::Reloc::RWPI)
378ef5ede52SUsman Nadeem             .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI)
3799a417395SKazu Hirata             .Default(std::nullopt);
3800fdfb65eSNadeem, Usman     if (relocModel.has_value())
3810fdfb65eSNadeem, Usman       opts.setRelocationModel(*relocModel);
382ef5ede52SUsman Nadeem     else
383ef5ede52SUsman Nadeem       diags.Report(clang::diag::err_drv_invalid_value)
3840fdfb65eSNadeem, Usman           << a->getAsString(args) << modelName;
385ef5ede52SUsman Nadeem   }
386ef5ede52SUsman Nadeem 
387ef5ede52SUsman Nadeem   // -pic-level and -pic-is-pie option.
3880fdfb65eSNadeem, Usman   if (int picLevel = getLastArgIntValue(
389ef5ede52SUsman Nadeem           args, clang::driver::options::OPT_pic_level, 0, diags)) {
3900fdfb65eSNadeem, Usman     if (picLevel > 2)
391ef5ede52SUsman Nadeem       diags.Report(clang::diag::err_drv_invalid_value)
392ef5ede52SUsman Nadeem           << args.getLastArg(clang::driver::options::OPT_pic_level)
393ef5ede52SUsman Nadeem                  ->getAsString(args)
3940fdfb65eSNadeem, Usman           << picLevel;
395ef5ede52SUsman Nadeem 
3960fdfb65eSNadeem, Usman     opts.PICLevel = picLevel;
397ef5ede52SUsman Nadeem     if (args.hasArg(clang::driver::options::OPT_pic_is_pie))
398ef5ede52SUsman Nadeem       opts.IsPIE = 1;
399ef5ede52SUsman Nadeem   }
4001360bfb0SMark Danial 
4019e6b46a9SDavid Truby   // -mcmodel option.
4029e6b46a9SDavid Truby   if (const llvm::opt::Arg *a =
4039e6b46a9SDavid Truby           args.getLastArg(clang::driver::options::OPT_mcmodel_EQ)) {
4049e6b46a9SDavid Truby     llvm::StringRef modelName = a->getValue();
4059e6b46a9SDavid Truby     std::optional<llvm::CodeModel::Model> codeModel = getCodeModel(modelName);
4069e6b46a9SDavid Truby 
4079e6b46a9SDavid Truby     if (codeModel.has_value())
4089e6b46a9SDavid Truby       opts.CodeModel = modelName;
4099e6b46a9SDavid Truby     else
4109e6b46a9SDavid Truby       diags.Report(clang::diag::err_drv_invalid_value)
4119e6b46a9SDavid Truby           << a->getAsString(args) << modelName;
4129e6b46a9SDavid Truby   }
4139e6b46a9SDavid Truby 
4149e6b46a9SDavid Truby   if (const llvm::opt::Arg *arg = args.getLastArg(
4159e6b46a9SDavid Truby           clang::driver::options::OPT_mlarge_data_threshold_EQ)) {
4169e6b46a9SDavid Truby     uint64_t LDT;
4179e6b46a9SDavid Truby     if (llvm::StringRef(arg->getValue()).getAsInteger(/*Radix=*/10, LDT)) {
4189e6b46a9SDavid Truby       diags.Report(clang::diag::err_drv_invalid_value)
4199e6b46a9SDavid Truby           << arg->getSpelling() << arg->getValue();
4209e6b46a9SDavid Truby     }
4219e6b46a9SDavid Truby     opts.LargeDataThreshold = LDT;
4229e6b46a9SDavid Truby   }
4239e6b46a9SDavid Truby 
4241360bfb0SMark Danial   // This option is compatible with -f[no-]underscoring in gfortran.
4251360bfb0SMark Danial   if (args.hasFlag(clang::driver::options::OPT_fno_underscoring,
4261360bfb0SMark Danial                    clang::driver::options::OPT_funderscoring, false)) {
4271360bfb0SMark Danial     opts.Underscoring = 0;
4281360bfb0SMark Danial   }
429869385b1SAndrzej Warzynski }
430869385b1SAndrzej Warzynski 
4312e9439e4SAndrzej Warzynski /// Parses all target input arguments and populates the target
4322e9439e4SAndrzej Warzynski /// options accordingly.
4332e9439e4SAndrzej Warzynski ///
4342e9439e4SAndrzej Warzynski /// \param [in] opts The target options instance to update
4352e9439e4SAndrzej Warzynski /// \param [in] args The list of input arguments (from the compiler invocation)
4361e462fafSAndrzej Warzynski static void parseTargetArgs(TargetOptions &opts, llvm::opt::ArgList &args) {
43702fb5b77SAndrzej Warzynski   if (const llvm::opt::Arg *a =
43802fb5b77SAndrzej Warzynski           args.getLastArg(clang::driver::options::OPT_triple))
43902fb5b77SAndrzej Warzynski     opts.triple = a->getValue();
4403951a734SUsman Nadeem 
4413951a734SUsman Nadeem   if (const llvm::opt::Arg *a =
4423951a734SUsman Nadeem           args.getLastArg(clang::driver::options::OPT_target_cpu))
4433951a734SUsman Nadeem     opts.cpu = a->getValue();
4443951a734SUsman Nadeem 
445f1d3fe7aSAlexis Perry-Holby   if (const llvm::opt::Arg *a =
446f1d3fe7aSAlexis Perry-Holby           args.getLastArg(clang::driver::options::OPT_tune_cpu))
447f1d3fe7aSAlexis Perry-Holby     opts.cpuToTuneFor = a->getValue();
448f1d3fe7aSAlexis Perry-Holby 
4493951a734SUsman Nadeem   for (const llvm::opt::Arg *currentArg :
4503951a734SUsman Nadeem        args.filtered(clang::driver::options::OPT_target_feature))
4513951a734SUsman Nadeem     opts.featuresAsWritten.emplace_back(currentArg->getValue());
4522e9439e4SAndrzej Warzynski 
453697bc748SRenaud Kauffmann   if (args.hasArg(clang::driver::options::OPT_fdisable_real_10))
454697bc748SRenaud Kauffmann     opts.disabledRealKinds.push_back(10);
455697bc748SRenaud Kauffmann 
456697bc748SRenaud Kauffmann   if (args.hasArg(clang::driver::options::OPT_fdisable_real_3))
457697bc748SRenaud Kauffmann     opts.disabledRealKinds.push_back(3);
458697bc748SRenaud Kauffmann 
459697bc748SRenaud Kauffmann   if (args.hasArg(clang::driver::options::OPT_fdisable_integer_2))
460697bc748SRenaud Kauffmann     opts.disabledIntegerKinds.push_back(2);
461697bc748SRenaud Kauffmann 
462697bc748SRenaud Kauffmann   if (args.hasArg(clang::driver::options::OPT_fdisable_integer_16))
463697bc748SRenaud Kauffmann     opts.disabledIntegerKinds.push_back(16);
4648e14c6c1SKelvin Li 
4658e14c6c1SKelvin Li   if (const llvm::opt::Arg *a =
4668e14c6c1SKelvin Li           args.getLastArg(clang::driver::options::OPT_mabi_EQ)) {
4678e14c6c1SKelvin Li     llvm::StringRef V = a->getValue();
4688e14c6c1SKelvin Li     if (V == "vec-extabi") {
4698e14c6c1SKelvin Li       opts.EnableAIXExtendedAltivecABI = true;
4708e14c6c1SKelvin Li     } else if (V == "vec-default") {
4718e14c6c1SKelvin Li       opts.EnableAIXExtendedAltivecABI = false;
4728e14c6c1SKelvin Li     }
4738e14c6c1SKelvin Li   }
474697bc748SRenaud Kauffmann }
475523d7bc6SAndrzej Warzynski // Tweak the frontend configuration based on the frontend action
476523d7bc6SAndrzej Warzynski static void setUpFrontendBasedOnAction(FrontendOptions &opts) {
47723d4c4f3SAndrzej Warzynski   if (opts.programAction == DebugDumpParsingLog)
47823d4c4f3SAndrzej Warzynski     opts.instrumentedParse = true;
47985b86c6fSAndrzej Warzynski 
48023d4c4f3SAndrzej Warzynski   if (opts.programAction == DebugDumpProvenance ||
48123d4c4f3SAndrzej Warzynski       opts.programAction == Fortran::frontend::GetDefinition)
48223d4c4f3SAndrzej Warzynski     opts.needProvenanceRangeToCharBlockMappings = true;
483523d7bc6SAndrzej Warzynski }
484523d7bc6SAndrzej Warzynski 
4850ec3ac9bSJonathon Penix /// Parse the argument specified for the -fconvert=<value> option
4860ec3ac9bSJonathon Penix static std::optional<const char *> parseConvertArg(const char *s) {
4870ec3ac9bSJonathon Penix   return llvm::StringSwitch<std::optional<const char *>>(s)
4880ec3ac9bSJonathon Penix       .Case("unknown", "UNKNOWN")
4890ec3ac9bSJonathon Penix       .Case("native", "NATIVE")
4900ec3ac9bSJonathon Penix       .Case("little-endian", "LITTLE_ENDIAN")
4910ec3ac9bSJonathon Penix       .Case("big-endian", "BIG_ENDIAN")
4920ec3ac9bSJonathon Penix       .Case("swap", "SWAP")
4930ec3ac9bSJonathon Penix       .Default(std::nullopt);
4940ec3ac9bSJonathon Penix }
4950ec3ac9bSJonathon Penix 
4961e462fafSAndrzej Warzynski static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
4976d0fef48SAndrzej Warzynski                               clang::DiagnosticsEngine &diags) {
498dc256a44SAndrzej Warzynski   unsigned numErrorsBefore = diags.getNumErrors();
499760e6c4cSAndrzej Warzynski 
500760e6c4cSAndrzej Warzynski   // By default the frontend driver creates a ParseSyntaxOnly action.
50123d4c4f3SAndrzej Warzynski   opts.programAction = ParseSyntaxOnly;
502760e6c4cSAndrzej Warzynski 
503d18a9aeaSAndrzej Warzynski   // Treat multiple action options as an invocation error. Note that `clang
504d18a9aeaSAndrzej Warzynski   // -cc1` does accept multiple action options, but will only consider the
505d18a9aeaSAndrzej Warzynski   // rightmost one.
506d18a9aeaSAndrzej Warzynski   if (args.hasMultipleArgs(clang::driver::options::OPT_Action_Group)) {
507d18a9aeaSAndrzej Warzynski     const unsigned diagID = diags.getCustomDiagID(
508d18a9aeaSAndrzej Warzynski         clang::DiagnosticsEngine::Error, "Only one action option is allowed");
509d18a9aeaSAndrzej Warzynski     diags.Report(diagID);
510d18a9aeaSAndrzej Warzynski     return false;
511d18a9aeaSAndrzej Warzynski   }
512d18a9aeaSAndrzej Warzynski 
513257b2971SCaroline Concatto   // Identify the action (i.e. opts.ProgramAction)
514257b2971SCaroline Concatto   if (const llvm::opt::Arg *a =
515257b2971SCaroline Concatto           args.getLastArg(clang::driver::options::OPT_Action_Group)) {
516257b2971SCaroline Concatto     switch (a->getOption().getID()) {
517257b2971SCaroline Concatto     default: {
518257b2971SCaroline Concatto       llvm_unreachable("Invalid option in group!");
519257b2971SCaroline Concatto     }
5204c5906cfSCaroline Concatto     case clang::driver::options::OPT_test_io:
52123d4c4f3SAndrzej Warzynski       opts.programAction = InputOutputTest;
5224c5906cfSCaroline Concatto       break;
523d28de0d7SCaroline Concatto     case clang::driver::options::OPT_E:
52423d4c4f3SAndrzej Warzynski       opts.programAction = PrintPreprocessedInput;
525d28de0d7SCaroline Concatto       break;
5267d246cb1SAndrzej Warzynski     case clang::driver::options::OPT_fsyntax_only:
52723d4c4f3SAndrzej Warzynski       opts.programAction = ParseSyntaxOnly;
5287d246cb1SAndrzej Warzynski       break;
52939ecf9d8STom Eccles     case clang::driver::options::OPT_emit_fir:
53039ecf9d8STom Eccles       opts.programAction = EmitFIR;
53139ecf9d8STom Eccles       break;
53239ecf9d8STom Eccles     case clang::driver::options::OPT_emit_hlfir:
53339ecf9d8STom Eccles       opts.programAction = EmitHLFIR;
53469c3309dSAndrzej Warzynski       break;
535e993b20cSAndrzej Warzynski     case clang::driver::options::OPT_emit_llvm:
536e993b20cSAndrzej Warzynski       opts.programAction = EmitLLVM;
537e993b20cSAndrzej Warzynski       break;
538dd56939aSAndrzej Warzynski     case clang::driver::options::OPT_emit_llvm_bc:
539dd56939aSAndrzej Warzynski       opts.programAction = EmitLLVMBitcode;
540dd56939aSAndrzej Warzynski       break;
541e5cdb6c5SAndrzej Warzynski     case clang::driver::options::OPT_emit_obj:
54223d4c4f3SAndrzej Warzynski       opts.programAction = EmitObj;
543e5cdb6c5SAndrzej Warzynski       break;
54438101b4eSAndrzej Warzynski     case clang::driver::options::OPT_S:
54538101b4eSAndrzej Warzynski       opts.programAction = EmitAssembly;
54638101b4eSAndrzej Warzynski       break;
54796d229c9SAndrzej Warzynski     case clang::driver::options::OPT_fdebug_unparse:
54823d4c4f3SAndrzej Warzynski       opts.programAction = DebugUnparse;
54996d229c9SAndrzej Warzynski       break;
550e81b3401SAndrzej Warzynski     case clang::driver::options::OPT_fdebug_unparse_no_sema:
55123d4c4f3SAndrzej Warzynski       opts.programAction = DebugUnparseNoSema;
552e81b3401SAndrzej Warzynski       break;
55396d229c9SAndrzej Warzynski     case clang::driver::options::OPT_fdebug_unparse_with_symbols:
55423d4c4f3SAndrzej Warzynski       opts.programAction = DebugUnparseWithSymbols;
55596d229c9SAndrzej Warzynski       break;
556e00a3ccfSPeter Klausler     case clang::driver::options::OPT_fdebug_unparse_with_modules:
557e00a3ccfSPeter Klausler       opts.programAction = DebugUnparseWithModules;
558e00a3ccfSPeter Klausler       break;
5594bd08dabSFaris Rehman     case clang::driver::options::OPT_fdebug_dump_symbols:
56023d4c4f3SAndrzej Warzynski       opts.programAction = DebugDumpSymbols;
5614bd08dabSFaris Rehman       break;
5624bd08dabSFaris Rehman     case clang::driver::options::OPT_fdebug_dump_parse_tree:
56323d4c4f3SAndrzej Warzynski       opts.programAction = DebugDumpParseTree;
5644bd08dabSFaris Rehman       break;
5658321579bSAndrzej Warzynski     case clang::driver::options::OPT_fdebug_dump_pft:
5668321579bSAndrzej Warzynski       opts.programAction = DebugDumpPFT;
5678321579bSAndrzej Warzynski       break;
568a6be6e31SAndrzej Warzynski     case clang::driver::options::OPT_fdebug_dump_all:
56923d4c4f3SAndrzej Warzynski       opts.programAction = DebugDumpAll;
570a6be6e31SAndrzej Warzynski       break;
571e81b3401SAndrzej Warzynski     case clang::driver::options::OPT_fdebug_dump_parse_tree_no_sema:
57223d4c4f3SAndrzej Warzynski       opts.programAction = DebugDumpParseTreeNoSema;
573e81b3401SAndrzej Warzynski       break;
5744bd08dabSFaris Rehman     case clang::driver::options::OPT_fdebug_dump_provenance:
57523d4c4f3SAndrzej Warzynski       opts.programAction = DebugDumpProvenance;
5764bd08dabSFaris Rehman       break;
577523d7bc6SAndrzej Warzynski     case clang::driver::options::OPT_fdebug_dump_parsing_log:
57823d4c4f3SAndrzej Warzynski       opts.programAction = DebugDumpParsingLog;
579523d7bc6SAndrzej Warzynski       break;
580529f7181SFaris Rehman     case clang::driver::options::OPT_fdebug_measure_parse_tree:
58123d4c4f3SAndrzej Warzynski       opts.programAction = DebugMeasureParseTree;
582529f7181SFaris Rehman       break;
583529f7181SFaris Rehman     case clang::driver::options::OPT_fdebug_pre_fir_tree:
58423d4c4f3SAndrzej Warzynski       opts.programAction = DebugPreFIRTree;
585529f7181SFaris Rehman       break;
586eefda605SAndrzej Warzynski     case clang::driver::options::OPT_fget_symbols_sources:
58723d4c4f3SAndrzej Warzynski       opts.programAction = GetSymbolsSources;
588eefda605SAndrzej Warzynski       break;
589dc256a44SAndrzej Warzynski     case clang::driver::options::OPT_fget_definition:
59023d4c4f3SAndrzej Warzynski       opts.programAction = GetDefinition;
591dc256a44SAndrzej Warzynski       break;
592e1da3297SStuart Ellis     case clang::driver::options::OPT_init_only:
59323d4c4f3SAndrzej Warzynski       opts.programAction = InitOnly;
594e1da3297SStuart Ellis       break;
595d28de0d7SCaroline Concatto 
596257b2971SCaroline Concatto       // TODO:
597e1da3297SStuart Ellis       // case clang::driver::options::OPT_emit_llvm:
598257b2971SCaroline Concatto       // case clang::driver::options::OPT_emit_llvm_only:
599257b2971SCaroline Concatto       // case clang::driver::options::OPT_emit_codegen_only:
600257b2971SCaroline Concatto       // case clang::driver::options::OPT_emit_module:
601257b2971SCaroline Concatto       // (...)
602257b2971SCaroline Concatto     }
603dc256a44SAndrzej Warzynski 
604dc256a44SAndrzej Warzynski     // Parse the values provided with `-fget-definition` (there should be 3
605dc256a44SAndrzej Warzynski     // integers)
606dc256a44SAndrzej Warzynski     if (llvm::opt::OptSpecifier(a->getOption().getID()) ==
607dc256a44SAndrzej Warzynski         clang::driver::options::OPT_fget_definition) {
608dc256a44SAndrzej Warzynski       unsigned optVals[3] = {0, 0, 0};
609dc256a44SAndrzej Warzynski 
610dc256a44SAndrzej Warzynski       for (unsigned i = 0; i < 3; i++) {
611dc256a44SAndrzej Warzynski         llvm::StringRef val = a->getValue(i);
612dc256a44SAndrzej Warzynski 
613dc256a44SAndrzej Warzynski         if (val.getAsInteger(10, optVals[i])) {
614dc256a44SAndrzej Warzynski           // A non-integer was encountered - that's an error.
615dc256a44SAndrzej Warzynski           diags.Report(clang::diag::err_drv_invalid_value)
616dc256a44SAndrzej Warzynski               << a->getOption().getName() << val;
617dc256a44SAndrzej Warzynski           break;
618dc256a44SAndrzej Warzynski         }
619dc256a44SAndrzej Warzynski       }
62023d4c4f3SAndrzej Warzynski       opts.getDefVals.line = optVals[0];
62123d4c4f3SAndrzej Warzynski       opts.getDefVals.startColumn = optVals[1];
62223d4c4f3SAndrzej Warzynski       opts.getDefVals.endColumn = optVals[2];
623dc256a44SAndrzej Warzynski     }
624257b2971SCaroline Concatto   }
625257b2971SCaroline Concatto 
626f52fc591SStuart Ellis   // Parsing -load <dsopath> option and storing shared object path
627f52fc591SStuart Ellis   if (llvm::opt::Arg *a = args.getLastArg(clang::driver::options::OPT_load)) {
628f52fc591SStuart Ellis     opts.plugins.push_back(a->getValue());
629f52fc591SStuart Ellis   }
630f52fc591SStuart Ellis 
631f52fc591SStuart Ellis   // Parsing -plugin <name> option and storing plugin name and setting action
632f52fc591SStuart Ellis   if (const llvm::opt::Arg *a =
633f52fc591SStuart Ellis           args.getLastArg(clang::driver::options::OPT_plugin)) {
634f52fc591SStuart Ellis     opts.programAction = PluginAction;
6351e462fafSAndrzej Warzynski     opts.actionName = a->getValue();
636f52fc591SStuart Ellis   }
637f52fc591SStuart Ellis 
63823d4c4f3SAndrzej Warzynski   opts.outputFile = args.getLastArgValue(clang::driver::options::OPT_o);
63923d4c4f3SAndrzej Warzynski   opts.showHelp = args.hasArg(clang::driver::options::OPT_help);
64023d4c4f3SAndrzej Warzynski   opts.showVersion = args.hasArg(clang::driver::options::OPT_version);
64123d7a6ceSTarun Prabhu   opts.printSupportedCPUs =
64223d7a6ceSTarun Prabhu       args.hasArg(clang::driver::options::OPT_print_supported_cpus);
643257b2971SCaroline Concatto 
644257b2971SCaroline Concatto   // Get the input kind (from the value passed via `-x`)
645257b2971SCaroline Concatto   InputKind dashX(Language::Unknown);
646257b2971SCaroline Concatto   if (const llvm::opt::Arg *a =
647257b2971SCaroline Concatto           args.getLastArg(clang::driver::options::OPT_x)) {
6481e462fafSAndrzej Warzynski     llvm::StringRef xValue = a->getValue();
649257b2971SCaroline Concatto     // Principal languages.
6501e462fafSAndrzej Warzynski     dashX = llvm::StringSwitch<InputKind>(xValue)
6513e782ba2SAndrzej Warzynski                 // Flang does not differentiate between pre-processed and not
6523e782ba2SAndrzej Warzynski                 // pre-processed inputs.
6533e782ba2SAndrzej Warzynski                 .Case("f95", Language::Fortran)
6543e782ba2SAndrzej Warzynski                 .Case("f95-cpp-input", Language::Fortran)
6558a8ef1caSValentin Clement (バレンタイン クレメン)                 // CUDA Fortran
6568a8ef1caSValentin Clement (バレンタイン クレメン)                 .Case("cuda", Language::Fortran)
657257b2971SCaroline Concatto                 .Default(Language::Unknown);
658257b2971SCaroline Concatto 
659cc3c6b61SAndrzej Warzynski     // Flang's intermediate representations.
6601e462fafSAndrzej Warzynski     if (dashX.isUnknown())
6611e462fafSAndrzej Warzynski       dashX = llvm::StringSwitch<InputKind>(xValue)
662257b2971SCaroline Concatto                   .Case("ir", Language::LLVM_IR)
663cc3c6b61SAndrzej Warzynski                   .Case("fir", Language::MLIR)
664cc3c6b61SAndrzej Warzynski                   .Case("mlir", Language::MLIR)
665257b2971SCaroline Concatto                   .Default(Language::Unknown);
666257b2971SCaroline Concatto 
6671e462fafSAndrzej Warzynski     if (dashX.isUnknown())
668257b2971SCaroline Concatto       diags.Report(clang::diag::err_drv_invalid_value)
669257b2971SCaroline Concatto           << a->getAsString(args) << a->getValue();
670257b2971SCaroline Concatto   }
671257b2971SCaroline Concatto 
6724c5906cfSCaroline Concatto   // Collect the input files and save them in our instance of FrontendOptions.
6734c5906cfSCaroline Concatto   std::vector<std::string> inputs =
6744c5906cfSCaroline Concatto       args.getAllArgValues(clang::driver::options::OPT_INPUT);
67523d4c4f3SAndrzej Warzynski   opts.inputs.clear();
6764c5906cfSCaroline Concatto   if (inputs.empty())
6774c5906cfSCaroline Concatto     // '-' is the default input if none is given.
6784c5906cfSCaroline Concatto     inputs.push_back("-");
6794c5906cfSCaroline Concatto   for (unsigned i = 0, e = inputs.size(); i != e; ++i) {
6804c5906cfSCaroline Concatto     InputKind ik = dashX;
6811e462fafSAndrzej Warzynski     if (ik.isUnknown()) {
6821e462fafSAndrzej Warzynski       ik = FrontendOptions::getInputKindForExtension(
6834c5906cfSCaroline Concatto           llvm::StringRef(inputs[i]).rsplit('.').second);
6841e462fafSAndrzej Warzynski       if (ik.isUnknown())
6854c5906cfSCaroline Concatto         ik = Language::Unknown;
6864c5906cfSCaroline Concatto       if (i == 0)
6874c5906cfSCaroline Concatto         dashX = ik;
6884c5906cfSCaroline Concatto     }
6894c5906cfSCaroline Concatto 
69023d4c4f3SAndrzej Warzynski     opts.inputs.emplace_back(std::move(inputs[i]), ik);
6914c5906cfSCaroline Concatto   }
6923a1513c1SFaris Rehman 
69323d4c4f3SAndrzej Warzynski   // Set fortranForm based on options -ffree-form and -ffixed-form.
69474d5c3c0SPeter Steinfeld   if (const auto *arg =
69574d5c3c0SPeter Steinfeld           args.getLastArg(clang::driver::options::OPT_ffixed_form,
6963a1513c1SFaris Rehman                           clang::driver::options::OPT_ffree_form)) {
69723d4c4f3SAndrzej Warzynski     opts.fortranForm =
6983a1513c1SFaris Rehman         arg->getOption().matches(clang::driver::options::OPT_ffixed_form)
6993a1513c1SFaris Rehman             ? FortranForm::FixedForm
7003a1513c1SFaris Rehman             : FortranForm::FreeForm;
7013a1513c1SFaris Rehman   }
7023a1513c1SFaris Rehman 
70323d4c4f3SAndrzej Warzynski   // Set fixedFormColumns based on -ffixed-line-length=<value>
7043a1513c1SFaris Rehman   if (const auto *arg =
7053a1513c1SFaris Rehman           args.getLastArg(clang::driver::options::OPT_ffixed_line_length_EQ)) {
7063a1513c1SFaris Rehman     llvm::StringRef argValue = llvm::StringRef(arg->getValue());
7073a1513c1SFaris Rehman     std::int64_t columns = -1;
7083a1513c1SFaris Rehman     if (argValue == "none") {
7093a1513c1SFaris Rehman       columns = 0;
7103a1513c1SFaris Rehman     } else if (argValue.getAsInteger(/*Radix=*/10, columns)) {
7113a1513c1SFaris Rehman       columns = -1;
7123a1513c1SFaris Rehman     }
7133a1513c1SFaris Rehman     if (columns < 0) {
714aefbfbcbSNick Desaulniers       diags.Report(clang::diag::err_drv_negative_columns)
715aefbfbcbSNick Desaulniers           << arg->getOption().getName() << arg->getValue();
7163a1513c1SFaris Rehman     } else if (columns == 0) {
71723d4c4f3SAndrzej Warzynski       opts.fixedFormColumns = 1000000;
7183a1513c1SFaris Rehman     } else if (columns < 7) {
719aefbfbcbSNick Desaulniers       diags.Report(clang::diag::err_drv_small_columns)
720aefbfbcbSNick Desaulniers           << arg->getOption().getName() << arg->getValue() << "7";
7213a1513c1SFaris Rehman     } else {
72223d4c4f3SAndrzej Warzynski       opts.fixedFormColumns = columns;
7233a1513c1SFaris Rehman     }
7243a1513c1SFaris Rehman   }
7256d48a1a5SFaris Rehman 
7260ec3ac9bSJonathon Penix   // Set conversion based on -fconvert=<value>
7270ec3ac9bSJonathon Penix   if (const auto *arg =
7280ec3ac9bSJonathon Penix           args.getLastArg(clang::driver::options::OPT_fconvert_EQ)) {
7290ec3ac9bSJonathon Penix     const char *argValue = arg->getValue();
7300ec3ac9bSJonathon Penix     if (auto convert = parseConvertArg(argValue))
7310ec3ac9bSJonathon Penix       opts.envDefaults.push_back({"FORT_CONVERT", *convert});
7320ec3ac9bSJonathon Penix     else
7330ec3ac9bSJonathon Penix       diags.Report(clang::diag::err_drv_invalid_value)
7340ec3ac9bSJonathon Penix           << arg->getAsString(args) << argValue;
7350ec3ac9bSJonathon Penix   }
7360ec3ac9bSJonathon Penix 
73755a96155SAndrzej Warzynski   // -f{no-}implicit-none
73823d4c4f3SAndrzej Warzynski   opts.features.Enable(
73910826ea7SFaris Rehman       Fortran::common::LanguageFeature::ImplicitNoneTypeAlways,
74055a96155SAndrzej Warzynski       args.hasFlag(clang::driver::options::OPT_fimplicit_none,
74155a96155SAndrzej Warzynski                    clang::driver::options::OPT_fno_implicit_none, false));
74255a96155SAndrzej Warzynski 
74355a96155SAndrzej Warzynski   // -f{no-}backslash
74423d4c4f3SAndrzej Warzynski   opts.features.Enable(Fortran::common::LanguageFeature::BackslashEscapes,
74555a96155SAndrzej Warzynski                        args.hasFlag(clang::driver::options::OPT_fbackslash,
74674d5c3c0SPeter Steinfeld                                     clang::driver::options::OPT_fno_backslash,
74774d5c3c0SPeter Steinfeld                                     false));
74855a96155SAndrzej Warzynski 
74955a96155SAndrzej Warzynski   // -f{no-}logical-abbreviations
75074d5c3c0SPeter Steinfeld   opts.features.Enable(
75174d5c3c0SPeter Steinfeld       Fortran::common::LanguageFeature::LogicalAbbreviations,
75255a96155SAndrzej Warzynski       args.hasFlag(clang::driver::options::OPT_flogical_abbreviations,
75374d5c3c0SPeter Steinfeld                    clang::driver::options::OPT_fno_logical_abbreviations,
75474d5c3c0SPeter Steinfeld                    false));
75555a96155SAndrzej Warzynski 
756fc97d2e6SPeter Klausler   // -f{no-}unsigned
757fc97d2e6SPeter Klausler   opts.features.Enable(Fortran::common::LanguageFeature::Unsigned,
758fc97d2e6SPeter Klausler                        args.hasFlag(clang::driver::options::OPT_funsigned,
759fc97d2e6SPeter Klausler                                     clang::driver::options::OPT_fno_unsigned,
760fc97d2e6SPeter Klausler                                     false));
761fc97d2e6SPeter Klausler 
76255a96155SAndrzej Warzynski   // -f{no-}xor-operator
76374d5c3c0SPeter Steinfeld   opts.features.Enable(
76474d5c3c0SPeter Steinfeld       Fortran::common::LanguageFeature::XOROperator,
76555a96155SAndrzej Warzynski       args.hasFlag(clang::driver::options::OPT_fxor_operator,
76655a96155SAndrzej Warzynski                    clang::driver::options::OPT_fno_xor_operator, false));
76755a96155SAndrzej Warzynski 
768996ef895SPeter Klausler   // -fno-automatic
769996ef895SPeter Klausler   if (args.hasArg(clang::driver::options::OPT_fno_automatic)) {
770996ef895SPeter Klausler     opts.features.Enable(Fortran::common::LanguageFeature::DefaultSave);
771996ef895SPeter Klausler   }
772996ef895SPeter Klausler 
773*7211bf48SjeanPerier   // -f{no}-save-main-program
774*7211bf48SjeanPerier   opts.features.Enable(
775*7211bf48SjeanPerier       Fortran::common::LanguageFeature::SaveMainProgram,
776*7211bf48SjeanPerier       args.hasFlag(clang::driver::options::OPT_fsave_main_program,
777*7211bf48SjeanPerier                    clang::driver::options::OPT_fno_save_main_program, false));
778645c1ee8SjeanPerier 
77910826ea7SFaris Rehman   if (args.hasArg(
78010826ea7SFaris Rehman           clang::driver::options::OPT_falternative_parameter_statement)) {
78123d4c4f3SAndrzej Warzynski     opts.features.Enable(Fortran::common::LanguageFeature::OldStyleParameter);
78210826ea7SFaris Rehman   }
78310826ea7SFaris Rehman   if (const llvm::opt::Arg *arg =
78410826ea7SFaris Rehman           args.getLastArg(clang::driver::options::OPT_finput_charset_EQ)) {
78510826ea7SFaris Rehman     llvm::StringRef argValue = arg->getValue();
78610826ea7SFaris Rehman     if (argValue == "utf-8") {
78723d4c4f3SAndrzej Warzynski       opts.encoding = Fortran::parser::Encoding::UTF_8;
78810826ea7SFaris Rehman     } else if (argValue == "latin-1") {
78923d4c4f3SAndrzej Warzynski       opts.encoding = Fortran::parser::Encoding::LATIN_1;
79010826ea7SFaris Rehman     } else {
79110826ea7SFaris Rehman       diags.Report(clang::diag::err_drv_invalid_value)
79210826ea7SFaris Rehman           << arg->getAsString(args) << argValue;
79310826ea7SFaris Rehman     }
79410826ea7SFaris Rehman   }
795523d7bc6SAndrzej Warzynski 
796523d7bc6SAndrzej Warzynski   setUpFrontendBasedOnAction(opts);
79723d4c4f3SAndrzej Warzynski   opts.dashX = dashX;
798dc256a44SAndrzej Warzynski 
799dc256a44SAndrzej Warzynski   return diags.getNumErrors() == numErrorsBefore;
800257b2971SCaroline Concatto }
801257b2971SCaroline Concatto 
802cd4abc52SArnamoy Bhattacharyya // Generate the path to look for intrinsic modules
8038dc474c6Smadanial0 static std::string getIntrinsicDir(const char *argv) {
804cd4abc52SArnamoy Bhattacharyya   // TODO: Find a system independent API
805cd4abc52SArnamoy Bhattacharyya   llvm::SmallString<128> driverPath;
8068dc474c6Smadanial0   driverPath.assign(llvm::sys::fs::getMainExecutable(argv, nullptr));
807cd4abc52SArnamoy Bhattacharyya   llvm::sys::path::remove_filename(driverPath);
808cd4abc52SArnamoy Bhattacharyya   driverPath.append("/../include/flang/");
809cd4abc52SArnamoy Bhattacharyya   return std::string(driverPath);
810cd4abc52SArnamoy Bhattacharyya }
811cd4abc52SArnamoy Bhattacharyya 
812dda366edSAndrzej Warzynski // Generate the path to look for OpenMP headers
8138dc474c6Smadanial0 static std::string getOpenMPHeadersDir(const char *argv) {
814dda366edSAndrzej Warzynski   llvm::SmallString<128> includePath;
8158dc474c6Smadanial0   includePath.assign(llvm::sys::fs::getMainExecutable(argv, nullptr));
816dda366edSAndrzej Warzynski   llvm::sys::path::remove_filename(includePath);
817dda366edSAndrzej Warzynski   includePath.append("/../include/flang/OpenMP/");
818dda366edSAndrzej Warzynski   return std::string(includePath);
819dda366edSAndrzej Warzynski }
820dda366edSAndrzej Warzynski 
8217809fa20SFaris Rehman /// Parses all preprocessor input arguments and populates the preprocessor
8227809fa20SFaris Rehman /// options accordingly.
8237809fa20SFaris Rehman ///
8247809fa20SFaris Rehman /// \param [in] opts The preprocessor options instance
8257809fa20SFaris Rehman /// \param [out] args The list of input arguments
82674d5c3c0SPeter Steinfeld static void parsePreprocessorArgs(Fortran::frontend::PreprocessorOptions &opts,
82774d5c3c0SPeter Steinfeld                                   llvm::opt::ArgList &args) {
8287809fa20SFaris Rehman   // Add macros from the command line.
82974d5c3c0SPeter Steinfeld   for (const auto *currentArg : args.filtered(clang::driver::options::OPT_D,
83074d5c3c0SPeter Steinfeld                                               clang::driver::options::OPT_U)) {
8317809fa20SFaris Rehman     if (currentArg->getOption().matches(clang::driver::options::OPT_D)) {
8327809fa20SFaris Rehman       opts.addMacroDef(currentArg->getValue());
8337809fa20SFaris Rehman     } else {
8347809fa20SFaris Rehman       opts.addMacroUndef(currentArg->getValue());
8357809fa20SFaris Rehman     }
8367809fa20SFaris Rehman   }
83787dfd5e0SFaris Rehman 
83887dfd5e0SFaris Rehman   // Add the ordered list of -I's.
83987dfd5e0SFaris Rehman   for (const auto *currentArg : args.filtered(clang::driver::options::OPT_I))
84087dfd5e0SFaris Rehman     opts.searchDirectoriesFromDashI.emplace_back(currentArg->getValue());
841cd4abc52SArnamoy Bhattacharyya 
842cd4abc52SArnamoy Bhattacharyya   // Prepend the ordered list of -intrinsic-modules-path
843cd4abc52SArnamoy Bhattacharyya   // to the default location to search.
844cd4abc52SArnamoy Bhattacharyya   for (const auto *currentArg :
845cd4abc52SArnamoy Bhattacharyya        args.filtered(clang::driver::options::OPT_fintrinsic_modules_path))
846cd4abc52SArnamoy Bhattacharyya     opts.searchDirectoriesFromIntrModPath.emplace_back(currentArg->getValue());
847b83a4450SAndrzej Warzynski 
848b83a4450SAndrzej Warzynski   // -cpp/-nocpp
849b83a4450SAndrzej Warzynski   if (const auto *currentArg = args.getLastArg(
850b83a4450SAndrzej Warzynski           clang::driver::options::OPT_cpp, clang::driver::options::OPT_nocpp))
85123d4c4f3SAndrzej Warzynski     opts.macrosFlag =
852b83a4450SAndrzej Warzynski         (currentArg->getOption().matches(clang::driver::options::OPT_cpp))
853b83a4450SAndrzej Warzynski             ? PPMacrosFlag::Include
854b83a4450SAndrzej Warzynski             : PPMacrosFlag::Exclude;
8553338ef93Speter klausler 
8563338ef93Speter klausler   opts.noReformat = args.hasArg(clang::driver::options::OPT_fno_reformat);
8574dfed691SPeter Klausler   opts.preprocessIncludeLines =
8584dfed691SPeter Klausler       args.hasArg(clang::driver::options::OPT_fpreprocess_include_lines);
8593338ef93Speter klausler   opts.noLineDirectives = args.hasArg(clang::driver::options::OPT_P);
8607d60232bSKrzysztof Parzyszek   opts.showMacros = args.hasArg(clang::driver::options::OPT_dM);
8617809fa20SFaris Rehman }
8627809fa20SFaris Rehman 
863985a42fdSArnamoy Bhattacharyya /// Parses all semantic related arguments and populates the variables
8646d0fef48SAndrzej Warzynski /// options accordingly. Returns false if new errors are generated.
8656d0fef48SAndrzej Warzynski static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
866985a42fdSArnamoy Bhattacharyya                           clang::DiagnosticsEngine &diags) {
8676d0fef48SAndrzej Warzynski   unsigned numErrorsBefore = diags.getNumErrors();
868985a42fdSArnamoy Bhattacharyya 
8691fd4beecSArnamoy Bhattacharyya   // -J/module-dir option
87084a0a3d3SPaul Osmialowski   std::vector<std::string> moduleDirList =
871985a42fdSArnamoy Bhattacharyya       args.getAllArgValues(clang::driver::options::OPT_module_dir);
87284a0a3d3SPaul Osmialowski   // User can only specify one -J/-module-dir directory, but may repeat
87384a0a3d3SPaul Osmialowski   // -J/-module-dir as long as the directory is the same each time.
874985a42fdSArnamoy Bhattacharyya   // https://gcc.gnu.org/onlinedocs/gfortran/Directory-Options.html
87584a0a3d3SPaul Osmialowski   std::sort(moduleDirList.begin(), moduleDirList.end());
87684a0a3d3SPaul Osmialowski   moduleDirList.erase(std::unique(moduleDirList.begin(), moduleDirList.end()),
87784a0a3d3SPaul Osmialowski                       moduleDirList.end());
878985a42fdSArnamoy Bhattacharyya   if (moduleDirList.size() > 1) {
879985a42fdSArnamoy Bhattacharyya     const unsigned diagID =
880985a42fdSArnamoy Bhattacharyya         diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
88184a0a3d3SPaul Osmialowski                               "Only one '-module-dir/-J' directory allowed. "
88284a0a3d3SPaul Osmialowski                               "'-module-dir/-J' may be given multiple times "
88384a0a3d3SPaul Osmialowski                               "but the directory must be the same each time.");
884985a42fdSArnamoy Bhattacharyya     diags.Report(diagID);
885985a42fdSArnamoy Bhattacharyya   }
886985a42fdSArnamoy Bhattacharyya   if (moduleDirList.size() == 1)
8871e462fafSAndrzej Warzynski     res.setModuleDir(moduleDirList[0]);
8881fd4beecSArnamoy Bhattacharyya 
8891fd4beecSArnamoy Bhattacharyya   // -fdebug-module-writer option
8901fd4beecSArnamoy Bhattacharyya   if (args.hasArg(clang::driver::options::OPT_fdebug_module_writer)) {
8911e462fafSAndrzej Warzynski     res.setDebugModuleDir(true);
8921fd4beecSArnamoy Bhattacharyya   }
8936d0fef48SAndrzej Warzynski 
89465987954SPeter Klausler   // -fhermetic-module-files option
89565987954SPeter Klausler   if (args.hasArg(clang::driver::options::OPT_fhermetic_module_files)) {
89665987954SPeter Klausler     res.setHermeticModuleFileOutput(true);
89765987954SPeter Klausler   }
89865987954SPeter Klausler 
89920bd2142SAndrzej Warzynski   // -module-suffix
90020bd2142SAndrzej Warzynski   if (const auto *moduleSuffix =
90120bd2142SAndrzej Warzynski           args.getLastArg(clang::driver::options::OPT_module_suffix)) {
9021e462fafSAndrzej Warzynski     res.setModuleFileSuffix(moduleSuffix->getValue());
90320bd2142SAndrzej Warzynski   }
90420bd2142SAndrzej Warzynski 
90555a96155SAndrzej Warzynski   // -f{no-}analyzed-objects-for-unparse
9061e462fafSAndrzej Warzynski   res.setUseAnalyzedObjectsForUnparse(args.hasFlag(
9071e462fafSAndrzej Warzynski       clang::driver::options::OPT_fanalyzed_objects_for_unparse,
90855a96155SAndrzej Warzynski       clang::driver::options::OPT_fno_analyzed_objects_for_unparse, true));
9092a7bb849SAndrzej Warzynski 
9106d0fef48SAndrzej Warzynski   return diags.getNumErrors() == numErrorsBefore;
911985a42fdSArnamoy Bhattacharyya }
912985a42fdSArnamoy Bhattacharyya 
9137416e8a8SArnamoy Bhattacharyya /// Parses all diagnostics related arguments and populates the variables
9146d0fef48SAndrzej Warzynski /// options accordingly. Returns false if new errors are generated.
9156d0fef48SAndrzej Warzynski static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
9167416e8a8SArnamoy Bhattacharyya                           clang::DiagnosticsEngine &diags) {
9176d0fef48SAndrzej Warzynski   unsigned numErrorsBefore = diags.getNumErrors();
9186d0fef48SAndrzej Warzynski 
9197416e8a8SArnamoy Bhattacharyya   // -Werror option
9207416e8a8SArnamoy Bhattacharyya   // TODO: Currently throws a Diagnostic for anything other than -W<error>,
9217416e8a8SArnamoy Bhattacharyya   // this has to change when other -W<opt>'s are supported.
9227416e8a8SArnamoy Bhattacharyya   if (args.hasArg(clang::driver::options::OPT_W_Joined)) {
923ce3a1c59SEthan Luis McDonough     const auto &wArgs =
924ce3a1c59SEthan Luis McDonough         args.getAllArgValues(clang::driver::options::OPT_W_Joined);
925ce3a1c59SEthan Luis McDonough     for (const auto &wArg : wArgs) {
926ce3a1c59SEthan Luis McDonough       if (wArg == "error") {
9271e462fafSAndrzej Warzynski         res.setWarnAsErr(true);
9287416e8a8SArnamoy Bhattacharyya       } else {
9297416e8a8SArnamoy Bhattacharyya         const unsigned diagID =
9307416e8a8SArnamoy Bhattacharyya             diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
9317416e8a8SArnamoy Bhattacharyya                                   "Only `-Werror` is supported currently.");
9327416e8a8SArnamoy Bhattacharyya         diags.Report(diagID);
9337416e8a8SArnamoy Bhattacharyya       }
9347416e8a8SArnamoy Bhattacharyya     }
935ce3a1c59SEthan Luis McDonough   }
9366d0fef48SAndrzej Warzynski 
93706eb10daSBrad Richardson   // Default to off for `flang -fc1`.
93843084160SPeixin Qiao   res.getFrontendOpts().showColors =
93943084160SPeixin Qiao       parseShowColorsArgs(args, /*defaultDiagColor=*/false);
94043084160SPeixin Qiao 
9418e315c6cSVictor Kingi   // Honor color diagnostics.
9428e315c6cSVictor Kingi   res.getDiagnosticOpts().ShowColors = res.getFrontendOpts().showColors;
9438e315c6cSVictor Kingi 
9446d0fef48SAndrzej Warzynski   return diags.getNumErrors() == numErrorsBefore;
9457416e8a8SArnamoy Bhattacharyya }
9467416e8a8SArnamoy Bhattacharyya 
947ab971c29SArnamoy Bhattacharyya /// Parses all Dialect related arguments and populates the variables
9486d0fef48SAndrzej Warzynski /// options accordingly. Returns false if new errors are generated.
9496d0fef48SAndrzej Warzynski static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
950ab971c29SArnamoy Bhattacharyya                              clang::DiagnosticsEngine &diags) {
9516d0fef48SAndrzej Warzynski   unsigned numErrorsBefore = diags.getNumErrors();
952ab971c29SArnamoy Bhattacharyya 
953ab971c29SArnamoy Bhattacharyya   // -fdefault* family
954ab971c29SArnamoy Bhattacharyya   if (args.hasArg(clang::driver::options::OPT_fdefault_real_8)) {
9551e462fafSAndrzej Warzynski     res.getDefaultKinds().set_defaultRealKind(8);
9561e462fafSAndrzej Warzynski     res.getDefaultKinds().set_doublePrecisionKind(16);
957ab971c29SArnamoy Bhattacharyya   }
958ab971c29SArnamoy Bhattacharyya   if (args.hasArg(clang::driver::options::OPT_fdefault_integer_8)) {
9591e462fafSAndrzej Warzynski     res.getDefaultKinds().set_defaultIntegerKind(8);
9601e462fafSAndrzej Warzynski     res.getDefaultKinds().set_subscriptIntegerKind(8);
9611e462fafSAndrzej Warzynski     res.getDefaultKinds().set_sizeIntegerKind(8);
962fc43c4f0SKiran Chandramohan     res.getDefaultKinds().set_defaultLogicalKind(8);
963ab971c29SArnamoy Bhattacharyya   }
964ab971c29SArnamoy Bhattacharyya   if (args.hasArg(clang::driver::options::OPT_fdefault_double_8)) {
965ab971c29SArnamoy Bhattacharyya     if (!args.hasArg(clang::driver::options::OPT_fdefault_real_8)) {
966ab971c29SArnamoy Bhattacharyya       // -fdefault-double-8 has to be used with -fdefault-real-8
967ab971c29SArnamoy Bhattacharyya       // to be compatible with gfortran
96874d5c3c0SPeter Steinfeld       const unsigned diagID = diags.getCustomDiagID(
96974d5c3c0SPeter Steinfeld           clang::DiagnosticsEngine::Error,
970ab971c29SArnamoy Bhattacharyya           "Use of `-fdefault-double-8` requires `-fdefault-real-8`");
971ab971c29SArnamoy Bhattacharyya       diags.Report(diagID);
972ab971c29SArnamoy Bhattacharyya     }
973ab971c29SArnamoy Bhattacharyya     // https://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html
9741e462fafSAndrzej Warzynski     res.getDefaultKinds().set_doublePrecisionKind(8);
975ab971c29SArnamoy Bhattacharyya   }
976ab971c29SArnamoy Bhattacharyya   if (args.hasArg(clang::driver::options::OPT_flarge_sizes))
9771e462fafSAndrzej Warzynski     res.getDefaultKinds().set_sizeIntegerKind(8);
978ab971c29SArnamoy Bhattacharyya 
9798a8ef1caSValentin Clement (バレンタイン クレメン)   // -x cuda
9808a8ef1caSValentin Clement (バレンタイン クレメン)   auto language = args.getLastArgValue(clang::driver::options::OPT_x);
981f841ca0cSKazu Hirata   if (language == "cuda") {
9828a8ef1caSValentin Clement (バレンタイン クレメン)     res.getFrontendOpts().features.Enable(
9838a8ef1caSValentin Clement (バレンタイン クレメン)         Fortran::common::LanguageFeature::CUDA);
9848a8ef1caSValentin Clement (バレンタイン クレメン)   }
9858a8ef1caSValentin Clement (バレンタイン クレメン) 
9869dadb1f6SSergio Afonso   // -fopenacc
987ab971c29SArnamoy Bhattacharyya   if (args.hasArg(clang::driver::options::OPT_fopenacc)) {
9881e462fafSAndrzej Warzynski     res.getFrontendOpts().features.Enable(
989ab971c29SArnamoy Bhattacharyya         Fortran::common::LanguageFeature::OpenACC);
990ab971c29SArnamoy Bhattacharyya   }
9919dadb1f6SSergio Afonso 
9929dadb1f6SSergio Afonso   // -pedantic
9939dadb1f6SSergio Afonso   if (args.hasArg(clang::driver::options::OPT_pedantic)) {
9949dadb1f6SSergio Afonso     res.setEnableConformanceChecks();
9959dadb1f6SSergio Afonso     res.setEnableUsageChecks();
9969dadb1f6SSergio Afonso   }
9979dadb1f6SSergio Afonso 
9989dadb1f6SSergio Afonso   // -w
9999dadb1f6SSergio Afonso   if (args.hasArg(clang::driver::options::OPT_w))
10009dadb1f6SSergio Afonso     res.setDisableWarnings();
10019dadb1f6SSergio Afonso 
10029dadb1f6SSergio Afonso   // -std=f2018
10039dadb1f6SSergio Afonso   // TODO: Set proper options when more fortran standards
10049dadb1f6SSergio Afonso   // are supported.
10059dadb1f6SSergio Afonso   if (args.hasArg(clang::driver::options::OPT_std_EQ)) {
10069dadb1f6SSergio Afonso     auto standard = args.getLastArgValue(clang::driver::options::OPT_std_EQ);
10079dadb1f6SSergio Afonso     // We only allow f2018 as the given standard
10089dadb1f6SSergio Afonso     if (standard == "f2018") {
10099dadb1f6SSergio Afonso       res.setEnableConformanceChecks();
10109dadb1f6SSergio Afonso     } else {
10119dadb1f6SSergio Afonso       const unsigned diagID =
10129dadb1f6SSergio Afonso           diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
10139dadb1f6SSergio Afonso                                 "Only -std=f2018 is allowed currently.");
10149dadb1f6SSergio Afonso       diags.Report(diagID);
10159dadb1f6SSergio Afonso     }
10169dadb1f6SSergio Afonso   }
10179dadb1f6SSergio Afonso   return diags.getNumErrors() == numErrorsBefore;
10189dadb1f6SSergio Afonso }
10199dadb1f6SSergio Afonso 
10209dadb1f6SSergio Afonso /// Parses all OpenMP related arguments if the -fopenmp option is present,
10219dadb1f6SSergio Afonso /// populating the \c res object accordingly. Returns false if new errors are
10229dadb1f6SSergio Afonso /// generated.
10239dadb1f6SSergio Afonso static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
10249dadb1f6SSergio Afonso                             clang::DiagnosticsEngine &diags) {
10254f130fa9STom Eccles   llvm::opt::Arg *arg = args.getLastArg(clang::driver::options::OPT_fopenmp,
10264f130fa9STom Eccles                                         clang::driver::options::OPT_fno_openmp);
10274f130fa9STom Eccles   if (!arg || arg->getOption().matches(clang::driver::options::OPT_fno_openmp))
10289dadb1f6SSergio Afonso     return true;
10299dadb1f6SSergio Afonso 
10309dadb1f6SSergio Afonso   unsigned numErrorsBefore = diags.getNumErrors();
10319dadb1f6SSergio Afonso   llvm::Triple t(res.getTargetOpts().triple);
10329dadb1f6SSergio Afonso 
1033d93bdd8bSDominik Adamski   // By default OpenMP is set to 1.1 version
1034d93bdd8bSDominik Adamski   res.getLangOpts().OpenMPVersion = 11;
10351e462fafSAndrzej Warzynski   res.getFrontendOpts().features.Enable(
1036ab971c29SArnamoy Bhattacharyya       Fortran::common::LanguageFeature::OpenMP);
1037d93bdd8bSDominik Adamski   if (int Version = getLastArgIntValue(
1038d93bdd8bSDominik Adamski           args, clang::driver::options::OPT_fopenmp_version_EQ,
1039d93bdd8bSDominik Adamski           res.getLangOpts().OpenMPVersion, diags)) {
1040d93bdd8bSDominik Adamski     res.getLangOpts().OpenMPVersion = Version;
1041d93bdd8bSDominik Adamski   }
1042b9549261SSergio Afonso   if (args.hasArg(clang::driver::options::OPT_fopenmp_force_usm)) {
1043b9549261SSergio Afonso     res.getLangOpts().OpenMPForceUSM = 1;
1044b9549261SSergio Afonso   }
104563ca93c7SSergio Afonso   if (args.hasArg(clang::driver::options::OPT_fopenmp_is_target_device)) {
104663ca93c7SSergio Afonso     res.getLangOpts().OpenMPIsTargetDevice = 1;
104753152f12SAndrew Gozillon 
10482e634367SAndrew Gozillon     // Get OpenMP host file path if any and report if a non existent file is
10492e634367SAndrew Gozillon     // found
10502e634367SAndrew Gozillon     if (auto *arg = args.getLastArg(
10512e634367SAndrew Gozillon             clang::driver::options::OPT_fopenmp_host_ir_file_path)) {
10522e634367SAndrew Gozillon       res.getLangOpts().OMPHostIRFile = arg->getValue();
10532e634367SAndrew Gozillon       if (!llvm::sys::fs::exists(res.getLangOpts().OMPHostIRFile))
10542e634367SAndrew Gozillon         diags.Report(clang::diag::err_drv_omp_host_ir_file_not_found)
10552e634367SAndrew Gozillon             << res.getLangOpts().OMPHostIRFile;
10562e634367SAndrew Gozillon     }
10572e634367SAndrew Gozillon 
105853152f12SAndrew Gozillon     if (args.hasFlag(
105953152f12SAndrew Gozillon             clang::driver::options::OPT_fopenmp_assume_teams_oversubscription,
106053152f12SAndrew Gozillon             clang::driver::options::
106153152f12SAndrew Gozillon                 OPT_fno_openmp_assume_teams_oversubscription,
106253152f12SAndrew Gozillon             /*Default=*/false))
106353152f12SAndrew Gozillon       res.getLangOpts().OpenMPTeamSubscription = true;
106453152f12SAndrew Gozillon 
10659dadb1f6SSergio Afonso     if (args.hasArg(clang::driver::options::OPT_fopenmp_assume_no_thread_state))
106653152f12SAndrew Gozillon       res.getLangOpts().OpenMPNoThreadState = 1;
106753152f12SAndrew Gozillon 
106853152f12SAndrew Gozillon     if (args.hasArg(
106953152f12SAndrew Gozillon             clang::driver::options::OPT_fopenmp_assume_no_nested_parallelism))
107053152f12SAndrew Gozillon       res.getLangOpts().OpenMPNoNestedParallelism = 1;
107153152f12SAndrew Gozillon 
10729dadb1f6SSergio Afonso     if (args.hasFlag(
10739dadb1f6SSergio Afonso             clang::driver::options::OPT_fopenmp_assume_threads_oversubscription,
107453152f12SAndrew Gozillon             clang::driver::options::
107553152f12SAndrew Gozillon                 OPT_fno_openmp_assume_threads_oversubscription,
107653152f12SAndrew Gozillon             /*Default=*/false))
107753152f12SAndrew Gozillon       res.getLangOpts().OpenMPThreadSubscription = true;
107853152f12SAndrew Gozillon 
107953152f12SAndrew Gozillon     if ((args.hasArg(clang::driver::options::OPT_fopenmp_target_debug) ||
108053152f12SAndrew Gozillon          args.hasArg(clang::driver::options::OPT_fopenmp_target_debug_EQ))) {
108153152f12SAndrew Gozillon       res.getLangOpts().OpenMPTargetDebug = getLastArgIntValue(
108253152f12SAndrew Gozillon           args, clang::driver::options::OPT_fopenmp_target_debug_EQ,
108353152f12SAndrew Gozillon           res.getLangOpts().OpenMPTargetDebug, diags);
108453152f12SAndrew Gozillon 
108553152f12SAndrew Gozillon       if (!res.getLangOpts().OpenMPTargetDebug &&
108653152f12SAndrew Gozillon           args.hasArg(clang::driver::options::OPT_fopenmp_target_debug))
108753152f12SAndrew Gozillon         res.getLangOpts().OpenMPTargetDebug = 1;
108853152f12SAndrew Gozillon     }
1089f443fbc4SDominik Adamski     if (args.hasArg(clang::driver::options::OPT_nogpulib))
1090f443fbc4SDominik Adamski       res.getLangOpts().NoGPULib = 1;
1091e002a38bSAndrew Gozillon   }
109240340cf9SSergio Afonso 
109340340cf9SSergio Afonso   switch (llvm::Triple(res.getTargetOpts().triple).getArch()) {
109440340cf9SSergio Afonso   case llvm::Triple::nvptx:
109540340cf9SSergio Afonso   case llvm::Triple::nvptx64:
109640340cf9SSergio Afonso   case llvm::Triple::amdgcn:
109740340cf9SSergio Afonso     if (!res.getLangOpts().OpenMPIsTargetDevice) {
109840340cf9SSergio Afonso       const unsigned diagID = diags.getCustomDiagID(
109940340cf9SSergio Afonso           clang::DiagnosticsEngine::Error,
110040340cf9SSergio Afonso           "OpenMP AMDGPU/NVPTX is only prepared to deal with device code.");
110140340cf9SSergio Afonso       diags.Report(diagID);
110240340cf9SSergio Afonso     }
110340340cf9SSergio Afonso     res.getLangOpts().OpenMPIsGPU = 1;
110440340cf9SSergio Afonso     break;
110540340cf9SSergio Afonso   default:
110640340cf9SSergio Afonso     res.getLangOpts().OpenMPIsGPU = 0;
110740340cf9SSergio Afonso     break;
110840340cf9SSergio Afonso   }
11094c7ebf79SArnamoy Bhattacharyya 
11109dadb1f6SSergio Afonso   // Get the OpenMP target triples if any.
11119dadb1f6SSergio Afonso   if (auto *arg =
11129dadb1f6SSergio Afonso           args.getLastArg(clang::driver::options::OPT_fopenmp_targets_EQ)) {
11139dadb1f6SSergio Afonso     enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit };
11149dadb1f6SSergio Afonso     auto getArchPtrSize = [](const llvm::Triple &triple) {
11159dadb1f6SSergio Afonso       if (triple.isArch16Bit())
11169dadb1f6SSergio Afonso         return Arch16Bit;
11179dadb1f6SSergio Afonso       if (triple.isArch32Bit())
11189dadb1f6SSergio Afonso         return Arch32Bit;
11199dadb1f6SSergio Afonso       assert(triple.isArch64Bit() && "Expected 64-bit architecture");
11209dadb1f6SSergio Afonso       return Arch64Bit;
11219dadb1f6SSergio Afonso     };
1122602df270SKiran Chandramohan 
11239dadb1f6SSergio Afonso     for (unsigned i = 0; i < arg->getNumValues(); ++i) {
11249dadb1f6SSergio Afonso       llvm::Triple tt(arg->getValue(i));
1125602df270SKiran Chandramohan 
11269dadb1f6SSergio Afonso       if (tt.getArch() == llvm::Triple::UnknownArch ||
11279dadb1f6SSergio Afonso           !(tt.getArch() == llvm::Triple::aarch64 || tt.isPPC() ||
11289dadb1f6SSergio Afonso             tt.getArch() == llvm::Triple::systemz ||
11299dadb1f6SSergio Afonso             tt.getArch() == llvm::Triple::nvptx ||
11309dadb1f6SSergio Afonso             tt.getArch() == llvm::Triple::nvptx64 ||
11319dadb1f6SSergio Afonso             tt.getArch() == llvm::Triple::amdgcn ||
11329dadb1f6SSergio Afonso             tt.getArch() == llvm::Triple::x86 ||
11339dadb1f6SSergio Afonso             tt.getArch() == llvm::Triple::x86_64))
11349dadb1f6SSergio Afonso         diags.Report(clang::diag::err_drv_invalid_omp_target)
11359dadb1f6SSergio Afonso             << arg->getValue(i);
11369dadb1f6SSergio Afonso       else if (getArchPtrSize(t) != getArchPtrSize(tt))
11379dadb1f6SSergio Afonso         diags.Report(clang::diag::err_drv_incompatible_omp_arch)
11389dadb1f6SSergio Afonso             << arg->getValue(i) << t.str();
11399dadb1f6SSergio Afonso       else
11409dadb1f6SSergio Afonso         res.getLangOpts().OMPTargetTriples.push_back(tt);
11414c7ebf79SArnamoy Bhattacharyya     }
11424c7ebf79SArnamoy Bhattacharyya   }
11436d0fef48SAndrzej Warzynski   return diags.getNumErrors() == numErrorsBefore;
1144ab971c29SArnamoy Bhattacharyya }
1145ab971c29SArnamoy Bhattacharyya 
11469698e575SYusuke MINATO /// Parses signed integer overflow options and populates the
11479698e575SYusuke MINATO /// CompilerInvocation accordingly.
11489698e575SYusuke MINATO /// Returns false if new errors are generated.
11499698e575SYusuke MINATO ///
11509698e575SYusuke MINATO /// \param [out] invoc Stores the processed arguments
11519698e575SYusuke MINATO /// \param [in] args The compiler invocation arguments to parse
11529698e575SYusuke MINATO /// \param [out] diags DiagnosticsEngine to report erros with
11539698e575SYusuke MINATO static bool parseIntegerOverflowArgs(CompilerInvocation &invoc,
11549698e575SYusuke MINATO                                      llvm::opt::ArgList &args,
11559698e575SYusuke MINATO                                      clang::DiagnosticsEngine &diags) {
11569698e575SYusuke MINATO   Fortran::common::LangOptions &opts = invoc.getLangOpts();
11579698e575SYusuke MINATO 
11589698e575SYusuke MINATO   if (args.getLastArg(clang::driver::options::OPT_fwrapv))
11599698e575SYusuke MINATO     opts.setSignedOverflowBehavior(Fortran::common::LangOptions::SOB_Defined);
11609698e575SYusuke MINATO 
11619698e575SYusuke MINATO   return true;
11629698e575SYusuke MINATO }
11639698e575SYusuke MINATO 
1164a784de78STom Eccles /// Parses all floating point related arguments and populates the
1165a784de78STom Eccles /// CompilerInvocation accordingly.
1166a784de78STom Eccles /// Returns false if new errors are generated.
1167a784de78STom Eccles ///
1168a784de78STom Eccles /// \param [out] invoc Stores the processed arguments
1169a784de78STom Eccles /// \param [in] args The compiler invocation arguments to parse
1170a784de78STom Eccles /// \param [out] diags DiagnosticsEngine to report erros with
1171a784de78STom Eccles static bool parseFloatingPointArgs(CompilerInvocation &invoc,
1172a784de78STom Eccles                                    llvm::opt::ArgList &args,
1173a784de78STom Eccles                                    clang::DiagnosticsEngine &diags) {
117458e8683aSKrzysztof Parzyszek   Fortran::common::LangOptions &opts = invoc.getLangOpts();
1175a784de78STom Eccles 
1176a784de78STom Eccles   if (const llvm::opt::Arg *a =
1177a784de78STom Eccles           args.getLastArg(clang::driver::options::OPT_ffp_contract)) {
1178a784de78STom Eccles     const llvm::StringRef val = a->getValue();
117958e8683aSKrzysztof Parzyszek     enum Fortran::common::LangOptions::FPModeKind fpContractMode;
1180a784de78STom Eccles 
1181a784de78STom Eccles     if (val == "off")
118258e8683aSKrzysztof Parzyszek       fpContractMode = Fortran::common::LangOptions::FPM_Off;
1183a784de78STom Eccles     else if (val == "fast")
118458e8683aSKrzysztof Parzyszek       fpContractMode = Fortran::common::LangOptions::FPM_Fast;
1185a784de78STom Eccles     else {
1186a784de78STom Eccles       diags.Report(clang::diag::err_drv_unsupported_option_argument)
11878c2c6228SFangrui Song           << a->getSpelling() << val;
1188a784de78STom Eccles       return false;
1189a784de78STom Eccles     }
1190a784de78STom Eccles 
1191a784de78STom Eccles     opts.setFPContractMode(fpContractMode);
1192a784de78STom Eccles   }
1193a784de78STom Eccles 
119442c79f70SZahira Ammarguellat   if (args.getLastArg(clang::driver::options::OPT_menable_no_infs)) {
11950fb763e7STom Eccles     opts.NoHonorInfs = true;
11960fb763e7STom Eccles   }
11970fb763e7STom Eccles 
11983a1b4092STom Eccles   if (args.getLastArg(clang::driver::options::OPT_menable_no_nans)) {
1199b5e93e39STom Eccles     opts.NoHonorNaNs = true;
1200b5e93e39STom Eccles   }
1201b5e93e39STom Eccles 
12023a1b4092STom Eccles   if (args.getLastArg(clang::driver::options::OPT_fapprox_func)) {
120336b37a1eSTom Eccles     opts.ApproxFunc = true;
120436b37a1eSTom Eccles   }
120536b37a1eSTom Eccles 
12063a1b4092STom Eccles   if (args.getLastArg(clang::driver::options::OPT_fno_signed_zeros)) {
1207b5b8a8cfSTom Eccles     opts.NoSignedZeros = true;
1208b5b8a8cfSTom Eccles   }
1209b5b8a8cfSTom Eccles 
12103a1b4092STom Eccles   if (args.getLastArg(clang::driver::options::OPT_mreassociate)) {
1211c4dc3c02STom Eccles     opts.AssociativeMath = true;
1212c4dc3c02STom Eccles   }
1213c4dc3c02STom Eccles 
12143a1b4092STom Eccles   if (args.getLastArg(clang::driver::options::OPT_freciprocal_math)) {
1215d0d4b635STom Eccles     opts.ReciprocalMath = true;
1216d0d4b635STom Eccles   }
1217d0d4b635STom Eccles 
1218e7b66602STom Eccles   if (args.getLastArg(clang::driver::options::OPT_ffast_math)) {
1219e7b66602STom Eccles     opts.NoHonorInfs = true;
1220e7b66602STom Eccles     opts.NoHonorNaNs = true;
1221e7b66602STom Eccles     opts.AssociativeMath = true;
1222e7b66602STom Eccles     opts.ReciprocalMath = true;
1223e7b66602STom Eccles     opts.ApproxFunc = true;
1224e7b66602STom Eccles     opts.NoSignedZeros = true;
122558e8683aSKrzysztof Parzyszek     opts.setFPContractMode(Fortran::common::LangOptions::FPM_Fast);
1226e7b66602STom Eccles   }
1227e7b66602STom Eccles 
1228a784de78STom Eccles   return true;
1229a784de78STom Eccles }
1230a784de78STom Eccles 
123111e68c7eSMats Petersson /// Parses vscale range options and populates the CompilerInvocation
123211e68c7eSMats Petersson /// accordingly.
123311e68c7eSMats Petersson /// Returns false if new errors are generated.
123411e68c7eSMats Petersson ///
123511e68c7eSMats Petersson /// \param [out] invoc Stores the processed arguments
123611e68c7eSMats Petersson /// \param [in] args The compiler invocation arguments to parse
123711e68c7eSMats Petersson /// \param [out] diags DiagnosticsEngine to report erros with
123811e68c7eSMats Petersson static bool parseVScaleArgs(CompilerInvocation &invoc, llvm::opt::ArgList &args,
123911e68c7eSMats Petersson                             clang::DiagnosticsEngine &diags) {
12408cac995eSAndrzej Warzyński   const auto *vscaleMin =
12418cac995eSAndrzej Warzyński       args.getLastArg(clang::driver::options::OPT_mvscale_min_EQ);
12428cac995eSAndrzej Warzyński   const auto *vscaleMax =
12438cac995eSAndrzej Warzyński       args.getLastArg(clang::driver::options::OPT_mvscale_max_EQ);
12448cac995eSAndrzej Warzyński 
12458cac995eSAndrzej Warzyński   if (!vscaleMin && !vscaleMax)
12468cac995eSAndrzej Warzyński     return true;
12478cac995eSAndrzej Warzyński 
12488cac995eSAndrzej Warzyński   llvm::Triple triple = llvm::Triple(invoc.getTargetOpts().triple);
12498cac995eSAndrzej Warzyński   if (!triple.isAArch64() && !triple.isRISCV()) {
12508cac995eSAndrzej Warzyński     const unsigned diagID =
12518cac995eSAndrzej Warzyński         diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
12528cac995eSAndrzej Warzyński                               "`-mvscale-max` and `-mvscale-min` are not "
12538cac995eSAndrzej Warzyński                               "supported for this architecture: %0");
12548cac995eSAndrzej Warzyński     diags.Report(diagID) << triple.getArchName();
12558cac995eSAndrzej Warzyński     return false;
12568cac995eSAndrzej Warzyński   }
12578cac995eSAndrzej Warzyński 
125858e8683aSKrzysztof Parzyszek   Fortran::common::LangOptions &opts = invoc.getLangOpts();
12598cac995eSAndrzej Warzyński   if (vscaleMin) {
12608cac995eSAndrzej Warzyński     llvm::StringRef argValue = llvm::StringRef(vscaleMin->getValue());
12618cac995eSAndrzej Warzyński     unsigned vscaleMinVal;
12628cac995eSAndrzej Warzyński     if (argValue.getAsInteger(/*Radix=*/10, vscaleMinVal)) {
126311e68c7eSMats Petersson       diags.Report(clang::diag::err_drv_unsupported_option_argument)
12648cac995eSAndrzej Warzyński           << vscaleMax->getSpelling() << argValue;
126511e68c7eSMats Petersson       return false;
126611e68c7eSMats Petersson     }
12678cac995eSAndrzej Warzyński     opts.VScaleMin = vscaleMinVal;
126811e68c7eSMats Petersson   }
12698cac995eSAndrzej Warzyński 
12708cac995eSAndrzej Warzyński   if (vscaleMax) {
12718cac995eSAndrzej Warzyński     llvm::StringRef argValue = llvm::StringRef(vscaleMax->getValue());
12728cac995eSAndrzej Warzyński     unsigned vscaleMaxVal;
12738cac995eSAndrzej Warzyński     if (argValue.getAsInteger(/*Radix=w*/ 10, vscaleMaxVal)) {
127411e68c7eSMats Petersson       diags.Report(clang::diag::err_drv_unsupported_option_argument)
12758cac995eSAndrzej Warzyński           << vscaleMax->getSpelling() << argValue;
127611e68c7eSMats Petersson       return false;
127711e68c7eSMats Petersson     }
12788cac995eSAndrzej Warzyński     opts.VScaleMax = vscaleMaxVal;
127911e68c7eSMats Petersson   }
128011e68c7eSMats Petersson   return true;
128111e68c7eSMats Petersson }
128211e68c7eSMats Petersson 
128377ecb9a4SDavid Truby static bool parseLinkerOptionsArgs(CompilerInvocation &invoc,
128477ecb9a4SDavid Truby                                    llvm::opt::ArgList &args,
128577ecb9a4SDavid Truby                                    clang::DiagnosticsEngine &diags) {
128677ecb9a4SDavid Truby   llvm::Triple triple = llvm::Triple(invoc.getTargetOpts().triple);
128777ecb9a4SDavid Truby 
128877ecb9a4SDavid Truby   // TODO: support --dependent-lib on other platforms when MLIR supports
128977ecb9a4SDavid Truby   //       !llvm.dependent.lib
129077ecb9a4SDavid Truby   if (args.hasArg(clang::driver::options::OPT_dependent_lib) &&
129177ecb9a4SDavid Truby       !triple.isOSWindows()) {
129277ecb9a4SDavid Truby     const unsigned diagID =
129377ecb9a4SDavid Truby         diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
129477ecb9a4SDavid Truby                               "--dependent-lib is only supported on Windows");
129577ecb9a4SDavid Truby     diags.Report(diagID);
129677ecb9a4SDavid Truby     return false;
129777ecb9a4SDavid Truby   }
129877ecb9a4SDavid Truby 
129977ecb9a4SDavid Truby   invoc.getCodeGenOpts().DependentLibs =
130077ecb9a4SDavid Truby       args.getAllArgValues(clang::driver::options::OPT_dependent_lib);
130177ecb9a4SDavid Truby   return true;
130277ecb9a4SDavid Truby }
130377ecb9a4SDavid Truby 
13049698e575SYusuke MINATO static bool parseLangOptionsArgs(CompilerInvocation &invoc,
13059698e575SYusuke MINATO                                  llvm::opt::ArgList &args,
13069698e575SYusuke MINATO                                  clang::DiagnosticsEngine &diags) {
13079698e575SYusuke MINATO   bool success = true;
13089698e575SYusuke MINATO 
13099698e575SYusuke MINATO   success &= parseIntegerOverflowArgs(invoc, args, diags);
13109698e575SYusuke MINATO   success &= parseFloatingPointArgs(invoc, args, diags);
13119698e575SYusuke MINATO   success &= parseVScaleArgs(invoc, args, diags);
13129698e575SYusuke MINATO 
13139698e575SYusuke MINATO   return success;
13149698e575SYusuke MINATO }
13159698e575SYusuke MINATO 
13161e462fafSAndrzej Warzynski bool CompilerInvocation::createFromArgs(
131748e96e97SAndrzej Warzyński     CompilerInvocation &invoc, llvm::ArrayRef<const char *> commandLineArgs,
1318541f5c4aSHussain Kadhem     clang::DiagnosticsEngine &diags, const char *argv0) {
1319257b2971SCaroline Concatto 
1320257b2971SCaroline Concatto   bool success = true;
1321257b2971SCaroline Concatto 
132202fb5b77SAndrzej Warzynski   // Set the default triple for this CompilerInvocation. This might be
132302fb5b77SAndrzej Warzynski   // overridden by users with `-triple` (see the call to `ParseTargetArgs`
132402fb5b77SAndrzej Warzynski   // below).
132502fb5b77SAndrzej Warzynski   // NOTE: Like in Clang, it would be nice to use option marshalling
132602fb5b77SAndrzej Warzynski   // for this so that the entire logic for setting-up the triple is in one
132702fb5b77SAndrzej Warzynski   // place.
132848e96e97SAndrzej Warzyński   invoc.getTargetOpts().triple =
132902fb5b77SAndrzej Warzynski       llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
133002fb5b77SAndrzej Warzynski 
1331257b2971SCaroline Concatto   // Parse the arguments
1332257b2971SCaroline Concatto   const llvm::opt::OptTable &opts = clang::driver::getDriverOptTable();
13339478f661SJustin Bogner   llvm::opt::Visibility visibilityMask(clang::driver::options::FC1Option);
1334257b2971SCaroline Concatto   unsigned missingArgIndex, missingArgCount;
1335257b2971SCaroline Concatto   llvm::opt::InputArgList args = opts.ParseArgs(
13369478f661SJustin Bogner       commandLineArgs, missingArgIndex, missingArgCount, visibilityMask);
1337257b2971SCaroline Concatto 
13382b4c9bc4SAndrzej Warzynski   // Check for missing argument error.
13392b4c9bc4SAndrzej Warzynski   if (missingArgCount) {
13402b4c9bc4SAndrzej Warzynski     diags.Report(clang::diag::err_drv_missing_argument)
13412b4c9bc4SAndrzej Warzynski         << args.getArgString(missingArgIndex) << missingArgCount;
13422b4c9bc4SAndrzej Warzynski     success = false;
13432b4c9bc4SAndrzej Warzynski   }
13442b4c9bc4SAndrzej Warzynski 
1345257b2971SCaroline Concatto   // Issue errors on unknown arguments
1346257b2971SCaroline Concatto   for (const auto *a : args.filtered(clang::driver::options::OPT_UNKNOWN)) {
1347257b2971SCaroline Concatto     auto argString = a->getAsString(args);
1348257b2971SCaroline Concatto     std::string nearest;
13499478f661SJustin Bogner     if (opts.findNearest(argString, nearest, visibilityMask) > 1)
1350257b2971SCaroline Concatto       diags.Report(clang::diag::err_drv_unknown_argument) << argString;
1351257b2971SCaroline Concatto     else
1352257b2971SCaroline Concatto       diags.Report(clang::diag::err_drv_unknown_argument_with_suggestion)
1353257b2971SCaroline Concatto           << argString << nearest;
1354257b2971SCaroline Concatto     success = false;
1355257b2971SCaroline Concatto   }
1356257b2971SCaroline Concatto 
1357acf6a322STom Eccles   // -flang-experimental-hlfir
135839ecf9d8STom Eccles   if (args.hasArg(clang::driver::options::OPT_flang_experimental_hlfir) ||
135939ecf9d8STom Eccles       args.hasArg(clang::driver::options::OPT_emit_hlfir)) {
136048e96e97SAndrzej Warzyński     invoc.loweringOpts.setLowerToHighLevelFIR(true);
1361acf6a322STom Eccles   }
1362acf6a322STom Eccles 
13639f265c38SjeanPerier   // -flang-deprecated-no-hlfir
13649f265c38SjeanPerier   if (args.hasArg(clang::driver::options::OPT_flang_deprecated_no_hlfir) &&
13659f265c38SjeanPerier       !args.hasArg(clang::driver::options::OPT_emit_hlfir)) {
13669f265c38SjeanPerier     if (args.hasArg(clang::driver::options::OPT_flang_experimental_hlfir)) {
13679f265c38SjeanPerier       const unsigned diagID = diags.getCustomDiagID(
13689f265c38SjeanPerier           clang::DiagnosticsEngine::Error,
13699f265c38SjeanPerier           "Options '-flang-experimental-hlfir' and "
13709f265c38SjeanPerier           "'-flang-deprecated-no-hlfir' cannot be both specified");
13719f265c38SjeanPerier       diags.Report(diagID);
13729f265c38SjeanPerier     }
137348e96e97SAndrzej Warzyński     invoc.loweringOpts.setLowerToHighLevelFIR(false);
13749f265c38SjeanPerier   }
13759f265c38SjeanPerier 
137600769d69SKelvin Li   // -fno-ppc-native-vector-element-order
137700769d69SKelvin Li   if (args.hasArg(clang::driver::options::OPT_fno_ppc_native_vec_elem_order)) {
137848e96e97SAndrzej Warzyński     invoc.loweringOpts.setNoPPCNativeVecElemOrder(true);
137900769d69SKelvin Li   }
138000769d69SKelvin Li 
1381ce326259SKiran Chandramohan   // -f[no-]init-global-zero
1382ce326259SKiran Chandramohan   if (args.hasFlag(clang::driver::options::OPT_finit_global_zero,
1383ce326259SKiran Chandramohan                    clang::driver::options::OPT_fno_init_global_zero,
1384ce326259SKiran Chandramohan                    /*default=*/true))
1385ce326259SKiran Chandramohan     invoc.loweringOpts.setInitGlobalZero(true);
1386ce326259SKiran Chandramohan   else
1387ce326259SKiran Chandramohan     invoc.loweringOpts.setInitGlobalZero(false);
1388ce326259SKiran Chandramohan 
138991989c67SVictor Kingi   // Preserve all the remark options requested, i.e. -Rpass, -Rpass-missed or
139091989c67SVictor Kingi   // -Rpass-analysis. This will be used later when processing and outputting the
139191989c67SVictor Kingi   // remarks generated by LLVM in ExecuteCompilerInvocation.cpp.
13928e315c6cSVictor Kingi   for (auto *a : args.filtered(clang::driver::options::OPT_R_Group)) {
13938e315c6cSVictor Kingi     if (a->getOption().matches(clang::driver::options::OPT_R_value_Group))
13948e315c6cSVictor Kingi       // This is -Rfoo=, where foo is the name of the diagnostic
13958e315c6cSVictor Kingi       // group. Add only the remark option name to the diagnostics. e.g. for
13968e315c6cSVictor Kingi       // -Rpass= we will add the string "pass".
139748e96e97SAndrzej Warzyński       invoc.getDiagnosticOpts().Remarks.push_back(
13988e315c6cSVictor Kingi           std::string(a->getOption().getName().drop_front(1).rtrim("=-")));
13998e315c6cSVictor Kingi     else
14008e315c6cSVictor Kingi       // If no regex was provided, add the provided value, e.g. for -Rpass add
14018e315c6cSVictor Kingi       // the string "pass".
140248e96e97SAndrzej Warzyński       invoc.getDiagnosticOpts().Remarks.push_back(a->getValue());
14038e315c6cSVictor Kingi   }
140491989c67SVictor Kingi 
14059d338749SSlava Zakharin   // -frealloc-lhs is the default.
14069d338749SSlava Zakharin   if (!args.hasFlag(clang::driver::options::OPT_frealloc_lhs,
14079d338749SSlava Zakharin                     clang::driver::options::OPT_fno_realloc_lhs, true))
14089d338749SSlava Zakharin     invoc.loweringOpts.setReallocateLHS(false);
14099d338749SSlava Zakharin 
141048e96e97SAndrzej Warzyński   success &= parseFrontendArgs(invoc.getFrontendOpts(), args, diags);
141148e96e97SAndrzej Warzyński   parseTargetArgs(invoc.getTargetOpts(), args);
141248e96e97SAndrzej Warzyński   parsePreprocessorArgs(invoc.getPreprocessorOpts(), args);
141348e96e97SAndrzej Warzyński   parseCodeGenArgs(invoc.getCodeGenOpts(), args, diags);
141448e96e97SAndrzej Warzyński   success &= parseDebugArgs(invoc.getCodeGenOpts(), args, diags);
141548e96e97SAndrzej Warzyński   success &= parseVectorLibArg(invoc.getCodeGenOpts(), args, diags);
141648e96e97SAndrzej Warzyński   success &= parseSemaArgs(invoc, args, diags);
141748e96e97SAndrzej Warzyński   success &= parseDialectArgs(invoc, args, diags);
14189dadb1f6SSergio Afonso   success &= parseOpenMPArgs(invoc, args, diags);
141948e96e97SAndrzej Warzyński   success &= parseDiagArgs(invoc, args, diags);
1420ebc2c71dSAndrzej Warzynski 
1421ebc2c71dSAndrzej Warzynski   // Collect LLVM (-mllvm) and MLIR (-mmlir) options.
1422ebc2c71dSAndrzej Warzynski   // NOTE: Try to avoid adding any options directly to `llvmArgs` or
1423ebc2c71dSAndrzej Warzynski   // `mlirArgs`. Instead, you can use
1424ebc2c71dSAndrzej Warzynski   //    * `-mllvm <your-llvm-option>`, or
1425ebc2c71dSAndrzej Warzynski   //    * `-mmlir <your-mlir-option>`.
142648e96e97SAndrzej Warzyński   invoc.frontendOpts.llvmArgs =
1427a7c08bcfSAndrzej Warzynski       args.getAllArgValues(clang::driver::options::OPT_mllvm);
142848e96e97SAndrzej Warzyński   invoc.frontendOpts.mlirArgs =
14296c93e1d3SAndrzej Warzynski       args.getAllArgValues(clang::driver::options::OPT_mmlir);
14306c93e1d3SAndrzej Warzynski 
14319698e575SYusuke MINATO   success &= parseLangOptionsArgs(invoc, args, diags);
143211e68c7eSMats Petersson 
143348e96e97SAndrzej Warzyński   success &= parseLinkerOptionsArgs(invoc, args, diags);
143477ecb9a4SDavid Truby 
1435541f5c4aSHussain Kadhem   // Set the string to be used as the return value of the COMPILER_OPTIONS
1436541f5c4aSHussain Kadhem   // intrinsic of iso_fortran_env. This is either passed in from the parent
1437541f5c4aSHussain Kadhem   // compiler driver invocation with an environment variable, or failing that
1438541f5c4aSHussain Kadhem   // set to the command line arguments of the frontend driver invocation.
143948e96e97SAndrzej Warzyński   invoc.allCompilerInvocOpts = std::string();
144048e96e97SAndrzej Warzyński   llvm::raw_string_ostream os(invoc.allCompilerInvocOpts);
1441541f5c4aSHussain Kadhem   char *compilerOptsEnv = std::getenv("FLANG_COMPILER_OPTIONS_STRING");
1442541f5c4aSHussain Kadhem   if (compilerOptsEnv != nullptr) {
1443541f5c4aSHussain Kadhem     os << compilerOptsEnv;
1444541f5c4aSHussain Kadhem   } else {
1445541f5c4aSHussain Kadhem     os << argv0 << ' ';
1446541f5c4aSHussain Kadhem     for (auto it = commandLineArgs.begin(), e = commandLineArgs.end(); it != e;
1447541f5c4aSHussain Kadhem          ++it) {
1448541f5c4aSHussain Kadhem       os << ' ' << *it;
1449541f5c4aSHussain Kadhem     }
1450541f5c4aSHussain Kadhem   }
1451541f5c4aSHussain Kadhem 
1452310c281bSmacurtis-amd   // Process the timing-related options.
1453310c281bSmacurtis-amd   if (args.hasArg(clang::driver::options::OPT_ftime_report))
1454310c281bSmacurtis-amd     invoc.enableTimers = true;
1455310c281bSmacurtis-amd 
145648e96e97SAndrzej Warzyński   invoc.setArgv0(argv0);
14578dc474c6Smadanial0 
1458257b2971SCaroline Concatto   return success;
1459257b2971SCaroline Concatto }
1460d28de0d7SCaroline Concatto 
14611e462fafSAndrzej Warzynski void CompilerInvocation::collectMacroDefinitions() {
14621e462fafSAndrzej Warzynski   auto &ppOpts = this->getPreprocessorOpts();
1463b83a4450SAndrzej Warzynski 
14647809fa20SFaris Rehman   for (unsigned i = 0, n = ppOpts.macros.size(); i != n; ++i) {
14657809fa20SFaris Rehman     llvm::StringRef macro = ppOpts.macros[i].first;
14667809fa20SFaris Rehman     bool isUndef = ppOpts.macros[i].second;
14677809fa20SFaris Rehman 
14687809fa20SFaris Rehman     std::pair<llvm::StringRef, llvm::StringRef> macroPair = macro.split('=');
14697809fa20SFaris Rehman     llvm::StringRef macroName = macroPair.first;
14707809fa20SFaris Rehman     llvm::StringRef macroBody = macroPair.second;
14717809fa20SFaris Rehman 
14727809fa20SFaris Rehman     // For an #undef'd macro, we only care about the name.
14737809fa20SFaris Rehman     if (isUndef) {
14741e462fafSAndrzej Warzynski       parserOpts.predefinitions.emplace_back(macroName.str(),
14751e462fafSAndrzej Warzynski                                              std::optional<std::string>{});
14767809fa20SFaris Rehman       continue;
14777809fa20SFaris Rehman     }
14787809fa20SFaris Rehman 
14797809fa20SFaris Rehman     // For a #define'd macro, figure out the actual definition.
14807809fa20SFaris Rehman     if (macroName.size() == macro.size())
14817809fa20SFaris Rehman       macroBody = "1";
14827809fa20SFaris Rehman     else {
14837809fa20SFaris Rehman       // Note: GCC drops anything following an end-of-line character.
14841e462fafSAndrzej Warzynski       llvm::StringRef::size_type end = macroBody.find_first_of("\n\r");
14851e462fafSAndrzej Warzynski       macroBody = macroBody.substr(0, end);
14867809fa20SFaris Rehman     }
14871e462fafSAndrzej Warzynski     parserOpts.predefinitions.emplace_back(
14887809fa20SFaris Rehman         macroName, std::optional<std::string>(macroBody.str()));
14897809fa20SFaris Rehman   }
14907809fa20SFaris Rehman }
14917809fa20SFaris Rehman 
14921e462fafSAndrzej Warzynski void CompilerInvocation::setDefaultFortranOpts() {
14931e462fafSAndrzej Warzynski   auto &fortranOptions = getFortranOpts();
1494d28de0d7SCaroline Concatto 
1495d28de0d7SCaroline Concatto   std::vector<std::string> searchDirectories{"."s};
1496d28de0d7SCaroline Concatto   fortranOptions.searchDirectories = searchDirectories;
1497dda366edSAndrzej Warzynski 
1498dda366edSAndrzej Warzynski   // Add the location of omp_lib.h to the search directories. Currently this is
1499dda366edSAndrzej Warzynski   // identical to the modules' directory.
15008dc474c6Smadanial0   fortranOptions.searchDirectories.emplace_back(
15018dc474c6Smadanial0       getOpenMPHeadersDir(getArgv0()));
1502dda366edSAndrzej Warzynski 
1503d28de0d7SCaroline Concatto   fortranOptions.isFixedForm = false;
15040feff71eSAndrzej Warzynski }
15050feff71eSAndrzej Warzynski 
15060feff71eSAndrzej Warzynski // TODO: When expanding this method, consider creating a dedicated API for
15070feff71eSAndrzej Warzynski // this. Also at some point we will need to differentiate between different
15080feff71eSAndrzej Warzynski // targets and add dedicated predefines for each.
15091e462fafSAndrzej Warzynski void CompilerInvocation::setDefaultPredefinitions() {
15101e462fafSAndrzej Warzynski   auto &fortranOptions = getFortranOpts();
15111e462fafSAndrzej Warzynski   const auto &frontendOptions = getFrontendOpts();
1512197d9a55SFaris Rehman   // Populate the macro list with version numbers and other predefinitions.
1513197d9a55SFaris Rehman   fortranOptions.predefinitions.emplace_back("__flang__", "1");
151474d5c3c0SPeter Steinfeld   fortranOptions.predefinitions.emplace_back("__flang_major__",
151574d5c3c0SPeter Steinfeld                                              FLANG_VERSION_MAJOR_STRING);
151674d5c3c0SPeter Steinfeld   fortranOptions.predefinitions.emplace_back("__flang_minor__",
151774d5c3c0SPeter Steinfeld                                              FLANG_VERSION_MINOR_STRING);
151874d5c3c0SPeter Steinfeld   fortranOptions.predefinitions.emplace_back("__flang_patchlevel__",
151974d5c3c0SPeter Steinfeld                                              FLANG_VERSION_PATCHLEVEL_STRING);
15206d48a1a5SFaris Rehman 
15216d48a1a5SFaris Rehman   // Add predefinitions based on extensions enabled
152223d4c4f3SAndrzej Warzynski   if (frontendOptions.features.IsEnabled(
15236d48a1a5SFaris Rehman           Fortran::common::LanguageFeature::OpenACC)) {
15240d6017cdSValentin Clement     fortranOptions.predefinitions.emplace_back("_OPENACC", "202211");
15256d48a1a5SFaris Rehman   }
152623d4c4f3SAndrzej Warzynski   if (frontendOptions.features.IsEnabled(
15276d48a1a5SFaris Rehman           Fortran::common::LanguageFeature::OpenMP)) {
15284a5ac14eSDominik Adamski     Fortran::common::setOpenMPMacro(getLangOpts().OpenMPVersion,
15294a5ac14eSDominik Adamski                                     fortranOptions.predefinitions);
15306d48a1a5SFaris Rehman   }
1531987258f5SDaniel Chen 
15321cfae76eSPeter Steinfeld   llvm::Triple targetTriple{llvm::Triple(this->targetOpts.triple)};
15338136ac1cSDaniel Chen   if (targetTriple.isPPC()) {
15348136ac1cSDaniel Chen     // '__powerpc__' is a generic macro for any PowerPC cases. e.g. Max integer
15358136ac1cSDaniel Chen     // size.
15368136ac1cSDaniel Chen     fortranOptions.predefinitions.emplace_back("__powerpc__", "1");
15378136ac1cSDaniel Chen   }
15388136ac1cSDaniel Chen   if (targetTriple.isOSLinux()) {
15398136ac1cSDaniel Chen     fortranOptions.predefinitions.emplace_back("__linux__", "1");
15408136ac1cSDaniel Chen   }
15418136ac1cSDaniel Chen 
1542987258f5SDaniel Chen   switch (targetTriple.getArch()) {
1543987258f5SDaniel Chen   default:
1544987258f5SDaniel Chen     break;
1545987258f5SDaniel Chen   case llvm::Triple::ArchType::x86_64:
15461cfae76eSPeter Steinfeld     fortranOptions.predefinitions.emplace_back("__x86_64__", "1");
15471cfae76eSPeter Steinfeld     fortranOptions.predefinitions.emplace_back("__x86_64", "1");
1548987258f5SDaniel Chen     break;
15491cfae76eSPeter Steinfeld   }
15506d48a1a5SFaris Rehman }
15516d48a1a5SFaris Rehman 
15521e462fafSAndrzej Warzynski void CompilerInvocation::setFortranOpts() {
15531e462fafSAndrzej Warzynski   auto &fortranOptions = getFortranOpts();
15541e462fafSAndrzej Warzynski   const auto &frontendOptions = getFrontendOpts();
15551e462fafSAndrzej Warzynski   const auto &preprocessorOptions = getPreprocessorOpts();
15561e462fafSAndrzej Warzynski   auto &moduleDirJ = getModuleDir();
15577809fa20SFaris Rehman 
155823d4c4f3SAndrzej Warzynski   if (frontendOptions.fortranForm != FortranForm::Unknown) {
15593a1513c1SFaris Rehman     fortranOptions.isFixedForm =
156023d4c4f3SAndrzej Warzynski         frontendOptions.fortranForm == FortranForm::FixedForm;
15613a1513c1SFaris Rehman   }
156223d4c4f3SAndrzej Warzynski   fortranOptions.fixedFormColumns = frontendOptions.fixedFormColumns;
15633a1513c1SFaris Rehman 
15644dfed691SPeter Klausler   // -E
15654dfed691SPeter Klausler   fortranOptions.prescanAndReformat =
15664dfed691SPeter Klausler       frontendOptions.programAction == PrintPreprocessedInput;
15674dfed691SPeter Klausler 
156823d4c4f3SAndrzej Warzynski   fortranOptions.features = frontendOptions.features;
156923d4c4f3SAndrzej Warzynski   fortranOptions.encoding = frontendOptions.encoding;
15706d48a1a5SFaris Rehman 
1571cd4abc52SArnamoy Bhattacharyya   // Adding search directories specified by -I
157287dfd5e0SFaris Rehman   fortranOptions.searchDirectories.insert(
157387dfd5e0SFaris Rehman       fortranOptions.searchDirectories.end(),
157487dfd5e0SFaris Rehman       preprocessorOptions.searchDirectoriesFromDashI.begin(),
157587dfd5e0SFaris Rehman       preprocessorOptions.searchDirectoriesFromDashI.end());
1576985a42fdSArnamoy Bhattacharyya 
1577cd4abc52SArnamoy Bhattacharyya   // Add the ordered list of -intrinsic-modules-path
1578cd4abc52SArnamoy Bhattacharyya   fortranOptions.searchDirectories.insert(
1579cd4abc52SArnamoy Bhattacharyya       fortranOptions.searchDirectories.end(),
1580cd4abc52SArnamoy Bhattacharyya       preprocessorOptions.searchDirectoriesFromIntrModPath.begin(),
1581cd4abc52SArnamoy Bhattacharyya       preprocessorOptions.searchDirectoriesFromIntrModPath.end());
1582cd4abc52SArnamoy Bhattacharyya 
158352a1346bSPeter Klausler   //  Add the default intrinsic module directory
15848dc474c6Smadanial0   fortranOptions.intrinsicModuleDirectories.emplace_back(
15858dc474c6Smadanial0       getIntrinsicDir(getArgv0()));
1586cd4abc52SArnamoy Bhattacharyya 
1587985a42fdSArnamoy Bhattacharyya   // Add the directory supplied through -J/-module-dir to the list of search
1588985a42fdSArnamoy Bhattacharyya   // directories
1589d0f1283eSKazu Hirata   if (moduleDirJ != ".")
1590985a42fdSArnamoy Bhattacharyya     fortranOptions.searchDirectories.emplace_back(moduleDirJ);
1591523d7bc6SAndrzej Warzynski 
159223d4c4f3SAndrzej Warzynski   if (frontendOptions.instrumentedParse)
1593523d7bc6SAndrzej Warzynski     fortranOptions.instrumentedParse = true;
15944c7ebf79SArnamoy Bhattacharyya 
15958df63a23SPeixin Qiao   if (frontendOptions.showColors)
15968df63a23SPeixin Qiao     fortranOptions.showColors = true;
15978df63a23SPeixin Qiao 
159823d4c4f3SAndrzej Warzynski   if (frontendOptions.needProvenanceRangeToCharBlockMappings)
159985b86c6fSAndrzej Warzynski     fortranOptions.needProvenanceRangeToCharBlockMappings = true;
160085b86c6fSAndrzej Warzynski 
1601191d4872SPeter Klausler   if (getEnableConformanceChecks())
16024c7ebf79SArnamoy Bhattacharyya     fortranOptions.features.WarnOnAllNonstandard();
1603191d4872SPeter Klausler 
1604191d4872SPeter Klausler   if (getEnableUsageChecks())
1605191d4872SPeter Klausler     fortranOptions.features.WarnOnAllUsage();
1606602df270SKiran Chandramohan 
1607602df270SKiran Chandramohan   if (getDisableWarnings()) {
1608602df270SKiran Chandramohan     fortranOptions.features.DisableAllNonstandardWarnings();
1609602df270SKiran Chandramohan     fortranOptions.features.DisableAllUsageWarnings();
1610602df270SKiran Chandramohan   }
1611985a42fdSArnamoy Bhattacharyya }
1612985a42fdSArnamoy Bhattacharyya 
1613ae4d7ac9SAndrzej Warzyński std::unique_ptr<Fortran::semantics::SemanticsContext>
1614ae4d7ac9SAndrzej Warzyński CompilerInvocation::getSemanticsCtx(
1615e59e8488SjeanPerier     Fortran::parser::AllCookedSources &allCookedSources,
1616e59e8488SjeanPerier     const llvm::TargetMachine &targetMachine) {
16171cfae76eSPeter Steinfeld   auto &fortranOptions = getFortranOpts();
16186d48a1a5SFaris Rehman 
1619ae4d7ac9SAndrzej Warzyński   auto semanticsContext = std::make_unique<semantics::SemanticsContext>(
16203b20a833SKrzysztof Parzyszek       getDefaultKinds(), fortranOptions.features, getLangOpts(),
16213b20a833SKrzysztof Parzyszek       allCookedSources);
16226d48a1a5SFaris Rehman 
16231e462fafSAndrzej Warzynski   semanticsContext->set_moduleDirectory(getModuleDir())
16244c7ebf79SArnamoy Bhattacharyya       .set_searchDirectories(fortranOptions.searchDirectories)
162552a1346bSPeter Klausler       .set_intrinsicModuleDirectories(fortranOptions.intrinsicModuleDirectories)
16261e462fafSAndrzej Warzynski       .set_warningsAreErrors(getWarnAsErr())
16276ffea74fSjeanPerier       .set_moduleFileSuffix(getModuleFileSuffix())
16286ffea74fSjeanPerier       .set_underscoring(getCodeGenOpts().Underscoring);
1629c4f04a12SPeixin Qiao 
1630e59e8488SjeanPerier   std::string compilerVersion = Fortran::common::getFlangFullVersion();
1631e59e8488SjeanPerier   Fortran::tools::setUpTargetCharacteristics(
1632697bc748SRenaud Kauffmann       semanticsContext->targetCharacteristics(), targetMachine, getTargetOpts(),
1633697bc748SRenaud Kauffmann       compilerVersion, allCompilerInvocOpts);
1634ae4d7ac9SAndrzej Warzyński   return semanticsContext;
16357809fa20SFaris Rehman }
1636f1eb945fSSlava Zakharin 
1637f1eb945fSSlava Zakharin /// Set \p loweringOptions controlling lowering behavior based
1638f1eb945fSSlava Zakharin /// on the \p optimizationLevel.
1639f1eb945fSSlava Zakharin void CompilerInvocation::setLoweringOptions() {
16408f3f15c1SSlava Zakharin   const CodeGenOptions &codegenOpts = getCodeGenOpts();
1641f1eb945fSSlava Zakharin 
1642f1eb945fSSlava Zakharin   // Lower TRANSPOSE as a runtime call under -O0.
1643f1eb945fSSlava Zakharin   loweringOpts.setOptimizeTranspose(codegenOpts.OptimizationLevel > 0);
16446ffea74fSjeanPerier   loweringOpts.setUnderscoring(codegenOpts.Underscoring);
16458f3f15c1SSlava Zakharin 
164658e8683aSKrzysztof Parzyszek   const Fortran::common::LangOptions &langOptions = getLangOpts();
16479698e575SYusuke MINATO   loweringOpts.setIntegerWrapAround(langOptions.getSignedOverflowBehavior() ==
16489698e575SYusuke MINATO                                     Fortran::common::LangOptions::SOB_Defined);
16498f3f15c1SSlava Zakharin   Fortran::common::MathOptionsBase &mathOpts = loweringOpts.getMathOptions();
16508f3f15c1SSlava Zakharin   // TODO: when LangOptions are finalized, we can represent
16518f3f15c1SSlava Zakharin   //       the math related options using Fortran::commmon::MathOptionsBase,
16528f3f15c1SSlava Zakharin   //       so that we can just copy it into LoweringOptions.
16538f3f15c1SSlava Zakharin   mathOpts
16548f3f15c1SSlava Zakharin       .setFPContractEnabled(langOptions.getFPContractMode() ==
165558e8683aSKrzysztof Parzyszek                             Fortran::common::LangOptions::FPM_Fast)
16563538ca3fSSlava Zakharin       .setNoHonorInfs(langOptions.NoHonorInfs)
16573538ca3fSSlava Zakharin       .setNoHonorNaNs(langOptions.NoHonorNaNs)
16583538ca3fSSlava Zakharin       .setApproxFunc(langOptions.ApproxFunc)
16593538ca3fSSlava Zakharin       .setNoSignedZeros(langOptions.NoSignedZeros)
16603538ca3fSSlava Zakharin       .setAssociativeMath(langOptions.AssociativeMath)
16613538ca3fSSlava Zakharin       .setReciprocalMath(langOptions.ReciprocalMath);
1662f1eb945fSSlava Zakharin }
1663