brintos

brintos / llvm-project-archived public Read only

0
0
Text · 43.4 KiB · 438de23 Raw
1175 lines · cpp
1//===-- Flang.cpp - Flang+LLVM ToolChain Implementations --------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Flang.h"10#include "Arch/RISCV.h"11 12#include "clang/Basic/CodeGenOptions.h"13#include "clang/Driver/CommonArgs.h"14#include "clang/Options/OptionUtils.h"15#include "clang/Options/Options.h"16#include "llvm/Frontend/Debug/Options.h"17#include "llvm/Support/Path.h"18#include "llvm/TargetParser/Host.h"19#include "llvm/TargetParser/RISCVISAInfo.h"20#include "llvm/TargetParser/RISCVTargetParser.h"21 22#include <cassert>23 24using namespace clang::driver;25using namespace clang::driver::tools;26using namespace clang;27using namespace llvm::opt;28 29/// Add -x lang to \p CmdArgs for \p Input.30static void addDashXForInput(const ArgList &Args, const InputInfo &Input,31                             ArgStringList &CmdArgs) {32  CmdArgs.push_back("-x");33  // Map the driver type to the frontend type.34  CmdArgs.push_back(types::getTypeName(Input.getType()));35}36 37void Flang::addFortranDialectOptions(const ArgList &Args,38                                     ArgStringList &CmdArgs) const {39  Args.addAllArgs(CmdArgs, {options::OPT_ffixed_form,40                            options::OPT_ffree_form,41                            options::OPT_ffixed_line_length_EQ,42                            options::OPT_fopenacc,43                            options::OPT_finput_charset_EQ,44                            options::OPT_fimplicit_none,45                            options::OPT_fimplicit_none_ext,46                            options::OPT_fno_implicit_none,47                            options::OPT_fbackslash,48                            options::OPT_fno_backslash,49                            options::OPT_flogical_abbreviations,50                            options::OPT_fno_logical_abbreviations,51                            options::OPT_fxor_operator,52                            options::OPT_fno_xor_operator,53                            options::OPT_falternative_parameter_statement,54                            options::OPT_fdefault_real_8,55                            options::OPT_fdefault_integer_8,56                            options::OPT_fdefault_double_8,57                            options::OPT_flarge_sizes,58                            options::OPT_fno_automatic,59                            options::OPT_fhermetic_module_files,60                            options::OPT_frealloc_lhs,61                            options::OPT_fno_realloc_lhs,62                            options::OPT_fsave_main_program,63                            options::OPT_fd_lines_as_code,64                            options::OPT_fd_lines_as_comments,65                            options::OPT_fno_save_main_program});66}67 68void Flang::addPreprocessingOptions(const ArgList &Args,69                                    ArgStringList &CmdArgs) const {70  Args.addAllArgs(CmdArgs,71                  {options::OPT_P, options::OPT_D, options::OPT_U,72                   options::OPT_I, options::OPT_cpp, options::OPT_nocpp});73}74 75/// @C shouldLoopVersion76///77/// Check if Loop Versioning should be enabled.78/// We look for the last of one of the following:79///   -Ofast, -O4, -O<number> and -f[no-]version-loops-for-stride.80/// Loop versioning is disabled if the last option is81///  -fno-version-loops-for-stride.82/// Loop versioning is enabled if the last option is one of:83///  -floop-versioning84///  -Ofast85///  -O486///  -O387/// For all other cases, loop versioning is is disabled.88///89/// The gfortran compiler automatically enables the option for -O3 or -Ofast.90///91/// @return true if loop-versioning should be enabled, otherwise false.92static bool shouldLoopVersion(const ArgList &Args) {93  const Arg *LoopVersioningArg = Args.getLastArg(94      options::OPT_Ofast, options::OPT_O, options::OPT_O4,95      options::OPT_floop_versioning, options::OPT_fno_loop_versioning);96  if (!LoopVersioningArg)97    return false;98 99  if (LoopVersioningArg->getOption().matches(options::OPT_fno_loop_versioning))100    return false;101 102  if (LoopVersioningArg->getOption().matches(options::OPT_floop_versioning))103    return true;104 105  if (LoopVersioningArg->getOption().matches(options::OPT_Ofast) ||106      LoopVersioningArg->getOption().matches(options::OPT_O4))107    return true;108 109  if (LoopVersioningArg->getOption().matches(options::OPT_O)) {110    StringRef S(LoopVersioningArg->getValue());111    unsigned OptLevel = 0;112    // Note -Os or Oz woould "fail" here, so return false. Which is the113    // desiered behavior.114    if (S.getAsInteger(10, OptLevel))115      return false;116 117    return OptLevel > 2;118  }119 120  llvm_unreachable("We should not end up here");121  return false;122}123 124void Flang::addDebugOptions(const llvm::opt::ArgList &Args, const JobAction &JA,125                            const InputInfo &Output, const InputInfo &Input,126                            llvm::opt::ArgStringList &CmdArgs) const {127  const auto &TC = getToolChain();128  const Driver &D = TC.getDriver();129  Args.addAllArgs(CmdArgs,130                  {options::OPT_module_dir, options::OPT_fdebug_module_writer,131                   options::OPT_fintrinsic_modules_path, options::OPT_pedantic,132                   options::OPT_std_EQ, options::OPT_W_Joined,133                   options::OPT_fconvert_EQ, options::OPT_fpass_plugin_EQ,134                   options::OPT_funderscoring, options::OPT_fno_underscoring,135                   options::OPT_funsigned, options::OPT_fno_unsigned,136                   options::OPT_finstrument_functions});137 138  llvm::codegenoptions::DebugInfoKind DebugInfoKind;139  bool hasDwarfNArg = getDwarfNArg(Args) != nullptr;140  if (Args.hasArg(options::OPT_gN_Group)) {141    Arg *gNArg = Args.getLastArg(options::OPT_gN_Group);142    DebugInfoKind = debugLevelToInfoKind(*gNArg);143  } else if (Args.hasArg(options::OPT_g_Flag) || hasDwarfNArg) {144    DebugInfoKind = llvm::codegenoptions::FullDebugInfo;145  } else {146    DebugInfoKind = llvm::codegenoptions::NoDebugInfo;147  }148  addDebugInfoKind(CmdArgs, DebugInfoKind);149  if (hasDwarfNArg) {150    const unsigned DwarfVersion = getDwarfVersion(getToolChain(), Args);151    CmdArgs.push_back(152        Args.MakeArgString("-dwarf-version=" + Twine(DwarfVersion)));153  }154  if (Args.hasArg(options::OPT_gsplit_dwarf) ||155      Args.hasArg(options::OPT_gsplit_dwarf_EQ)) {156    // FIXME: -gsplit-dwarf on AIX is currently unimplemented.157    if (TC.getTriple().isOSAIX()) {158      D.Diag(diag::err_drv_unsupported_opt_for_target)159          << Args.getLastArg(options::OPT_gsplit_dwarf)->getSpelling()160          << TC.getTriple().str();161      return;162    }163    if (DebugInfoKind == llvm::codegenoptions::NoDebugInfo)164      return;165 166    Arg *SplitDWARFArg;167    DwarfFissionKind DwarfFission = getDebugFissionKind(D, Args, SplitDWARFArg);168 169    if (DwarfFission == DwarfFissionKind::None ||170        !checkDebugInfoOption(SplitDWARFArg, Args, D, TC))171      return;172 173    if (!TC.getTriple().isOSBinFormatELF() &&174        !TC.getTriple().isOSBinFormatWasm() &&175        !TC.getTriple().isOSBinFormatCOFF()) {176      D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target)177          << SplitDWARFArg->getSpelling() << TC.getTriple().str();178      return;179    }180 181    if (!isa<AssembleJobAction>(JA) && !isa<CompileJobAction>(JA) &&182        isa<BackendJobAction>(JA))183      return;184 185    const char *SplitDWARFOut = SplitDebugName(JA, Args, Input, Output);186    CmdArgs.push_back("-split-dwarf-file");187    CmdArgs.push_back(SplitDWARFOut);188    if (DwarfFission == DwarfFissionKind::Split) {189      CmdArgs.push_back("-split-dwarf-output");190      CmdArgs.push_back(SplitDWARFOut);191    }192  }193}194 195void Flang::addCodegenOptions(const ArgList &Args,196                              ArgStringList &CmdArgs) const {197  Arg *stackArrays =198      Args.getLastArg(options::OPT_Ofast, options::OPT_fstack_arrays,199                      options::OPT_fno_stack_arrays);200  if (stackArrays &&201      !stackArrays->getOption().matches(options::OPT_fno_stack_arrays))202    CmdArgs.push_back("-fstack-arrays");203 204  Args.addOptInFlag(CmdArgs, options::OPT_fexperimental_loop_fusion,205                    options::OPT_fno_experimental_loop_fusion);206 207  handleInterchangeLoopsArgs(Args, CmdArgs);208  handleVectorizeLoopsArgs(Args, CmdArgs);209  handleVectorizeSLPArgs(Args, CmdArgs);210 211  if (shouldLoopVersion(Args))212    CmdArgs.push_back("-fversion-loops-for-stride");213 214  for (const auto &arg :215       Args.getAllArgValues(options::OPT_frepack_arrays_contiguity_EQ))216    if (arg != "whole" && arg != "innermost") {217      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)218          << "-frepack-arrays-contiguity=" << arg;219    }220 221  Args.addAllArgs(222      CmdArgs,223      {options::OPT_fdo_concurrent_to_openmp_EQ,224       options::OPT_flang_experimental_hlfir,225       options::OPT_flang_deprecated_no_hlfir,226       options::OPT_fno_ppc_native_vec_elem_order,227       options::OPT_fppc_native_vec_elem_order, options::OPT_finit_global_zero,228       options::OPT_fno_init_global_zero, options::OPT_frepack_arrays,229       options::OPT_fno_repack_arrays,230       options::OPT_frepack_arrays_contiguity_EQ,231       options::OPT_fstack_repack_arrays, options::OPT_fno_stack_repack_arrays,232       options::OPT_ftime_report, options::OPT_ftime_report_EQ,233       options::OPT_funroll_loops, options::OPT_fno_unroll_loops});234  if (Args.hasArg(options::OPT_fcoarray))235    CmdArgs.push_back("-fcoarray");236}237 238void Flang::addLTOOptions(const ArgList &Args, ArgStringList &CmdArgs) const {239  const ToolChain &TC = getToolChain();240  const Driver &D = TC.getDriver();241  DiagnosticsEngine &Diags = D.getDiags();242  LTOKind LTOMode = D.getLTOMode();243  // LTO mode is parsed by the Clang driver library.244  assert(LTOMode != LTOK_Unknown && "Unknown LTO mode.");245  if (LTOMode == LTOK_Full)246    CmdArgs.push_back("-flto=full");247  else if (LTOMode == LTOK_Thin) {248    Diags.Report(249        Diags.getCustomDiagID(DiagnosticsEngine::Warning,250                              "the option '-flto=thin' is a work in progress"));251    CmdArgs.push_back("-flto=thin");252  }253  Args.addAllArgs(CmdArgs, {options::OPT_ffat_lto_objects,254                            options::OPT_fno_fat_lto_objects});255}256 257void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const {258  // ParsePICArgs parses -fPIC/-fPIE and their variants and returns a tuple of259  // (RelocationModel, PICLevel, IsPIE).260  llvm::Reloc::Model RelocationModel;261  unsigned PICLevel;262  bool IsPIE;263  std::tie(RelocationModel, PICLevel, IsPIE) =264      ParsePICArgs(getToolChain(), Args);265 266  if (auto *RMName = RelocationModelName(RelocationModel)) {267    CmdArgs.push_back("-mrelocation-model");268    CmdArgs.push_back(RMName);269  }270  if (PICLevel > 0) {271    CmdArgs.push_back("-pic-level");272    CmdArgs.push_back(PICLevel == 1 ? "1" : "2");273    if (IsPIE)274      CmdArgs.push_back("-pic-is-pie");275  }276}277 278void Flang::AddAArch64TargetArgs(const ArgList &Args,279                                 ArgStringList &CmdArgs) const {280  // Handle -msve_vector_bits=<bits>281  if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) {282    StringRef Val = A->getValue();283    const Driver &D = getToolChain().getDriver();284    if (Val == "128" || Val == "256" || Val == "512" || Val == "1024" ||285        Val == "2048" || Val == "128+" || Val == "256+" || Val == "512+" ||286        Val == "1024+" || Val == "2048+") {287      unsigned Bits = 0;288      if (!Val.consume_back("+")) {289        [[maybe_unused]] bool Invalid = Val.getAsInteger(10, Bits);290        assert(!Invalid && "Failed to parse value");291        CmdArgs.push_back(292            Args.MakeArgString("-mvscale-max=" + llvm::Twine(Bits / 128)));293      }294 295      [[maybe_unused]] bool Invalid = Val.getAsInteger(10, Bits);296      assert(!Invalid && "Failed to parse value");297      CmdArgs.push_back(298          Args.MakeArgString("-mvscale-min=" + llvm::Twine(Bits / 128)));299      // Silently drop requests for vector-length agnostic code as it's implied.300    } else if (Val != "scalable")301      // Handle the unsupported values passed to msve-vector-bits.302      D.Diag(diag::err_drv_unsupported_option_argument)303          << A->getSpelling() << Val;304  }305}306 307void Flang::AddLoongArch64TargetArgs(const ArgList &Args,308                                     ArgStringList &CmdArgs) const {309  const Driver &D = getToolChain().getDriver();310  // Currently, flang only support `-mabi=lp64d` in LoongArch64.311  if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {312    StringRef V = A->getValue();313    if (V != "lp64d") {314      D.Diag(diag::err_drv_argument_not_allowed_with) << "-mabi" << V;315    }316  }317 318  if (const Arg *A = Args.getLastArg(options::OPT_mannotate_tablejump,319                                     options::OPT_mno_annotate_tablejump)) {320    if (A->getOption().matches(options::OPT_mannotate_tablejump)) {321      CmdArgs.push_back("-mllvm");322      CmdArgs.push_back("-loongarch-annotate-tablejump");323    }324  }325}326 327void Flang::AddPPCTargetArgs(const ArgList &Args,328                             ArgStringList &CmdArgs) const {329  const Driver &D = getToolChain().getDriver();330  bool VecExtabi = false;331 332  if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {333    StringRef V = A->getValue();334    if (V == "vec-extabi")335      VecExtabi = true;336    else if (V == "vec-default")337      VecExtabi = false;338    else339      D.Diag(diag::err_drv_unsupported_option_argument)340          << A->getSpelling() << V;341  }342 343  const llvm::Triple &T = getToolChain().getTriple();344  if (VecExtabi) {345    if (!T.isOSAIX()) {346      D.Diag(diag::err_drv_unsupported_opt_for_target)347          << "-mabi=vec-extabi" << T.str();348    }349    CmdArgs.push_back("-mabi=vec-extabi");350  }351}352 353void Flang::AddRISCVTargetArgs(const ArgList &Args,354                               ArgStringList &CmdArgs) const {355  const Driver &D = getToolChain().getDriver();356  const llvm::Triple &Triple = getToolChain().getTriple();357 358  StringRef ABIName = riscv::getRISCVABI(Args, Triple);359  if (ABIName == "lp64" || ABIName == "lp64f" || ABIName == "lp64d")360    CmdArgs.push_back(Args.MakeArgString("-mabi=" + ABIName));361  else362    D.Diag(diag::err_drv_unsupported_option_argument) << "-mabi=" << ABIName;363 364  // Handle -mrvv-vector-bits=<bits>365  if (Arg *A = Args.getLastArg(options::OPT_mrvv_vector_bits_EQ)) {366    StringRef Val = A->getValue();367 368    // Get minimum VLen from march.369    unsigned MinVLen = 0;370    std::string Arch = riscv::getRISCVArch(Args, Triple);371    auto ISAInfo = llvm::RISCVISAInfo::parseArchString(372        Arch, /*EnableExperimentalExtensions*/ true);373    // Ignore parsing error.374    if (!errorToBool(ISAInfo.takeError()))375      MinVLen = (*ISAInfo)->getMinVLen();376 377    // If the value is "zvl", use MinVLen from march. Otherwise, try to parse378    // as integer as long as we have a MinVLen.379    unsigned Bits = 0;380    if (Val == "zvl" && MinVLen >= llvm::RISCV::RVVBitsPerBlock) {381      Bits = MinVLen;382    } else if (!Val.getAsInteger(10, Bits)) {383      // Only accept power of 2 values beteen RVVBitsPerBlock and 65536 that384      // at least MinVLen.385      if (Bits < MinVLen || Bits < llvm::RISCV::RVVBitsPerBlock ||386          Bits > 65536 || !llvm::isPowerOf2_32(Bits))387        Bits = 0;388    }389 390    // If we got a valid value try to use it.391    if (Bits != 0) {392      unsigned VScaleMin = Bits / llvm::RISCV::RVVBitsPerBlock;393      CmdArgs.push_back(394          Args.MakeArgString("-mvscale-max=" + llvm::Twine(VScaleMin)));395      CmdArgs.push_back(396          Args.MakeArgString("-mvscale-min=" + llvm::Twine(VScaleMin)));397    } else if (Val != "scalable") {398      // Handle the unsupported values passed to mrvv-vector-bits.399      D.Diag(diag::err_drv_unsupported_option_argument)400          << A->getSpelling() << Val;401    }402  }403}404 405void Flang::AddX86_64TargetArgs(const ArgList &Args,406                                ArgStringList &CmdArgs) const {407  if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {408    StringRef Value = A->getValue();409    if (Value == "intel" || Value == "att") {410      CmdArgs.push_back(Args.MakeArgString("-mllvm"));411      CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));412    } else {413      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)414          << A->getSpelling() << Value;415    }416  }417}418 419static void addVSDefines(const ToolChain &TC, const ArgList &Args,420                         ArgStringList &CmdArgs) {421 422  unsigned ver = 0;423  const VersionTuple vt = TC.computeMSVCVersion(nullptr, Args);424  ver = vt.getMajor() * 10000000 + vt.getMinor().value_or(0) * 100000 +425        vt.getSubminor().value_or(0);426  CmdArgs.push_back(Args.MakeArgString("-D_MSC_VER=" + Twine(ver / 100000)));427  CmdArgs.push_back(Args.MakeArgString("-D_MSC_FULL_VER=" + Twine(ver)));428  CmdArgs.push_back(Args.MakeArgString("-D_WIN32"));429 430  const llvm::Triple &triple = TC.getTriple();431  if (triple.isAArch64()) {432    CmdArgs.push_back("-D_M_ARM64=1");433  } else if (triple.isX86() && triple.isArch32Bit()) {434    CmdArgs.push_back("-D_M_IX86=600");435  } else if (triple.isX86() && triple.isArch64Bit()) {436    CmdArgs.push_back("-D_M_X64=100");437  } else {438    llvm_unreachable(439        "Flang on Windows only supports X86_32, X86_64 and AArch64");440  }441}442 443static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,444                                    ArgStringList &CmdArgs) {445  assert(TC.getTriple().isKnownWindowsMSVCEnvironment() &&446         "can only add VS runtime library on Windows!");447 448  // Flang/Clang (including clang-cl) -compiled programs targeting the MSVC ABI449  // should only depend on msv(u)crt. LLVM still emits libgcc/compiler-rt450  // functions in some cases like 128-bit integer math (__udivti3, __modti3,451  // __fixsfti, __floattidf, ...) that msvc does not support. We are injecting a452  // dependency to Compiler-RT's builtin library where these are implemented.453  CmdArgs.push_back(Args.MakeArgString(454      "--dependent-lib=" + TC.getCompilerRTBasename(Args, "builtins")));455 456  unsigned RTOptionID = options::OPT__SLASH_MT;457  if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {458    RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())459                     .Case("static", options::OPT__SLASH_MT)460                     .Case("static_dbg", options::OPT__SLASH_MTd)461                     .Case("dll", options::OPT__SLASH_MD)462                     .Case("dll_dbg", options::OPT__SLASH_MDd)463                     .Default(options::OPT__SLASH_MT);464  }465  switch (RTOptionID) {466  case options::OPT__SLASH_MT:467    CmdArgs.push_back("-D_MT");468    CmdArgs.push_back("--dependent-lib=libcmt");469    CmdArgs.push_back("--dependent-lib=flang_rt.runtime.static.lib");470    break;471  case options::OPT__SLASH_MTd:472    CmdArgs.push_back("-D_MT");473    CmdArgs.push_back("-D_DEBUG");474    CmdArgs.push_back("--dependent-lib=libcmtd");475    CmdArgs.push_back("--dependent-lib=flang_rt.runtime.static_dbg.lib");476    break;477  case options::OPT__SLASH_MD:478    CmdArgs.push_back("-D_MT");479    CmdArgs.push_back("-D_DLL");480    CmdArgs.push_back("--dependent-lib=msvcrt");481    CmdArgs.push_back("--dependent-lib=flang_rt.runtime.dynamic.lib");482    break;483  case options::OPT__SLASH_MDd:484    CmdArgs.push_back("-D_MT");485    CmdArgs.push_back("-D_DEBUG");486    CmdArgs.push_back("-D_DLL");487    CmdArgs.push_back("--dependent-lib=msvcrtd");488    CmdArgs.push_back("--dependent-lib=flang_rt.runtime.dynamic_dbg.lib");489    break;490  }491}492 493void Flang::AddAMDGPUTargetArgs(const ArgList &Args,494                                ArgStringList &CmdArgs) const {495  if (Arg *A = Args.getLastArg(options::OPT_mcode_object_version_EQ)) {496    StringRef Val = A->getValue();497    CmdArgs.push_back(Args.MakeArgString("-mcode-object-version=" + Val));498    CmdArgs.push_back(Args.MakeArgString("-mllvm"));499    CmdArgs.push_back(500        Args.MakeArgString("--amdhsa-code-object-version=" + Val));501  }502 503  const ToolChain &TC = getToolChain();504  TC.addClangTargetOptions(Args, CmdArgs, Action::OffloadKind::OFK_OpenMP);505}506 507void Flang::addTargetOptions(const ArgList &Args,508                             ArgStringList &CmdArgs) const {509  const ToolChain &TC = getToolChain();510  const llvm::Triple &Triple = TC.getEffectiveTriple();511  const Driver &D = TC.getDriver();512 513  std::string CPU = getCPUName(D, Args, Triple);514  if (!CPU.empty()) {515    CmdArgs.push_back("-target-cpu");516    CmdArgs.push_back(Args.MakeArgString(CPU));517  }518 519  addOutlineAtomicsArgs(D, getToolChain(), Args, CmdArgs, Triple);520 521  // Add the target features.522  switch (TC.getArch()) {523  default:524    getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);525    break;526  case llvm::Triple::aarch64:527    getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);528    AddAArch64TargetArgs(Args, CmdArgs);529    break;530 531  case llvm::Triple::r600:532  case llvm::Triple::amdgcn:533    getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);534    AddAMDGPUTargetArgs(Args, CmdArgs);535    break;536  case llvm::Triple::riscv64:537    getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);538    AddRISCVTargetArgs(Args, CmdArgs);539    break;540  case llvm::Triple::x86_64:541    getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);542    AddX86_64TargetArgs(Args, CmdArgs);543    break;544  case llvm::Triple::ppc:545  case llvm::Triple::ppc64:546  case llvm::Triple::ppc64le:547    AddPPCTargetArgs(Args, CmdArgs);548    break;549  case llvm::Triple::loongarch64:550    getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);551    AddLoongArch64TargetArgs(Args, CmdArgs);552    break;553  }554 555  if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {556    StringRef Name = A->getValue();557    if (Name == "SVML") {558      if (Triple.getArch() != llvm::Triple::x86 &&559          Triple.getArch() != llvm::Triple::x86_64)560        D.Diag(diag::err_drv_unsupported_opt_for_target)561            << Name << Triple.getArchName();562    } else if (Name == "AMDLIBM") {563      if (Triple.getArch() != llvm::Triple::x86 &&564          Triple.getArch() != llvm::Triple::x86_64)565        D.Diag(diag::err_drv_unsupported_opt_for_target)566            << Name << Triple.getArchName();567    } else if (Name == "libmvec") {568      if (Triple.getArch() != llvm::Triple::x86 &&569          Triple.getArch() != llvm::Triple::x86_64 &&570          Triple.getArch() != llvm::Triple::aarch64 &&571          Triple.getArch() != llvm::Triple::aarch64_be)572        D.Diag(diag::err_drv_unsupported_opt_for_target)573            << Name << Triple.getArchName();574    } else if (Name == "SLEEF" || Name == "ArmPL") {575      if (Triple.getArch() != llvm::Triple::aarch64 &&576          Triple.getArch() != llvm::Triple::aarch64_be)577        D.Diag(diag::err_drv_unsupported_opt_for_target)578            << Name << Triple.getArchName();579    }580 581    if (Triple.isOSDarwin()) {582      // flang doesn't currently suport nostdlib, nodefaultlibs. Adding these583      // here incase they are added someday584      if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {585        if (A->getValue() == StringRef{"Accelerate"}) {586          CmdArgs.push_back("-framework");587          CmdArgs.push_back("Accelerate");588        }589      }590    }591    A->render(Args, CmdArgs);592  }593 594  if (Triple.isKnownWindowsMSVCEnvironment()) {595    processVSRuntimeLibrary(TC, Args, CmdArgs);596    addVSDefines(TC, Args, CmdArgs);597  }598 599  // TODO: Add target specific flags, ABI, mtune option etc.600  if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) {601    CmdArgs.push_back("-tune-cpu");602    if (A->getValue() == StringRef{"native"})603      CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName()));604    else605      CmdArgs.push_back(A->getValue());606  }607 608  Args.addAllArgs(CmdArgs,609                  {options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,610                   options::OPT_fatomic_ignore_denormal_mode,611                   options::OPT_fno_atomic_ignore_denormal_mode,612                   options::OPT_fatomic_fine_grained_memory,613                   options::OPT_fno_atomic_fine_grained_memory,614                   options::OPT_fatomic_remote_memory,615                   options::OPT_fno_atomic_remote_memory,616                   options::OPT_munsafe_fp_atomics});617}618 619void Flang::addOffloadOptions(Compilation &C, const InputInfoList &Inputs,620                              const JobAction &JA, const ArgList &Args,621                              ArgStringList &CmdArgs) const {622  bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);623  bool IsHostOffloadingAction = JA.isHostOffloading(Action::OFK_OpenMP) ||624                                JA.isHostOffloading(C.getActiveOffloadKinds());625 626  // Skips the primary input file, which is the input file that the compilation627  // proccess will be executed upon (e.g. the host bitcode file) and628  // adds other secondary input (e.g. device bitcode files for embedding to the629  // -fembed-offload-object argument or the host IR file for proccessing630  // during device compilation to the fopenmp-host-ir-file-path argument via631  // OpenMPDeviceInput). This is condensed logic from the ConstructJob632  // function inside of the Clang driver for pushing on further input arguments633  // needed for offloading during various phases of compilation.634  for (size_t i = 1; i < Inputs.size(); ++i) {635    if (Inputs[i].getType() == types::TY_Nothing) {636      // contains nothing, so it's skippable637    } else if (IsHostOffloadingAction) {638      CmdArgs.push_back(639          Args.MakeArgString("-fembed-offload-object=" +640                             getToolChain().getInputFilename(Inputs[i])));641    } else if (IsOpenMPDevice) {642      if (Inputs[i].getFilename()) {643        CmdArgs.push_back("-fopenmp-host-ir-file-path");644        CmdArgs.push_back(Args.MakeArgString(Inputs[i].getFilename()));645      } else {646        llvm_unreachable("missing openmp host-ir file for device offloading");647      }648    } else {649      llvm_unreachable(650          "unexpectedly given multiple inputs or given unknown input");651    }652  }653 654  if (IsOpenMPDevice) {655    // -fopenmp-is-target-device is passed along to tell the frontend that it is656    // generating code for a device, so that only the relevant code is emitted.657    CmdArgs.push_back("-fopenmp-is-target-device");658 659    // When in OpenMP offloading mode, enable debugging on the device.660    Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_target_debug_EQ);661    if (Args.hasFlag(options::OPT_fopenmp_target_debug,662                     options::OPT_fno_openmp_target_debug, /*Default=*/false))663      CmdArgs.push_back("-fopenmp-target-debug");664 665    // When in OpenMP offloading mode, forward assumptions information about666    // thread and team counts in the device.667    if (Args.hasFlag(options::OPT_fopenmp_assume_teams_oversubscription,668                     options::OPT_fno_openmp_assume_teams_oversubscription,669                     /*Default=*/false))670      CmdArgs.push_back("-fopenmp-assume-teams-oversubscription");671    if (Args.hasFlag(options::OPT_fopenmp_assume_threads_oversubscription,672                     options::OPT_fno_openmp_assume_threads_oversubscription,673                     /*Default=*/false))674      CmdArgs.push_back("-fopenmp-assume-threads-oversubscription");675    if (Args.hasArg(options::OPT_fopenmp_assume_no_thread_state))676      CmdArgs.push_back("-fopenmp-assume-no-thread-state");677    if (Args.hasArg(options::OPT_fopenmp_assume_no_nested_parallelism))678      CmdArgs.push_back("-fopenmp-assume-no-nested-parallelism");679    if (!Args.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,680                      true))681      CmdArgs.push_back("-nogpulib");682  }683 684  addOpenMPHostOffloadingArgs(C, JA, Args, CmdArgs);685}686 687static void addFloatingPointOptions(const Driver &D, const ArgList &Args,688                                    ArgStringList &CmdArgs) {689  StringRef FPContract;690  bool HonorINFs = true;691  bool HonorNaNs = true;692  bool ApproxFunc = false;693  bool SignedZeros = true;694  bool AssociativeMath = false;695  bool ReciprocalMath = false;696 697  StringRef LastComplexRangeOption;698  LangOptions::ComplexRangeKind Range = LangOptions::ComplexRangeKind::CX_None;699 700  if (const Arg *A = Args.getLastArg(options::OPT_ffp_contract)) {701    const StringRef Val = A->getValue();702    if (Val == "fast" || Val == "off") {703      FPContract = Val;704    } else if (Val == "on") {705      // Warn instead of error because users might have makefiles written for706      // gfortran (which accepts -ffp-contract=on)707      D.Diag(diag::warn_drv_unsupported_option_for_flang)708          << Val << A->getOption().getName() << "off";709      FPContract = "off";710    } else711      // Clang's "fast-honor-pragmas" option is not supported because it is712      // non-standard713      D.Diag(diag::err_drv_unsupported_option_argument)714          << A->getSpelling() << Val;715  }716 717  for (const Arg *A : Args) {718    auto optId = A->getOption().getID();719    switch (optId) {720    // if this isn't an FP option, skip the claim below721    default:722      continue;723 724    case options::OPT_fcomplex_arithmetic_EQ: {725      LangOptions::ComplexRangeKind NewRange;726      StringRef Val = A->getValue();727      if (Val == "full")728        NewRange = LangOptions::ComplexRangeKind::CX_Full;729      else if (Val == "improved")730        NewRange = LangOptions::ComplexRangeKind::CX_Improved;731      else if (Val == "basic")732        NewRange = LangOptions::ComplexRangeKind::CX_Basic;733      else {734        D.Diag(diag::err_drv_unsupported_option_argument)735            << A->getSpelling() << Val;736        break;737      }738 739      setComplexRange(D, Args.MakeArgString(A->getSpelling() + Val), NewRange,740                      LastComplexRangeOption, Range);741      break;742    }743    case options::OPT_fhonor_infinities:744      HonorINFs = true;745      break;746    case options::OPT_fno_honor_infinities:747      HonorINFs = false;748      break;749    case options::OPT_fhonor_nans:750      HonorNaNs = true;751      break;752    case options::OPT_fno_honor_nans:753      HonorNaNs = false;754      break;755    case options::OPT_fapprox_func:756      ApproxFunc = true;757      break;758    case options::OPT_fno_approx_func:759      ApproxFunc = false;760      break;761    case options::OPT_fsigned_zeros:762      SignedZeros = true;763      break;764    case options::OPT_fno_signed_zeros:765      SignedZeros = false;766      break;767    case options::OPT_fassociative_math:768      AssociativeMath = true;769      break;770    case options::OPT_fno_associative_math:771      AssociativeMath = false;772      break;773    case options::OPT_freciprocal_math:774      ReciprocalMath = true;775      break;776    case options::OPT_fno_reciprocal_math:777      ReciprocalMath = false;778      break;779    case options::OPT_Ofast:780      [[fallthrough]];781    case options::OPT_ffast_math:782      HonorINFs = false;783      HonorNaNs = false;784      AssociativeMath = true;785      ReciprocalMath = true;786      ApproxFunc = true;787      SignedZeros = false;788      FPContract = "fast";789      setComplexRange(D, A->getSpelling(),790                      LangOptions::ComplexRangeKind::CX_Basic,791                      LastComplexRangeOption, Range);792      break;793    case options::OPT_fno_fast_math:794      HonorINFs = true;795      HonorNaNs = true;796      AssociativeMath = false;797      ReciprocalMath = false;798      ApproxFunc = false;799      SignedZeros = true;800      // -fno-fast-math should undo -ffast-math so I return FPContract to the801      // default. It is important to check it is "fast" (the default) so that802      // --ffp-contract=off -fno-fast-math --> -ffp-contract=off803      if (FPContract == "fast")804        FPContract = "";805      setComplexRange(D, A->getSpelling(),806                      LangOptions::ComplexRangeKind::CX_None,807                      LastComplexRangeOption, Range);808      break;809    }810 811    // If we handled this option claim it812    A->claim();813  }814 815  StringRef Recip = parseMRecipOption(D.getDiags(), Args);816  if (!Recip.empty())817    CmdArgs.push_back(Args.MakeArgString("-mrecip=" + Recip));818 819  if (Range != LangOptions::ComplexRangeKind::CX_None) {820    std::string ComplexRangeStr = renderComplexRangeOption(Range);821    CmdArgs.push_back(Args.MakeArgString(ComplexRangeStr));822    CmdArgs.push_back(Args.MakeArgString("-fcomplex-arithmetic=" +823                                         complexRangeKindToStr(Range)));824  }825 826  if (llvm::opt::Arg *A =827          Args.getLastArg(clang::options::OPT_ffast_real_mod,828                          clang::options::OPT_fno_fast_real_mod)) {829    if (A->getOption().matches(clang::options::OPT_ffast_real_mod))830      CmdArgs.push_back("-ffast-real-mod");831    else if (A->getOption().matches(clang::options::OPT_fno_fast_real_mod))832      CmdArgs.push_back("-fno-fast-real-mod");833  }834 835  if (!HonorINFs && !HonorNaNs && AssociativeMath && ReciprocalMath &&836      ApproxFunc && !SignedZeros &&837      (FPContract == "fast" || FPContract.empty())) {838    CmdArgs.push_back("-ffast-math");839    return;840  }841 842  if (!FPContract.empty())843    CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));844 845  if (!HonorINFs)846    CmdArgs.push_back("-menable-no-infs");847 848  if (!HonorNaNs)849    CmdArgs.push_back("-menable-no-nans");850 851  if (ApproxFunc)852    CmdArgs.push_back("-fapprox-func");853 854  if (!SignedZeros)855    CmdArgs.push_back("-fno-signed-zeros");856 857  if (AssociativeMath && !SignedZeros)858    CmdArgs.push_back("-mreassociate");859 860  if (ReciprocalMath)861    CmdArgs.push_back("-freciprocal-math");862}863 864static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,865                                 const InputInfo &Input) {866  StringRef Format = "yaml";867  if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))868    Format = A->getValue();869 870  CmdArgs.push_back("-opt-record-file");871 872  const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);873  if (A) {874    CmdArgs.push_back(A->getValue());875  } else {876    SmallString<128> F;877 878    if (Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) {879      if (Arg *FinalOutput = Args.getLastArg(options::OPT_o))880        F = FinalOutput->getValue();881    }882 883    if (F.empty()) {884      // Use the input filename.885      F = llvm::sys::path::stem(Input.getBaseInput());886    }887 888    SmallString<32> Extension;889    Extension += "opt.";890    Extension += Format;891 892    llvm::sys::path::replace_extension(F, Extension);893    CmdArgs.push_back(Args.MakeArgString(F));894  }895 896  if (const Arg *A =897          Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {898    CmdArgs.push_back("-opt-record-passes");899    CmdArgs.push_back(A->getValue());900  }901 902  if (!Format.empty()) {903    CmdArgs.push_back("-opt-record-format");904    CmdArgs.push_back(Format.data());905  }906}907 908void Flang::ConstructJob(Compilation &C, const JobAction &JA,909                         const InputInfo &Output, const InputInfoList &Inputs,910                         const ArgList &Args, const char *LinkingOutput) const {911  const auto &TC = getToolChain();912  const llvm::Triple &Triple = TC.getEffectiveTriple();913  const std::string &TripleStr = Triple.getTriple();914 915  const Driver &D = TC.getDriver();916  ArgStringList CmdArgs;917 918  // Invoke ourselves in -fc1 mode.919  CmdArgs.push_back("-fc1");920 921  // Add the "effective" target triple.922  CmdArgs.push_back("-triple");923  CmdArgs.push_back(Args.MakeArgString(TripleStr));924 925  if (isa<PreprocessJobAction>(JA)) {926    CmdArgs.push_back("-E");927    if (Args.getLastArg(options::OPT_dM)) {928      CmdArgs.push_back("-dM");929    }930  } else if (isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) {931    if (JA.getType() == types::TY_Nothing) {932      CmdArgs.push_back("-fsyntax-only");933    } else if (JA.getType() == types::TY_AST) {934      CmdArgs.push_back("-emit-ast");935    } else if (JA.getType() == types::TY_LLVM_IR ||936               JA.getType() == types::TY_LTO_IR) {937      CmdArgs.push_back("-emit-llvm");938    } else if (JA.getType() == types::TY_LLVM_BC ||939               JA.getType() == types::TY_LTO_BC) {940      CmdArgs.push_back("-emit-llvm-bc");941    } else if (JA.getType() == types::TY_PP_Asm) {942      CmdArgs.push_back("-S");943    } else {944      assert(false && "Unexpected output type!");945    }946  } else if (isa<AssembleJobAction>(JA)) {947    CmdArgs.push_back("-emit-obj");948  } else if (isa<PrecompileJobAction>(JA)) {949    // The precompile job action is only needed for options such as -mcpu=help.950    // Those will already have been handled by the fc1 driver.951  } else {952    assert(false && "Unexpected action class for Flang tool.");953  }954 955  // We support some options that are invalid for Fortran and have no effect.956  // These are solely for compatibility with other compilers. Emit a warning if957  // any such options are provided, then proceed normally.958  for (options::ID Opt : {options::OPT_fbuiltin, options::OPT_fno_builtin})959    if (const Arg *A = Args.getLastArg(Opt))960      D.Diag(diag::warn_drv_invalid_argument_for_flang) << A->getSpelling();961 962  const InputInfo &Input = Inputs[0];963  types::ID InputType = Input.getType();964 965  // Add preprocessing options like -I, -D, etc. if we are using the966  // preprocessor (i.e. skip when dealing with e.g. binary files).967  if (types::getPreprocessedType(InputType) != types::TY_INVALID)968    addPreprocessingOptions(Args, CmdArgs);969 970  addFortranDialectOptions(Args, CmdArgs);971 972  // 'flang -E' always produces output that is suitable for use as fixed form973  // Fortran. However it is only valid free form source if the original is also974  // free form. Ensure this logic does not incorrectly assume fixed-form for975  // cases where it shouldn't, such as `flang -x f95 foo.f90`.976  bool isAtemporaryPreprocessedFile =977      Input.isFilename() &&978      llvm::sys::path::extension(Input.getFilename())979          .ends_with(types::getTypeTempSuffix(InputType, /*CLStyle=*/false));980  if (InputType == types::TY_PP_Fortran && isAtemporaryPreprocessedFile &&981      !Args.getLastArg(options::OPT_ffixed_form, options::OPT_ffree_form))982    CmdArgs.push_back("-ffixed-form");983 984  handleColorDiagnosticsArgs(D, Args, CmdArgs);985 986  addLTOOptions(Args, CmdArgs);987 988  // -fPIC and related options.989  addPicOptions(Args, CmdArgs);990 991  // Floating point related options992  addFloatingPointOptions(D, Args, CmdArgs);993 994  // Add target args, features, etc.995  addTargetOptions(Args, CmdArgs);996 997  llvm::Reloc::Model RelocationModel =998      std::get<0>(ParsePICArgs(getToolChain(), Args));999  // Add MCModel information1000  addMCModel(D, Args, Triple, RelocationModel, CmdArgs);1001 1002  // Add Codegen options1003  addCodegenOptions(Args, CmdArgs);1004 1005  // Add R Group options1006  Args.AddAllArgs(CmdArgs, options::OPT_R_Group);1007 1008  // Remarks can be enabled with any of the `-f.*optimization-record.*` flags.1009  if (willEmitRemarks(Args))1010    renderRemarksOptions(Args, CmdArgs, Input);1011 1012  // Add debug compile options1013  addDebugOptions(Args, JA, Output, Input, CmdArgs);1014 1015  // Disable all warnings1016  // TODO: Handle interactions between -w, -pedantic, -Wall, -WOption1017  Args.AddLastArg(CmdArgs, options::OPT_w);1018 1019  // recognise options: fprofile-generate -fprofile-use=1020  Args.addAllArgs(1021      CmdArgs, {options::OPT_fprofile_generate, options::OPT_fprofile_use_EQ});1022 1023  // Forward flags for OpenMP. We don't do this if the current action is an1024  // device offloading action other than OpenMP.1025  if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,1026                   options::OPT_fno_openmp, false) &&1027      (JA.isDeviceOffloading(Action::OFK_None) ||1028       JA.isDeviceOffloading(Action::OFK_OpenMP))) {1029    switch (D.getOpenMPRuntime(Args)) {1030    case Driver::OMPRT_OMP:1031    case Driver::OMPRT_IOMP5:1032      // Clang can generate useful OpenMP code for these two runtime libraries.1033      CmdArgs.push_back("-fopenmp");1034      Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);1035 1036      if (Args.hasArg(options::OPT_fopenmp_force_usm))1037        CmdArgs.push_back("-fopenmp-force-usm");1038      Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,1039                      options::OPT_fno_openmp_simd);1040 1041      // FIXME: Clang supports a whole bunch more flags here.1042      break;1043    default:1044      // By default, if Clang doesn't know how to generate useful OpenMP code1045      // for a specific runtime library, we just don't pass the '-fopenmp' flag1046      // down to the actual compilation.1047      // FIXME: It would be better to have a mode which *only* omits IR1048      // generation based on the OpenMP support so that we get consistent1049      // semantic analysis, etc.1050      const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ);1051      D.Diag(diag::warn_drv_unsupported_openmp_library)1052          << A->getSpelling() << A->getValue();1053      break;1054    }1055  } else {1056    Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,1057                    options::OPT_fno_openmp_simd);1058  }1059 1060  // Pass the path to compiler resource files.1061  CmdArgs.push_back("-resource-dir");1062  CmdArgs.push_back(D.ResourceDir.c_str());1063 1064  // Offloading related options1065  addOffloadOptions(C, Inputs, JA, Args, CmdArgs);1066 1067  // Forward -Xflang arguments to -fc11068  Args.AddAllArgValues(CmdArgs, options::OPT_Xflang);1069 1070  CodeGenOptions::FramePointerKind FPKeepKind =1071      getFramePointerKind(Args, Triple);1072 1073  const char *FPKeepKindStr = nullptr;1074  switch (FPKeepKind) {1075  case CodeGenOptions::FramePointerKind::None:1076    FPKeepKindStr = "-mframe-pointer=none";1077    break;1078  case CodeGenOptions::FramePointerKind::Reserved:1079    FPKeepKindStr = "-mframe-pointer=reserved";1080    break;1081  case CodeGenOptions::FramePointerKind::NonLeafNoReserve:1082    FPKeepKindStr = "-mframe-pointer=non-leaf-no-reserve";1083    break;1084  case CodeGenOptions::FramePointerKind::NonLeaf:1085    FPKeepKindStr = "-mframe-pointer=non-leaf";1086    break;1087  case CodeGenOptions::FramePointerKind::All:1088    FPKeepKindStr = "-mframe-pointer=all";1089    break;1090  }1091  assert(FPKeepKindStr && "unknown FramePointerKind");1092  CmdArgs.push_back(FPKeepKindStr);1093 1094  // Forward -mllvm options to the LLVM option parser. In practice, this means1095  // forwarding to `-fc1` as that's where the LLVM parser is run.1096  for (const Arg *A : Args.filtered(options::OPT_mllvm)) {1097    A->claim();1098    A->render(Args, CmdArgs);1099  }1100 1101  for (const Arg *A : Args.filtered(options::OPT_mmlir)) {1102    A->claim();1103    A->render(Args, CmdArgs);1104  }1105 1106  // Remove any unsupported gfortran diagnostic options1107  for (const Arg *A : Args.filtered(options::OPT_flang_ignored_w_Group)) {1108    A->claim();1109    D.Diag(diag::warn_drv_unsupported_diag_option_for_flang)1110        << A->getOption().getName();1111  }1112 1113  // Optimization level for CodeGen.1114  if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) {1115    if (A->getOption().matches(options::OPT_O4)) {1116      CmdArgs.push_back("-O3");1117      D.Diag(diag::warn_O4_is_O3);1118    } else if (A->getOption().matches(options::OPT_Ofast)) {1119      CmdArgs.push_back("-O3");1120      D.Diag(diag::warn_drv_deprecated_arg_ofast_for_flang);1121    } else {1122      A->render(Args, CmdArgs);1123    }1124  }1125 1126  renderCommonIntegerOverflowOptions(Args, CmdArgs);1127 1128  assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");1129  if (Output.isFilename()) {1130    CmdArgs.push_back("-o");1131    CmdArgs.push_back(Output.getFilename());1132  }1133 1134  if (Args.getLastArg(options::OPT_save_temps_EQ))1135    Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ);1136 1137  addDashXForInput(Args, Input, CmdArgs);1138 1139  bool FRecordCmdLine = false;1140  bool GRecordCmdLine = false;1141  if (shouldRecordCommandLine(TC, Args, FRecordCmdLine, GRecordCmdLine)) {1142    const char *CmdLine = renderEscapedCommandLine(TC, Args);1143    if (FRecordCmdLine) {1144      CmdArgs.push_back("-record-command-line");1145      CmdArgs.push_back(CmdLine);1146    }1147    if (TC.UseDwarfDebugFlags() || GRecordCmdLine) {1148      CmdArgs.push_back("-dwarf-debug-flags");1149      CmdArgs.push_back(CmdLine);1150    }1151  }1152 1153  // The input could be Ty_Nothing when "querying" options such as -mcpu=help1154  // are used.1155  ArrayRef<InputInfo> FrontendInputs = Input;1156  if (Input.isNothing())1157    FrontendInputs = {};1158 1159  for (const InputInfo &Input : FrontendInputs) {1160    if (Input.isFilename())1161      CmdArgs.push_back(Input.getFilename());1162    else1163      Input.getInputArg().renderAsInput(Args, CmdArgs);1164  }1165 1166  const char *Exec = Args.MakeArgString(D.GetProgramPath("flang", TC));1167  C.addCommand(std::make_unique<Command>(JA, *this,1168                                         ResponseFileSupport::AtFileUTF8(),1169                                         Exec, CmdArgs, Inputs, Output));1170}1171 1172Flang::Flang(const ToolChain &TC) : Tool("flang", "flang frontend", TC) {}1173 1174Flang::~Flang() {}1175