1480093f4SDimitry Andric //===-- Flang.cpp - Flang+LLVM ToolChain Implementations --------*- C++ -*-===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric 9480093f4SDimitry Andric #include "Flang.h" 10480093f4SDimitry Andric #include "CommonArgs.h" 11480093f4SDimitry Andric 12*5f757f3fSDimitry Andric #include "clang/Basic/CodeGenOptions.h" 13480093f4SDimitry Andric #include "clang/Driver/Options.h" 1406c3fb27SDimitry Andric #include "llvm/Frontend/Debug/Options.h" 15*5f757f3fSDimitry Andric #include "llvm/Support/FileSystem.h" 16*5f757f3fSDimitry Andric #include "llvm/Support/Path.h" 17480093f4SDimitry Andric 18480093f4SDimitry Andric #include <cassert> 19480093f4SDimitry Andric 20480093f4SDimitry Andric using namespace clang::driver; 21480093f4SDimitry Andric using namespace clang::driver::tools; 22480093f4SDimitry Andric using namespace clang; 23480093f4SDimitry Andric using namespace llvm::opt; 24480093f4SDimitry Andric 2581ad6265SDimitry Andric /// Add -x lang to \p CmdArgs for \p Input. 2681ad6265SDimitry Andric static void addDashXForInput(const ArgList &Args, const InputInfo &Input, 2781ad6265SDimitry Andric ArgStringList &CmdArgs) { 2881ad6265SDimitry Andric CmdArgs.push_back("-x"); 2981ad6265SDimitry Andric // Map the driver type to the frontend type. 3081ad6265SDimitry Andric CmdArgs.push_back(types::getTypeName(Input.getType())); 3181ad6265SDimitry Andric } 3281ad6265SDimitry Andric 33bdd1243dSDimitry Andric void Flang::addFortranDialectOptions(const ArgList &Args, 34fe6060f1SDimitry Andric ArgStringList &CmdArgs) const { 35*5f757f3fSDimitry Andric Args.addAllArgs(CmdArgs, {options::OPT_ffixed_form, 3606c3fb27SDimitry Andric options::OPT_ffree_form, 3706c3fb27SDimitry Andric options::OPT_ffixed_line_length_EQ, 3806c3fb27SDimitry Andric options::OPT_fopenmp, 3906c3fb27SDimitry Andric options::OPT_fopenmp_version_EQ, 4006c3fb27SDimitry Andric options::OPT_fopenacc, 4106c3fb27SDimitry Andric options::OPT_finput_charset_EQ, 4206c3fb27SDimitry Andric options::OPT_fimplicit_none, 4306c3fb27SDimitry Andric options::OPT_fno_implicit_none, 4406c3fb27SDimitry Andric options::OPT_fbackslash, 4506c3fb27SDimitry Andric options::OPT_fno_backslash, 46fe6060f1SDimitry Andric options::OPT_flogical_abbreviations, 47fe6060f1SDimitry Andric options::OPT_fno_logical_abbreviations, 4806c3fb27SDimitry Andric options::OPT_fxor_operator, 4906c3fb27SDimitry Andric options::OPT_fno_xor_operator, 50fe6060f1SDimitry Andric options::OPT_falternative_parameter_statement, 5106c3fb27SDimitry Andric options::OPT_fdefault_real_8, 5206c3fb27SDimitry Andric options::OPT_fdefault_integer_8, 5306c3fb27SDimitry Andric options::OPT_fdefault_double_8, 5406c3fb27SDimitry Andric options::OPT_flarge_sizes, 554824e7fdSDimitry Andric options::OPT_fno_automatic}); 56fe6060f1SDimitry Andric } 57fe6060f1SDimitry Andric 58bdd1243dSDimitry Andric void Flang::addPreprocessingOptions(const ArgList &Args, 59e8d8bef9SDimitry Andric ArgStringList &CmdArgs) const { 60*5f757f3fSDimitry Andric Args.addAllArgs(CmdArgs, 61349cc55cSDimitry Andric {options::OPT_P, options::OPT_D, options::OPT_U, 62349cc55cSDimitry Andric options::OPT_I, options::OPT_cpp, options::OPT_nocpp}); 63fe6060f1SDimitry Andric } 64fe6060f1SDimitry Andric 6506c3fb27SDimitry Andric /// @C shouldLoopVersion 6606c3fb27SDimitry Andric /// 6706c3fb27SDimitry Andric /// Check if Loop Versioning should be enabled. 6806c3fb27SDimitry Andric /// We look for the last of one of the following: 6906c3fb27SDimitry Andric /// -Ofast, -O4, -O<number> and -f[no-]version-loops-for-stride. 7006c3fb27SDimitry Andric /// Loop versioning is disabled if the last option is 7106c3fb27SDimitry Andric /// -fno-version-loops-for-stride. 7206c3fb27SDimitry Andric /// Loop versioning is enabled if the last option is one of: 7306c3fb27SDimitry Andric /// -floop-versioning 7406c3fb27SDimitry Andric /// -Ofast 7506c3fb27SDimitry Andric /// -O4 7606c3fb27SDimitry Andric /// -O3 7706c3fb27SDimitry Andric /// For all other cases, loop versioning is is disabled. 7806c3fb27SDimitry Andric /// 7906c3fb27SDimitry Andric /// The gfortran compiler automatically enables the option for -O3 or -Ofast. 8006c3fb27SDimitry Andric /// 8106c3fb27SDimitry Andric /// @return true if loop-versioning should be enabled, otherwise false. 8206c3fb27SDimitry Andric static bool shouldLoopVersion(const ArgList &Args) { 8306c3fb27SDimitry Andric const Arg *LoopVersioningArg = Args.getLastArg( 8406c3fb27SDimitry Andric options::OPT_Ofast, options::OPT_O, options::OPT_O4, 8506c3fb27SDimitry Andric options::OPT_floop_versioning, options::OPT_fno_loop_versioning); 8606c3fb27SDimitry Andric if (!LoopVersioningArg) 8706c3fb27SDimitry Andric return false; 8806c3fb27SDimitry Andric 8906c3fb27SDimitry Andric if (LoopVersioningArg->getOption().matches(options::OPT_fno_loop_versioning)) 9006c3fb27SDimitry Andric return false; 9106c3fb27SDimitry Andric 9206c3fb27SDimitry Andric if (LoopVersioningArg->getOption().matches(options::OPT_floop_versioning)) 9306c3fb27SDimitry Andric return true; 9406c3fb27SDimitry Andric 9506c3fb27SDimitry Andric if (LoopVersioningArg->getOption().matches(options::OPT_Ofast) || 9606c3fb27SDimitry Andric LoopVersioningArg->getOption().matches(options::OPT_O4)) 9706c3fb27SDimitry Andric return true; 9806c3fb27SDimitry Andric 9906c3fb27SDimitry Andric if (LoopVersioningArg->getOption().matches(options::OPT_O)) { 10006c3fb27SDimitry Andric StringRef S(LoopVersioningArg->getValue()); 10106c3fb27SDimitry Andric unsigned OptLevel = 0; 10206c3fb27SDimitry Andric // Note -Os or Oz woould "fail" here, so return false. Which is the 10306c3fb27SDimitry Andric // desiered behavior. 10406c3fb27SDimitry Andric if (S.getAsInteger(10, OptLevel)) 10506c3fb27SDimitry Andric return false; 10606c3fb27SDimitry Andric 10706c3fb27SDimitry Andric return OptLevel > 2; 10806c3fb27SDimitry Andric } 10906c3fb27SDimitry Andric 11006c3fb27SDimitry Andric llvm_unreachable("We should not end up here"); 11106c3fb27SDimitry Andric return false; 11206c3fb27SDimitry Andric } 11306c3fb27SDimitry Andric 114bdd1243dSDimitry Andric void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const { 115*5f757f3fSDimitry Andric Args.addAllArgs(CmdArgs, 116fe6060f1SDimitry Andric {options::OPT_module_dir, options::OPT_fdebug_module_writer, 117fe6060f1SDimitry Andric options::OPT_fintrinsic_modules_path, options::OPT_pedantic, 118bdd1243dSDimitry Andric options::OPT_std_EQ, options::OPT_W_Joined, 11906c3fb27SDimitry Andric options::OPT_fconvert_EQ, options::OPT_fpass_plugin_EQ, 12006c3fb27SDimitry Andric options::OPT_funderscoring, options::OPT_fno_underscoring}); 12106c3fb27SDimitry Andric 12206c3fb27SDimitry Andric llvm::codegenoptions::DebugInfoKind DebugInfoKind; 12306c3fb27SDimitry Andric if (Args.hasArg(options::OPT_gN_Group)) { 12406c3fb27SDimitry Andric Arg *gNArg = Args.getLastArg(options::OPT_gN_Group); 12506c3fb27SDimitry Andric DebugInfoKind = debugLevelToInfoKind(*gNArg); 12606c3fb27SDimitry Andric } else if (Args.hasArg(options::OPT_g_Flag)) { 12706c3fb27SDimitry Andric DebugInfoKind = llvm::codegenoptions::DebugLineTablesOnly; 12806c3fb27SDimitry Andric } else { 12906c3fb27SDimitry Andric DebugInfoKind = llvm::codegenoptions::NoDebugInfo; 13006c3fb27SDimitry Andric } 13106c3fb27SDimitry Andric addDebugInfoKind(CmdArgs, DebugInfoKind); 13206c3fb27SDimitry Andric } 13306c3fb27SDimitry Andric 13406c3fb27SDimitry Andric void Flang::addCodegenOptions(const ArgList &Args, 13506c3fb27SDimitry Andric ArgStringList &CmdArgs) const { 13606c3fb27SDimitry Andric Arg *stackArrays = 13706c3fb27SDimitry Andric Args.getLastArg(options::OPT_Ofast, options::OPT_fstack_arrays, 13806c3fb27SDimitry Andric options::OPT_fno_stack_arrays); 13906c3fb27SDimitry Andric if (stackArrays && 14006c3fb27SDimitry Andric !stackArrays->getOption().matches(options::OPT_fno_stack_arrays)) 14106c3fb27SDimitry Andric CmdArgs.push_back("-fstack-arrays"); 14206c3fb27SDimitry Andric 14306c3fb27SDimitry Andric if (shouldLoopVersion(Args)) 14406c3fb27SDimitry Andric CmdArgs.push_back("-fversion-loops-for-stride"); 145*5f757f3fSDimitry Andric 146*5f757f3fSDimitry Andric Args.addAllArgs(CmdArgs, {options::OPT_flang_experimental_hlfir, 147*5f757f3fSDimitry Andric options::OPT_flang_deprecated_no_hlfir, 148*5f757f3fSDimitry Andric options::OPT_flang_experimental_polymorphism, 149*5f757f3fSDimitry Andric options::OPT_fno_ppc_native_vec_elem_order, 150*5f757f3fSDimitry Andric options::OPT_fppc_native_vec_elem_order}); 151bdd1243dSDimitry Andric } 152bdd1243dSDimitry Andric 153bdd1243dSDimitry Andric void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const { 154bdd1243dSDimitry Andric // ParsePICArgs parses -fPIC/-fPIE and their variants and returns a tuple of 155bdd1243dSDimitry Andric // (RelocationModel, PICLevel, IsPIE). 156bdd1243dSDimitry Andric llvm::Reloc::Model RelocationModel; 157bdd1243dSDimitry Andric unsigned PICLevel; 158bdd1243dSDimitry Andric bool IsPIE; 159bdd1243dSDimitry Andric std::tie(RelocationModel, PICLevel, IsPIE) = 160bdd1243dSDimitry Andric ParsePICArgs(getToolChain(), Args); 161bdd1243dSDimitry Andric 162bdd1243dSDimitry Andric if (auto *RMName = RelocationModelName(RelocationModel)) { 163bdd1243dSDimitry Andric CmdArgs.push_back("-mrelocation-model"); 164bdd1243dSDimitry Andric CmdArgs.push_back(RMName); 165bdd1243dSDimitry Andric } 166bdd1243dSDimitry Andric if (PICLevel > 0) { 167bdd1243dSDimitry Andric CmdArgs.push_back("-pic-level"); 168bdd1243dSDimitry Andric CmdArgs.push_back(PICLevel == 1 ? "1" : "2"); 169bdd1243dSDimitry Andric if (IsPIE) 170bdd1243dSDimitry Andric CmdArgs.push_back("-pic-is-pie"); 171bdd1243dSDimitry Andric } 172bdd1243dSDimitry Andric } 173bdd1243dSDimitry Andric 174*5f757f3fSDimitry Andric void Flang::AddAArch64TargetArgs(const ArgList &Args, 175*5f757f3fSDimitry Andric ArgStringList &CmdArgs) const { 176*5f757f3fSDimitry Andric // Handle -msve_vector_bits=<bits> 177*5f757f3fSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) { 178*5f757f3fSDimitry Andric StringRef Val = A->getValue(); 179*5f757f3fSDimitry Andric const Driver &D = getToolChain().getDriver(); 180*5f757f3fSDimitry Andric if (Val.equals("128") || Val.equals("256") || Val.equals("512") || 181*5f757f3fSDimitry Andric Val.equals("1024") || Val.equals("2048") || Val.equals("128+") || 182*5f757f3fSDimitry Andric Val.equals("256+") || Val.equals("512+") || Val.equals("1024+") || 183*5f757f3fSDimitry Andric Val.equals("2048+")) { 184*5f757f3fSDimitry Andric unsigned Bits = 0; 185*5f757f3fSDimitry Andric if (Val.ends_with("+")) 186*5f757f3fSDimitry Andric Val = Val.substr(0, Val.size() - 1); 187*5f757f3fSDimitry Andric else { 188*5f757f3fSDimitry Andric [[maybe_unused]] bool Invalid = Val.getAsInteger(10, Bits); 189*5f757f3fSDimitry Andric assert(!Invalid && "Failed to parse value"); 190*5f757f3fSDimitry Andric CmdArgs.push_back( 191*5f757f3fSDimitry Andric Args.MakeArgString("-mvscale-max=" + llvm::Twine(Bits / 128))); 192*5f757f3fSDimitry Andric } 193*5f757f3fSDimitry Andric 194*5f757f3fSDimitry Andric [[maybe_unused]] bool Invalid = Val.getAsInteger(10, Bits); 195*5f757f3fSDimitry Andric assert(!Invalid && "Failed to parse value"); 196*5f757f3fSDimitry Andric CmdArgs.push_back( 197*5f757f3fSDimitry Andric Args.MakeArgString("-mvscale-min=" + llvm::Twine(Bits / 128))); 198*5f757f3fSDimitry Andric // Silently drop requests for vector-length agnostic code as it's implied. 199*5f757f3fSDimitry Andric } else if (!Val.equals("scalable")) 200*5f757f3fSDimitry Andric // Handle the unsupported values passed to msve-vector-bits. 201*5f757f3fSDimitry Andric D.Diag(diag::err_drv_unsupported_option_argument) 202*5f757f3fSDimitry Andric << A->getSpelling() << Val; 203*5f757f3fSDimitry Andric } 204*5f757f3fSDimitry Andric } 205*5f757f3fSDimitry Andric 206*5f757f3fSDimitry Andric static void addVSDefines(const ToolChain &TC, const ArgList &Args, 207*5f757f3fSDimitry Andric ArgStringList &CmdArgs) { 208*5f757f3fSDimitry Andric 209*5f757f3fSDimitry Andric unsigned ver = 0; 210*5f757f3fSDimitry Andric const VersionTuple vt = TC.computeMSVCVersion(nullptr, Args); 211*5f757f3fSDimitry Andric ver = vt.getMajor() * 10000000 + vt.getMinor().value_or(0) * 100000 + 212*5f757f3fSDimitry Andric vt.getSubminor().value_or(0); 213*5f757f3fSDimitry Andric CmdArgs.push_back(Args.MakeArgString("-D_MSC_VER=" + Twine(ver / 100000))); 214*5f757f3fSDimitry Andric CmdArgs.push_back(Args.MakeArgString("-D_MSC_FULL_VER=" + Twine(ver))); 215*5f757f3fSDimitry Andric CmdArgs.push_back(Args.MakeArgString("-D_WIN32")); 216*5f757f3fSDimitry Andric 217*5f757f3fSDimitry Andric llvm::Triple triple = TC.getTriple(); 218*5f757f3fSDimitry Andric if (triple.isAArch64()) { 219*5f757f3fSDimitry Andric CmdArgs.push_back("-D_M_ARM64=1"); 220*5f757f3fSDimitry Andric } else if (triple.isX86() && triple.isArch32Bit()) { 221*5f757f3fSDimitry Andric CmdArgs.push_back("-D_M_IX86=600"); 222*5f757f3fSDimitry Andric } else if (triple.isX86() && triple.isArch64Bit()) { 223*5f757f3fSDimitry Andric CmdArgs.push_back("-D_M_X64=100"); 224*5f757f3fSDimitry Andric } else { 225*5f757f3fSDimitry Andric llvm_unreachable( 226*5f757f3fSDimitry Andric "Flang on Windows only supports X86_32, X86_64 and AArch64"); 227*5f757f3fSDimitry Andric } 228*5f757f3fSDimitry Andric } 229*5f757f3fSDimitry Andric 230*5f757f3fSDimitry Andric static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args, 231*5f757f3fSDimitry Andric ArgStringList &CmdArgs) { 232*5f757f3fSDimitry Andric assert(TC.getTriple().isKnownWindowsMSVCEnvironment() && 233*5f757f3fSDimitry Andric "can only add VS runtime library on Windows!"); 234*5f757f3fSDimitry Andric // if -fno-fortran-main has been passed, skip linking Fortran_main.a 235*5f757f3fSDimitry Andric bool LinkFortranMain = !Args.hasArg(options::OPT_no_fortran_main); 236*5f757f3fSDimitry Andric if (TC.getTriple().isKnownWindowsMSVCEnvironment()) { 237*5f757f3fSDimitry Andric CmdArgs.push_back(Args.MakeArgString( 238*5f757f3fSDimitry Andric "--dependent-lib=" + TC.getCompilerRTBasename(Args, "builtins"))); 239*5f757f3fSDimitry Andric } 240*5f757f3fSDimitry Andric unsigned RTOptionID = options::OPT__SLASH_MT; 241*5f757f3fSDimitry Andric if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) { 242*5f757f3fSDimitry Andric RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue()) 243*5f757f3fSDimitry Andric .Case("static", options::OPT__SLASH_MT) 244*5f757f3fSDimitry Andric .Case("static_dbg", options::OPT__SLASH_MTd) 245*5f757f3fSDimitry Andric .Case("dll", options::OPT__SLASH_MD) 246*5f757f3fSDimitry Andric .Case("dll_dbg", options::OPT__SLASH_MDd) 247*5f757f3fSDimitry Andric .Default(options::OPT__SLASH_MT); 248*5f757f3fSDimitry Andric } 249*5f757f3fSDimitry Andric switch (RTOptionID) { 250*5f757f3fSDimitry Andric case options::OPT__SLASH_MT: 251*5f757f3fSDimitry Andric CmdArgs.push_back("-D_MT"); 252*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=libcmt"); 253*5f757f3fSDimitry Andric if (LinkFortranMain) 254*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=Fortran_main.static.lib"); 255*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=FortranRuntime.static.lib"); 256*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=FortranDecimal.static.lib"); 257*5f757f3fSDimitry Andric break; 258*5f757f3fSDimitry Andric case options::OPT__SLASH_MTd: 259*5f757f3fSDimitry Andric CmdArgs.push_back("-D_MT"); 260*5f757f3fSDimitry Andric CmdArgs.push_back("-D_DEBUG"); 261*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=libcmtd"); 262*5f757f3fSDimitry Andric if (LinkFortranMain) 263*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=Fortran_main.static_dbg.lib"); 264*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=FortranRuntime.static_dbg.lib"); 265*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=FortranDecimal.static_dbg.lib"); 266*5f757f3fSDimitry Andric break; 267*5f757f3fSDimitry Andric case options::OPT__SLASH_MD: 268*5f757f3fSDimitry Andric CmdArgs.push_back("-D_MT"); 269*5f757f3fSDimitry Andric CmdArgs.push_back("-D_DLL"); 270*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=msvcrt"); 271*5f757f3fSDimitry Andric if (LinkFortranMain) 272*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic.lib"); 273*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic.lib"); 274*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic.lib"); 275*5f757f3fSDimitry Andric break; 276*5f757f3fSDimitry Andric case options::OPT__SLASH_MDd: 277*5f757f3fSDimitry Andric CmdArgs.push_back("-D_MT"); 278*5f757f3fSDimitry Andric CmdArgs.push_back("-D_DEBUG"); 279*5f757f3fSDimitry Andric CmdArgs.push_back("-D_DLL"); 280*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=msvcrtd"); 281*5f757f3fSDimitry Andric if (LinkFortranMain) 282*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic_dbg.lib"); 283*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic_dbg.lib"); 284*5f757f3fSDimitry Andric CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic_dbg.lib"); 285*5f757f3fSDimitry Andric break; 286*5f757f3fSDimitry Andric } 287*5f757f3fSDimitry Andric } 288*5f757f3fSDimitry Andric 289*5f757f3fSDimitry Andric void Flang::AddAMDGPUTargetArgs(const ArgList &Args, 290*5f757f3fSDimitry Andric ArgStringList &CmdArgs) const { 291*5f757f3fSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mcode_object_version_EQ)) { 292*5f757f3fSDimitry Andric StringRef Val = A->getValue(); 293*5f757f3fSDimitry Andric CmdArgs.push_back(Args.MakeArgString("-mcode-object-version=" + Val)); 294*5f757f3fSDimitry Andric } 295*5f757f3fSDimitry Andric } 296*5f757f3fSDimitry Andric 297bdd1243dSDimitry Andric void Flang::addTargetOptions(const ArgList &Args, 298bdd1243dSDimitry Andric ArgStringList &CmdArgs) const { 299bdd1243dSDimitry Andric const ToolChain &TC = getToolChain(); 300bdd1243dSDimitry Andric const llvm::Triple &Triple = TC.getEffectiveTriple(); 301bdd1243dSDimitry Andric const Driver &D = TC.getDriver(); 302bdd1243dSDimitry Andric 303bdd1243dSDimitry Andric std::string CPU = getCPUName(D, Args, Triple); 304bdd1243dSDimitry Andric if (!CPU.empty()) { 305bdd1243dSDimitry Andric CmdArgs.push_back("-target-cpu"); 306bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(CPU)); 307bdd1243dSDimitry Andric } 308bdd1243dSDimitry Andric 309bdd1243dSDimitry Andric // Add the target features. 310bdd1243dSDimitry Andric switch (TC.getArch()) { 311bdd1243dSDimitry Andric default: 312bdd1243dSDimitry Andric break; 313*5f757f3fSDimitry Andric case llvm::Triple::aarch64: 314*5f757f3fSDimitry Andric getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); 315*5f757f3fSDimitry Andric AddAArch64TargetArgs(Args, CmdArgs); 316*5f757f3fSDimitry Andric break; 317*5f757f3fSDimitry Andric 31806c3fb27SDimitry Andric case llvm::Triple::r600: 31906c3fb27SDimitry Andric case llvm::Triple::amdgcn: 320*5f757f3fSDimitry Andric getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); 321*5f757f3fSDimitry Andric AddAMDGPUTargetArgs(Args, CmdArgs); 322*5f757f3fSDimitry Andric break; 32306c3fb27SDimitry Andric case llvm::Triple::riscv64: 324bdd1243dSDimitry Andric case llvm::Triple::x86_64: 325bdd1243dSDimitry Andric getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); 326bdd1243dSDimitry Andric break; 327bdd1243dSDimitry Andric } 328bdd1243dSDimitry Andric 329*5f757f3fSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_fveclib)) { 330*5f757f3fSDimitry Andric StringRef Name = A->getValue(); 331*5f757f3fSDimitry Andric if (Name == "SVML") { 332*5f757f3fSDimitry Andric if (Triple.getArch() != llvm::Triple::x86 && 333*5f757f3fSDimitry Andric Triple.getArch() != llvm::Triple::x86_64) 334*5f757f3fSDimitry Andric D.Diag(diag::err_drv_unsupported_opt_for_target) 335*5f757f3fSDimitry Andric << Name << Triple.getArchName(); 336*5f757f3fSDimitry Andric } else if (Name == "LIBMVEC-X86") { 337*5f757f3fSDimitry Andric if (Triple.getArch() != llvm::Triple::x86 && 338*5f757f3fSDimitry Andric Triple.getArch() != llvm::Triple::x86_64) 339*5f757f3fSDimitry Andric D.Diag(diag::err_drv_unsupported_opt_for_target) 340*5f757f3fSDimitry Andric << Name << Triple.getArchName(); 341*5f757f3fSDimitry Andric } else if (Name == "SLEEF" || Name == "ArmPL") { 342*5f757f3fSDimitry Andric if (Triple.getArch() != llvm::Triple::aarch64 && 343*5f757f3fSDimitry Andric Triple.getArch() != llvm::Triple::aarch64_be) 344*5f757f3fSDimitry Andric D.Diag(diag::err_drv_unsupported_opt_for_target) 345*5f757f3fSDimitry Andric << Name << Triple.getArchName(); 346*5f757f3fSDimitry Andric } 347*5f757f3fSDimitry Andric 348*5f757f3fSDimitry Andric if (Triple.isOSDarwin()) { 349*5f757f3fSDimitry Andric // flang doesn't currently suport nostdlib, nodefaultlibs. Adding these 350*5f757f3fSDimitry Andric // here incase they are added someday 351*5f757f3fSDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 352*5f757f3fSDimitry Andric if (A->getValue() == StringRef{"Accelerate"}) { 353*5f757f3fSDimitry Andric CmdArgs.push_back("-framework"); 354*5f757f3fSDimitry Andric CmdArgs.push_back("Accelerate"); 355*5f757f3fSDimitry Andric A->render(Args, CmdArgs); 356*5f757f3fSDimitry Andric } 357*5f757f3fSDimitry Andric } 358*5f757f3fSDimitry Andric } else { 359*5f757f3fSDimitry Andric A->render(Args, CmdArgs); 360*5f757f3fSDimitry Andric } 361*5f757f3fSDimitry Andric } 362*5f757f3fSDimitry Andric 363*5f757f3fSDimitry Andric if (Triple.isKnownWindowsMSVCEnvironment()) { 364*5f757f3fSDimitry Andric processVSRuntimeLibrary(TC, Args, CmdArgs); 365*5f757f3fSDimitry Andric addVSDefines(TC, Args, CmdArgs); 366*5f757f3fSDimitry Andric } 367*5f757f3fSDimitry Andric 368bdd1243dSDimitry Andric // TODO: Add target specific flags, ABI, mtune option etc. 369bdd1243dSDimitry Andric } 370bdd1243dSDimitry Andric 37106c3fb27SDimitry Andric void Flang::addOffloadOptions(Compilation &C, const InputInfoList &Inputs, 37206c3fb27SDimitry Andric const JobAction &JA, const ArgList &Args, 37306c3fb27SDimitry Andric ArgStringList &CmdArgs) const { 37406c3fb27SDimitry Andric bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP); 37506c3fb27SDimitry Andric bool IsHostOffloadingAction = JA.isHostOffloading(Action::OFK_OpenMP) || 37606c3fb27SDimitry Andric JA.isHostOffloading(C.getActiveOffloadKinds()); 37706c3fb27SDimitry Andric 37806c3fb27SDimitry Andric // Skips the primary input file, which is the input file that the compilation 37906c3fb27SDimitry Andric // proccess will be executed upon (e.g. the host bitcode file) and 38006c3fb27SDimitry Andric // adds other secondary input (e.g. device bitcode files for embedding to the 38106c3fb27SDimitry Andric // -fembed-offload-object argument or the host IR file for proccessing 38206c3fb27SDimitry Andric // during device compilation to the fopenmp-host-ir-file-path argument via 38306c3fb27SDimitry Andric // OpenMPDeviceInput). This is condensed logic from the ConstructJob 38406c3fb27SDimitry Andric // function inside of the Clang driver for pushing on further input arguments 38506c3fb27SDimitry Andric // needed for offloading during various phases of compilation. 38606c3fb27SDimitry Andric for (size_t i = 1; i < Inputs.size(); ++i) { 38706c3fb27SDimitry Andric if (Inputs[i].getType() == types::TY_Nothing) { 38806c3fb27SDimitry Andric // contains nothing, so it's skippable 38906c3fb27SDimitry Andric } else if (IsHostOffloadingAction) { 39006c3fb27SDimitry Andric CmdArgs.push_back( 39106c3fb27SDimitry Andric Args.MakeArgString("-fembed-offload-object=" + 39206c3fb27SDimitry Andric getToolChain().getInputFilename(Inputs[i]))); 39306c3fb27SDimitry Andric } else if (IsOpenMPDevice) { 39406c3fb27SDimitry Andric if (Inputs[i].getFilename()) { 39506c3fb27SDimitry Andric CmdArgs.push_back("-fopenmp-host-ir-file-path"); 39606c3fb27SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Inputs[i].getFilename())); 39706c3fb27SDimitry Andric } else { 39806c3fb27SDimitry Andric llvm_unreachable("missing openmp host-ir file for device offloading"); 39906c3fb27SDimitry Andric } 40006c3fb27SDimitry Andric } else { 40106c3fb27SDimitry Andric llvm_unreachable( 40206c3fb27SDimitry Andric "unexpectedly given multiple inputs or given unknown input"); 40306c3fb27SDimitry Andric } 40406c3fb27SDimitry Andric } 40506c3fb27SDimitry Andric 40606c3fb27SDimitry Andric if (IsOpenMPDevice) { 40706c3fb27SDimitry Andric // -fopenmp-is-target-device is passed along to tell the frontend that it is 40806c3fb27SDimitry Andric // generating code for a device, so that only the relevant code is emitted. 40906c3fb27SDimitry Andric CmdArgs.push_back("-fopenmp-is-target-device"); 41006c3fb27SDimitry Andric 41106c3fb27SDimitry Andric // When in OpenMP offloading mode, enable debugging on the device. 41206c3fb27SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_target_debug_EQ); 41306c3fb27SDimitry Andric if (Args.hasFlag(options::OPT_fopenmp_target_debug, 41406c3fb27SDimitry Andric options::OPT_fno_openmp_target_debug, /*Default=*/false)) 41506c3fb27SDimitry Andric CmdArgs.push_back("-fopenmp-target-debug"); 41606c3fb27SDimitry Andric 41706c3fb27SDimitry Andric // When in OpenMP offloading mode, forward assumptions information about 41806c3fb27SDimitry Andric // thread and team counts in the device. 41906c3fb27SDimitry Andric if (Args.hasFlag(options::OPT_fopenmp_assume_teams_oversubscription, 42006c3fb27SDimitry Andric options::OPT_fno_openmp_assume_teams_oversubscription, 42106c3fb27SDimitry Andric /*Default=*/false)) 42206c3fb27SDimitry Andric CmdArgs.push_back("-fopenmp-assume-teams-oversubscription"); 42306c3fb27SDimitry Andric if (Args.hasFlag(options::OPT_fopenmp_assume_threads_oversubscription, 42406c3fb27SDimitry Andric options::OPT_fno_openmp_assume_threads_oversubscription, 42506c3fb27SDimitry Andric /*Default=*/false)) 42606c3fb27SDimitry Andric CmdArgs.push_back("-fopenmp-assume-threads-oversubscription"); 42706c3fb27SDimitry Andric if (Args.hasArg(options::OPT_fopenmp_assume_no_thread_state)) 42806c3fb27SDimitry Andric CmdArgs.push_back("-fopenmp-assume-no-thread-state"); 42906c3fb27SDimitry Andric if (Args.hasArg(options::OPT_fopenmp_assume_no_nested_parallelism)) 43006c3fb27SDimitry Andric CmdArgs.push_back("-fopenmp-assume-no-nested-parallelism"); 43106c3fb27SDimitry Andric } 43206c3fb27SDimitry Andric } 43306c3fb27SDimitry Andric 434bdd1243dSDimitry Andric static void addFloatingPointOptions(const Driver &D, const ArgList &Args, 435bdd1243dSDimitry Andric ArgStringList &CmdArgs) { 436bdd1243dSDimitry Andric StringRef FPContract; 437bdd1243dSDimitry Andric bool HonorINFs = true; 438bdd1243dSDimitry Andric bool HonorNaNs = true; 439bdd1243dSDimitry Andric bool ApproxFunc = false; 440bdd1243dSDimitry Andric bool SignedZeros = true; 441bdd1243dSDimitry Andric bool AssociativeMath = false; 442bdd1243dSDimitry Andric bool ReciprocalMath = false; 443bdd1243dSDimitry Andric 444bdd1243dSDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_ffp_contract)) { 445bdd1243dSDimitry Andric const StringRef Val = A->getValue(); 446bdd1243dSDimitry Andric if (Val == "fast" || Val == "off") { 447bdd1243dSDimitry Andric FPContract = Val; 448bdd1243dSDimitry Andric } else if (Val == "on") { 449bdd1243dSDimitry Andric // Warn instead of error because users might have makefiles written for 450bdd1243dSDimitry Andric // gfortran (which accepts -ffp-contract=on) 451bdd1243dSDimitry Andric D.Diag(diag::warn_drv_unsupported_option_for_flang) 452bdd1243dSDimitry Andric << Val << A->getOption().getName() << "off"; 453bdd1243dSDimitry Andric FPContract = "off"; 454bdd1243dSDimitry Andric } else 455bdd1243dSDimitry Andric // Clang's "fast-honor-pragmas" option is not supported because it is 456bdd1243dSDimitry Andric // non-standard 457bdd1243dSDimitry Andric D.Diag(diag::err_drv_unsupported_option_argument) 458bdd1243dSDimitry Andric << A->getSpelling() << Val; 459bdd1243dSDimitry Andric } 460bdd1243dSDimitry Andric 461bdd1243dSDimitry Andric for (const Arg *A : Args) { 462bdd1243dSDimitry Andric auto optId = A->getOption().getID(); 463bdd1243dSDimitry Andric switch (optId) { 464bdd1243dSDimitry Andric // if this isn't an FP option, skip the claim below 465bdd1243dSDimitry Andric default: 466bdd1243dSDimitry Andric continue; 467bdd1243dSDimitry Andric 468bdd1243dSDimitry Andric case options::OPT_fhonor_infinities: 469bdd1243dSDimitry Andric HonorINFs = true; 470bdd1243dSDimitry Andric break; 471bdd1243dSDimitry Andric case options::OPT_fno_honor_infinities: 472bdd1243dSDimitry Andric HonorINFs = false; 473bdd1243dSDimitry Andric break; 474bdd1243dSDimitry Andric case options::OPT_fhonor_nans: 475bdd1243dSDimitry Andric HonorNaNs = true; 476bdd1243dSDimitry Andric break; 477bdd1243dSDimitry Andric case options::OPT_fno_honor_nans: 478bdd1243dSDimitry Andric HonorNaNs = false; 479bdd1243dSDimitry Andric break; 480bdd1243dSDimitry Andric case options::OPT_fapprox_func: 481bdd1243dSDimitry Andric ApproxFunc = true; 482bdd1243dSDimitry Andric break; 483bdd1243dSDimitry Andric case options::OPT_fno_approx_func: 484bdd1243dSDimitry Andric ApproxFunc = false; 485bdd1243dSDimitry Andric break; 486bdd1243dSDimitry Andric case options::OPT_fsigned_zeros: 487bdd1243dSDimitry Andric SignedZeros = true; 488bdd1243dSDimitry Andric break; 489bdd1243dSDimitry Andric case options::OPT_fno_signed_zeros: 490bdd1243dSDimitry Andric SignedZeros = false; 491bdd1243dSDimitry Andric break; 492bdd1243dSDimitry Andric case options::OPT_fassociative_math: 493bdd1243dSDimitry Andric AssociativeMath = true; 494bdd1243dSDimitry Andric break; 495bdd1243dSDimitry Andric case options::OPT_fno_associative_math: 496bdd1243dSDimitry Andric AssociativeMath = false; 497bdd1243dSDimitry Andric break; 498bdd1243dSDimitry Andric case options::OPT_freciprocal_math: 499bdd1243dSDimitry Andric ReciprocalMath = true; 500bdd1243dSDimitry Andric break; 501bdd1243dSDimitry Andric case options::OPT_fno_reciprocal_math: 502bdd1243dSDimitry Andric ReciprocalMath = false; 503bdd1243dSDimitry Andric break; 504bdd1243dSDimitry Andric case options::OPT_Ofast: 505bdd1243dSDimitry Andric [[fallthrough]]; 506bdd1243dSDimitry Andric case options::OPT_ffast_math: 507bdd1243dSDimitry Andric HonorINFs = false; 508bdd1243dSDimitry Andric HonorNaNs = false; 509bdd1243dSDimitry Andric AssociativeMath = true; 510bdd1243dSDimitry Andric ReciprocalMath = true; 511bdd1243dSDimitry Andric ApproxFunc = true; 512bdd1243dSDimitry Andric SignedZeros = false; 513bdd1243dSDimitry Andric FPContract = "fast"; 514bdd1243dSDimitry Andric break; 515bdd1243dSDimitry Andric case options::OPT_fno_fast_math: 516bdd1243dSDimitry Andric HonorINFs = true; 517bdd1243dSDimitry Andric HonorNaNs = true; 518bdd1243dSDimitry Andric AssociativeMath = false; 519bdd1243dSDimitry Andric ReciprocalMath = false; 520bdd1243dSDimitry Andric ApproxFunc = false; 521bdd1243dSDimitry Andric SignedZeros = true; 522bdd1243dSDimitry Andric // -fno-fast-math should undo -ffast-math so I return FPContract to the 523bdd1243dSDimitry Andric // default. It is important to check it is "fast" (the default) so that 524bdd1243dSDimitry Andric // --ffp-contract=off -fno-fast-math --> -ffp-contract=off 525bdd1243dSDimitry Andric if (FPContract == "fast") 526bdd1243dSDimitry Andric FPContract = ""; 527bdd1243dSDimitry Andric break; 528bdd1243dSDimitry Andric } 529bdd1243dSDimitry Andric 530bdd1243dSDimitry Andric // If we handled this option claim it 531bdd1243dSDimitry Andric A->claim(); 532bdd1243dSDimitry Andric } 533bdd1243dSDimitry Andric 534bdd1243dSDimitry Andric if (!HonorINFs && !HonorNaNs && AssociativeMath && ReciprocalMath && 535bdd1243dSDimitry Andric ApproxFunc && !SignedZeros && 536bdd1243dSDimitry Andric (FPContract == "fast" || FPContract == "")) { 537bdd1243dSDimitry Andric CmdArgs.push_back("-ffast-math"); 538bdd1243dSDimitry Andric return; 539bdd1243dSDimitry Andric } 540bdd1243dSDimitry Andric 541bdd1243dSDimitry Andric if (!FPContract.empty()) 542bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract)); 543bdd1243dSDimitry Andric 544bdd1243dSDimitry Andric if (!HonorINFs) 545bdd1243dSDimitry Andric CmdArgs.push_back("-menable-no-infs"); 546bdd1243dSDimitry Andric 547bdd1243dSDimitry Andric if (!HonorNaNs) 548bdd1243dSDimitry Andric CmdArgs.push_back("-menable-no-nans"); 549bdd1243dSDimitry Andric 550bdd1243dSDimitry Andric if (ApproxFunc) 551bdd1243dSDimitry Andric CmdArgs.push_back("-fapprox-func"); 552bdd1243dSDimitry Andric 553bdd1243dSDimitry Andric if (!SignedZeros) 554bdd1243dSDimitry Andric CmdArgs.push_back("-fno-signed-zeros"); 555bdd1243dSDimitry Andric 556bdd1243dSDimitry Andric if (AssociativeMath && !SignedZeros) 557bdd1243dSDimitry Andric CmdArgs.push_back("-mreassociate"); 558bdd1243dSDimitry Andric 559bdd1243dSDimitry Andric if (ReciprocalMath) 560bdd1243dSDimitry Andric CmdArgs.push_back("-freciprocal-math"); 561e8d8bef9SDimitry Andric } 562e8d8bef9SDimitry Andric 563*5f757f3fSDimitry Andric static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs, 564*5f757f3fSDimitry Andric const InputInfo &Input) { 565*5f757f3fSDimitry Andric StringRef Format = "yaml"; 566*5f757f3fSDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ)) 567*5f757f3fSDimitry Andric Format = A->getValue(); 568*5f757f3fSDimitry Andric 569*5f757f3fSDimitry Andric CmdArgs.push_back("-opt-record-file"); 570*5f757f3fSDimitry Andric 571*5f757f3fSDimitry Andric const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ); 572*5f757f3fSDimitry Andric if (A) { 573*5f757f3fSDimitry Andric CmdArgs.push_back(A->getValue()); 574*5f757f3fSDimitry Andric } else { 575*5f757f3fSDimitry Andric SmallString<128> F; 576*5f757f3fSDimitry Andric 577*5f757f3fSDimitry Andric if (Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) { 578*5f757f3fSDimitry Andric if (Arg *FinalOutput = Args.getLastArg(options::OPT_o)) 579*5f757f3fSDimitry Andric F = FinalOutput->getValue(); 580*5f757f3fSDimitry Andric } 581*5f757f3fSDimitry Andric 582*5f757f3fSDimitry Andric if (F.empty()) { 583*5f757f3fSDimitry Andric // Use the input filename. 584*5f757f3fSDimitry Andric F = llvm::sys::path::stem(Input.getBaseInput()); 585*5f757f3fSDimitry Andric } 586*5f757f3fSDimitry Andric 587*5f757f3fSDimitry Andric SmallString<32> Extension; 588*5f757f3fSDimitry Andric Extension += "opt."; 589*5f757f3fSDimitry Andric Extension += Format; 590*5f757f3fSDimitry Andric 591*5f757f3fSDimitry Andric llvm::sys::path::replace_extension(F, Extension); 592*5f757f3fSDimitry Andric CmdArgs.push_back(Args.MakeArgString(F)); 593*5f757f3fSDimitry Andric } 594*5f757f3fSDimitry Andric 595*5f757f3fSDimitry Andric if (const Arg *A = 596*5f757f3fSDimitry Andric Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) { 597*5f757f3fSDimitry Andric CmdArgs.push_back("-opt-record-passes"); 598*5f757f3fSDimitry Andric CmdArgs.push_back(A->getValue()); 599*5f757f3fSDimitry Andric } 600*5f757f3fSDimitry Andric 601*5f757f3fSDimitry Andric if (!Format.empty()) { 602*5f757f3fSDimitry Andric CmdArgs.push_back("-opt-record-format"); 603*5f757f3fSDimitry Andric CmdArgs.push_back(Format.data()); 604*5f757f3fSDimitry Andric } 605*5f757f3fSDimitry Andric } 606*5f757f3fSDimitry Andric 607480093f4SDimitry Andric void Flang::ConstructJob(Compilation &C, const JobAction &JA, 608480093f4SDimitry Andric const InputInfo &Output, const InputInfoList &Inputs, 609480093f4SDimitry Andric const ArgList &Args, const char *LinkingOutput) const { 610480093f4SDimitry Andric const auto &TC = getToolChain(); 61181ad6265SDimitry Andric const llvm::Triple &Triple = TC.getEffectiveTriple(); 61281ad6265SDimitry Andric const std::string &TripleStr = Triple.getTriple(); 613480093f4SDimitry Andric 61481ad6265SDimitry Andric const Driver &D = TC.getDriver(); 615480093f4SDimitry Andric ArgStringList CmdArgs; 61606c3fb27SDimitry Andric DiagnosticsEngine &Diags = D.getDiags(); 617480093f4SDimitry Andric 618e8d8bef9SDimitry Andric // Invoke ourselves in -fc1 mode. 619480093f4SDimitry Andric CmdArgs.push_back("-fc1"); 620480093f4SDimitry Andric 621e8d8bef9SDimitry Andric // Add the "effective" target triple. 62281ad6265SDimitry Andric CmdArgs.push_back("-triple"); 62381ad6265SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TripleStr)); 624480093f4SDimitry Andric 625480093f4SDimitry Andric if (isa<PreprocessJobAction>(JA)) { 626480093f4SDimitry Andric CmdArgs.push_back("-E"); 627480093f4SDimitry Andric } else if (isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) { 628480093f4SDimitry Andric if (JA.getType() == types::TY_Nothing) { 629480093f4SDimitry Andric CmdArgs.push_back("-fsyntax-only"); 630480093f4SDimitry Andric } else if (JA.getType() == types::TY_AST) { 631480093f4SDimitry Andric CmdArgs.push_back("-emit-ast"); 632480093f4SDimitry Andric } else if (JA.getType() == types::TY_LLVM_IR || 633480093f4SDimitry Andric JA.getType() == types::TY_LTO_IR) { 634480093f4SDimitry Andric CmdArgs.push_back("-emit-llvm"); 635480093f4SDimitry Andric } else if (JA.getType() == types::TY_LLVM_BC || 636480093f4SDimitry Andric JA.getType() == types::TY_LTO_BC) { 637480093f4SDimitry Andric CmdArgs.push_back("-emit-llvm-bc"); 638480093f4SDimitry Andric } else if (JA.getType() == types::TY_PP_Asm) { 639480093f4SDimitry Andric CmdArgs.push_back("-S"); 640480093f4SDimitry Andric } else { 641480093f4SDimitry Andric assert(false && "Unexpected output type!"); 642480093f4SDimitry Andric } 643480093f4SDimitry Andric } else if (isa<AssembleJobAction>(JA)) { 644480093f4SDimitry Andric CmdArgs.push_back("-emit-obj"); 645480093f4SDimitry Andric } else { 646480093f4SDimitry Andric assert(false && "Unexpected action class for Flang tool."); 647480093f4SDimitry Andric } 648480093f4SDimitry Andric 649e8d8bef9SDimitry Andric const InputInfo &Input = Inputs[0]; 650e8d8bef9SDimitry Andric types::ID InputType = Input.getType(); 651e8d8bef9SDimitry Andric 652e8d8bef9SDimitry Andric // Add preprocessing options like -I, -D, etc. if we are using the 653e8d8bef9SDimitry Andric // preprocessor (i.e. skip when dealing with e.g. binary files). 654e8d8bef9SDimitry Andric if (types::getPreprocessedType(InputType) != types::TY_INVALID) 655bdd1243dSDimitry Andric addPreprocessingOptions(Args, CmdArgs); 656e8d8bef9SDimitry Andric 657bdd1243dSDimitry Andric addFortranDialectOptions(Args, CmdArgs); 658fe6060f1SDimitry Andric 65981ad6265SDimitry Andric // Color diagnostics are parsed by the driver directly from argv and later 66081ad6265SDimitry Andric // re-parsed to construct this job; claim any possible color diagnostic here 66181ad6265SDimitry Andric // to avoid warn_drv_unused_argument. 66281ad6265SDimitry Andric Args.getLastArg(options::OPT_fcolor_diagnostics, 66381ad6265SDimitry Andric options::OPT_fno_color_diagnostics); 66406c3fb27SDimitry Andric if (Diags.getDiagnosticOptions().ShowColors) 66581ad6265SDimitry Andric CmdArgs.push_back("-fcolor-diagnostics"); 66681ad6265SDimitry Andric 66706c3fb27SDimitry Andric // LTO mode is parsed by the Clang driver library. 66806c3fb27SDimitry Andric LTOKind LTOMode = D.getLTOMode(/* IsOffload */ false); 66906c3fb27SDimitry Andric assert(LTOMode != LTOK_Unknown && "Unknown LTO mode."); 67006c3fb27SDimitry Andric if (LTOMode == LTOK_Full) 67106c3fb27SDimitry Andric CmdArgs.push_back("-flto=full"); 67206c3fb27SDimitry Andric else if (LTOMode == LTOK_Thin) { 67306c3fb27SDimitry Andric Diags.Report( 67406c3fb27SDimitry Andric Diags.getCustomDiagID(DiagnosticsEngine::Warning, 67506c3fb27SDimitry Andric "the option '-flto=thin' is a work in progress")); 67606c3fb27SDimitry Andric CmdArgs.push_back("-flto=thin"); 67706c3fb27SDimitry Andric } 67806c3fb27SDimitry Andric 679bdd1243dSDimitry Andric // -fPIC and related options. 680bdd1243dSDimitry Andric addPicOptions(Args, CmdArgs); 681bdd1243dSDimitry Andric 682bdd1243dSDimitry Andric // Floating point related options 683bdd1243dSDimitry Andric addFloatingPointOptions(D, Args, CmdArgs); 684bdd1243dSDimitry Andric 685bdd1243dSDimitry Andric // Add target args, features, etc. 686bdd1243dSDimitry Andric addTargetOptions(Args, CmdArgs); 687bdd1243dSDimitry Andric 68806c3fb27SDimitry Andric // Add Codegen options 68906c3fb27SDimitry Andric addCodegenOptions(Args, CmdArgs); 69006c3fb27SDimitry Andric 691*5f757f3fSDimitry Andric // Add R Group options 692*5f757f3fSDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_R_Group); 693*5f757f3fSDimitry Andric 694*5f757f3fSDimitry Andric // Remarks can be enabled with any of the `-f.*optimization-record.*` flags. 695*5f757f3fSDimitry Andric if (willEmitRemarks(Args)) 696*5f757f3fSDimitry Andric renderRemarksOptions(Args, CmdArgs, Input); 697*5f757f3fSDimitry Andric 698fe6060f1SDimitry Andric // Add other compile options 699bdd1243dSDimitry Andric addOtherOptions(Args, CmdArgs); 700fe6060f1SDimitry Andric 70106c3fb27SDimitry Andric // Offloading related options 70206c3fb27SDimitry Andric addOffloadOptions(C, Inputs, JA, Args, CmdArgs); 70306c3fb27SDimitry Andric 704fe6060f1SDimitry Andric // Forward -Xflang arguments to -fc1 705fe6060f1SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT_Xflang); 706fe6060f1SDimitry Andric 707*5f757f3fSDimitry Andric CodeGenOptions::FramePointerKind FPKeepKind = 708*5f757f3fSDimitry Andric getFramePointerKind(Args, Triple); 709*5f757f3fSDimitry Andric 710*5f757f3fSDimitry Andric const char *FPKeepKindStr = nullptr; 711*5f757f3fSDimitry Andric switch (FPKeepKind) { 712*5f757f3fSDimitry Andric case CodeGenOptions::FramePointerKind::None: 713*5f757f3fSDimitry Andric FPKeepKindStr = "-mframe-pointer=none"; 714*5f757f3fSDimitry Andric break; 715*5f757f3fSDimitry Andric case CodeGenOptions::FramePointerKind::NonLeaf: 716*5f757f3fSDimitry Andric FPKeepKindStr = "-mframe-pointer=non-leaf"; 717*5f757f3fSDimitry Andric break; 718*5f757f3fSDimitry Andric case CodeGenOptions::FramePointerKind::All: 719*5f757f3fSDimitry Andric FPKeepKindStr = "-mframe-pointer=all"; 720*5f757f3fSDimitry Andric break; 721*5f757f3fSDimitry Andric } 722*5f757f3fSDimitry Andric assert(FPKeepKindStr && "unknown FramePointerKind"); 723*5f757f3fSDimitry Andric CmdArgs.push_back(FPKeepKindStr); 724*5f757f3fSDimitry Andric 72581ad6265SDimitry Andric // Forward -mllvm options to the LLVM option parser. In practice, this means 72681ad6265SDimitry Andric // forwarding to `-fc1` as that's where the LLVM parser is run. 72781ad6265SDimitry Andric for (const Arg *A : Args.filtered(options::OPT_mllvm)) { 72881ad6265SDimitry Andric A->claim(); 72981ad6265SDimitry Andric A->render(Args, CmdArgs); 73081ad6265SDimitry Andric } 73181ad6265SDimitry Andric 73281ad6265SDimitry Andric for (const Arg *A : Args.filtered(options::OPT_mmlir)) { 73381ad6265SDimitry Andric A->claim(); 73481ad6265SDimitry Andric A->render(Args, CmdArgs); 73581ad6265SDimitry Andric } 73681ad6265SDimitry Andric 73706c3fb27SDimitry Andric // Remove any unsupported gfortran diagnostic options 73806c3fb27SDimitry Andric for (const Arg *A : Args.filtered(options::OPT_flang_ignored_w_Group)) { 73906c3fb27SDimitry Andric A->claim(); 74006c3fb27SDimitry Andric D.Diag(diag::warn_drv_unsupported_diag_option_for_flang) 74106c3fb27SDimitry Andric << A->getOption().getName(); 74206c3fb27SDimitry Andric } 74306c3fb27SDimitry Andric 74481ad6265SDimitry Andric // Optimization level for CodeGen. 74581ad6265SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) { 74681ad6265SDimitry Andric if (A->getOption().matches(options::OPT_O4)) { 74781ad6265SDimitry Andric CmdArgs.push_back("-O3"); 74881ad6265SDimitry Andric D.Diag(diag::warn_O4_is_O3); 749bdd1243dSDimitry Andric } else if (A->getOption().matches(options::OPT_Ofast)) { 750bdd1243dSDimitry Andric CmdArgs.push_back("-O3"); 75181ad6265SDimitry Andric } else { 75281ad6265SDimitry Andric A->render(Args, CmdArgs); 75381ad6265SDimitry Andric } 75481ad6265SDimitry Andric } 75581ad6265SDimitry Andric 756*5f757f3fSDimitry Andric assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 757480093f4SDimitry Andric if (Output.isFilename()) { 758480093f4SDimitry Andric CmdArgs.push_back("-o"); 759480093f4SDimitry Andric CmdArgs.push_back(Output.getFilename()); 760480093f4SDimitry Andric } 761480093f4SDimitry Andric 762480093f4SDimitry Andric assert(Input.isFilename() && "Invalid input."); 76381ad6265SDimitry Andric 76406c3fb27SDimitry Andric if (Args.getLastArg(options::OPT_save_temps_EQ)) 76506c3fb27SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ); 76606c3fb27SDimitry Andric 76781ad6265SDimitry Andric addDashXForInput(Args, Input, CmdArgs); 76881ad6265SDimitry Andric 769480093f4SDimitry Andric CmdArgs.push_back(Input.getFilename()); 770480093f4SDimitry Andric 771e8d8bef9SDimitry Andric // TODO: Replace flang-new with flang once the new driver replaces the 772e8d8bef9SDimitry Andric // throwaway driver 773e8d8bef9SDimitry Andric const char *Exec = Args.MakeArgString(D.GetProgramPath("flang-new", TC)); 774e8d8bef9SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, 775e8d8bef9SDimitry Andric ResponseFileSupport::AtFileUTF8(), 776e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 777480093f4SDimitry Andric } 778480093f4SDimitry Andric 779e8d8bef9SDimitry Andric Flang::Flang(const ToolChain &TC) : Tool("flang-new", "flang frontend", TC) {} 780480093f4SDimitry Andric 781480093f4SDimitry Andric Flang::~Flang() {} 782