10b57cec5SDimitry Andric //===--- CommonArgs.cpp - Args handling for multiple toolchains -*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "CommonArgs.h" 100b57cec5SDimitry Andric #include "Arch/AArch64.h" 110b57cec5SDimitry Andric #include "Arch/ARM.h" 12bdd1243dSDimitry Andric #include "Arch/CSKY.h" 13bdd1243dSDimitry Andric #include "Arch/LoongArch.h" 14fe6060f1SDimitry Andric #include "Arch/M68k.h" 150b57cec5SDimitry Andric #include "Arch/Mips.h" 160b57cec5SDimitry Andric #include "Arch/PPC.h" 17bdd1243dSDimitry Andric #include "Arch/RISCV.h" 1861cfbce3SDimitry Andric #include "Arch/Sparc.h" 190b57cec5SDimitry Andric #include "Arch/SystemZ.h" 205ffd83dbSDimitry Andric #include "Arch/VE.h" 210b57cec5SDimitry Andric #include "Arch/X86.h" 220eae32dcSDimitry Andric #include "HIPAMD.h" 230b57cec5SDimitry Andric #include "Hexagon.h" 24bdd1243dSDimitry Andric #include "MSP430.h" 255f757f3fSDimitry Andric #include "Solaris.h" 260b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 275f757f3fSDimitry Andric #include "clang/Basic/CodeGenOptions.h" 280b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h" 290b57cec5SDimitry Andric #include "clang/Basic/ObjCRuntime.h" 300b57cec5SDimitry Andric #include "clang/Basic/Version.h" 310b57cec5SDimitry Andric #include "clang/Config/config.h" 320b57cec5SDimitry Andric #include "clang/Driver/Action.h" 330b57cec5SDimitry Andric #include "clang/Driver/Compilation.h" 340b57cec5SDimitry Andric #include "clang/Driver/Driver.h" 350b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 36fe6060f1SDimitry Andric #include "clang/Driver/InputInfo.h" 370b57cec5SDimitry Andric #include "clang/Driver/Job.h" 380b57cec5SDimitry Andric #include "clang/Driver/Options.h" 390b57cec5SDimitry Andric #include "clang/Driver/SanitizerArgs.h" 400b57cec5SDimitry Andric #include "clang/Driver/ToolChain.h" 410b57cec5SDimitry Andric #include "clang/Driver/Util.h" 420b57cec5SDimitry Andric #include "clang/Driver/XRayArgs.h" 430b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 44349cc55cSDimitry Andric #include "llvm/ADT/SmallSet.h" 450b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 460b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 470b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 480b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 49bdd1243dSDimitry Andric #include "llvm/BinaryFormat/Magic.h" 50e8d8bef9SDimitry Andric #include "llvm/Config/llvm-config.h" 510b57cec5SDimitry Andric #include "llvm/Option/Arg.h" 520b57cec5SDimitry Andric #include "llvm/Option/ArgList.h" 530b57cec5SDimitry Andric #include "llvm/Option/Option.h" 540b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 550b57cec5SDimitry Andric #include "llvm/Support/Compression.h" 560b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 570b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 580b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 590b57cec5SDimitry Andric #include "llvm/Support/Path.h" 600b57cec5SDimitry Andric #include "llvm/Support/Process.h" 610b57cec5SDimitry Andric #include "llvm/Support/Program.h" 620b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 635ffd83dbSDimitry Andric #include "llvm/Support/Threading.h" 640b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 650b57cec5SDimitry Andric #include "llvm/Support/YAMLParser.h" 6606c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 6706c3fb27SDimitry Andric #include "llvm/TargetParser/TargetParser.h" 68bdd1243dSDimitry Andric #include <optional> 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric using namespace clang::driver; 710b57cec5SDimitry Andric using namespace clang::driver::tools; 720b57cec5SDimitry Andric using namespace clang; 730b57cec5SDimitry Andric using namespace llvm::opt; 740b57cec5SDimitry Andric 755f757f3fSDimitry Andric static bool useFramePointerForTargetByDefault(const llvm::opt::ArgList &Args, 765f757f3fSDimitry Andric const llvm::Triple &Triple) { 775f757f3fSDimitry Andric if (Args.hasArg(clang::driver::options::OPT_pg) && 785f757f3fSDimitry Andric !Args.hasArg(clang::driver::options::OPT_mfentry)) 795f757f3fSDimitry Andric return true; 805f757f3fSDimitry Andric 81*0fca6ea1SDimitry Andric if (Triple.isAndroid()) 825f757f3fSDimitry Andric return true; 835f757f3fSDimitry Andric 845f757f3fSDimitry Andric switch (Triple.getArch()) { 855f757f3fSDimitry Andric case llvm::Triple::xcore: 865f757f3fSDimitry Andric case llvm::Triple::wasm32: 875f757f3fSDimitry Andric case llvm::Triple::wasm64: 885f757f3fSDimitry Andric case llvm::Triple::msp430: 895f757f3fSDimitry Andric // XCore never wants frame pointers, regardless of OS. 905f757f3fSDimitry Andric // WebAssembly never wants frame pointers. 915f757f3fSDimitry Andric return false; 925f757f3fSDimitry Andric case llvm::Triple::ppc: 935f757f3fSDimitry Andric case llvm::Triple::ppcle: 945f757f3fSDimitry Andric case llvm::Triple::ppc64: 955f757f3fSDimitry Andric case llvm::Triple::ppc64le: 965f757f3fSDimitry Andric case llvm::Triple::riscv32: 975f757f3fSDimitry Andric case llvm::Triple::riscv64: 985f757f3fSDimitry Andric case llvm::Triple::sparc: 995f757f3fSDimitry Andric case llvm::Triple::sparcel: 1005f757f3fSDimitry Andric case llvm::Triple::sparcv9: 1015f757f3fSDimitry Andric case llvm::Triple::amdgcn: 1025f757f3fSDimitry Andric case llvm::Triple::r600: 1035f757f3fSDimitry Andric case llvm::Triple::csky: 1045f757f3fSDimitry Andric case llvm::Triple::loongarch32: 1055f757f3fSDimitry Andric case llvm::Triple::loongarch64: 106*0fca6ea1SDimitry Andric case llvm::Triple::m68k: 1075f757f3fSDimitry Andric return !clang::driver::tools::areOptimizationsEnabled(Args); 1085f757f3fSDimitry Andric default: 1095f757f3fSDimitry Andric break; 1105f757f3fSDimitry Andric } 1115f757f3fSDimitry Andric 1125f757f3fSDimitry Andric if (Triple.isOSFuchsia() || Triple.isOSNetBSD()) { 1135f757f3fSDimitry Andric return !clang::driver::tools::areOptimizationsEnabled(Args); 1145f757f3fSDimitry Andric } 1155f757f3fSDimitry Andric 1165f757f3fSDimitry Andric if (Triple.isOSLinux() || Triple.isOSHurd()) { 1175f757f3fSDimitry Andric switch (Triple.getArch()) { 1185f757f3fSDimitry Andric // Don't use a frame pointer on linux if optimizing for certain targets. 1195f757f3fSDimitry Andric case llvm::Triple::arm: 1205f757f3fSDimitry Andric case llvm::Triple::armeb: 1215f757f3fSDimitry Andric case llvm::Triple::thumb: 1225f757f3fSDimitry Andric case llvm::Triple::thumbeb: 1235f757f3fSDimitry Andric case llvm::Triple::mips64: 1245f757f3fSDimitry Andric case llvm::Triple::mips64el: 1255f757f3fSDimitry Andric case llvm::Triple::mips: 1265f757f3fSDimitry Andric case llvm::Triple::mipsel: 1275f757f3fSDimitry Andric case llvm::Triple::systemz: 1285f757f3fSDimitry Andric case llvm::Triple::x86: 1295f757f3fSDimitry Andric case llvm::Triple::x86_64: 1305f757f3fSDimitry Andric return !clang::driver::tools::areOptimizationsEnabled(Args); 1315f757f3fSDimitry Andric default: 1325f757f3fSDimitry Andric return true; 1335f757f3fSDimitry Andric } 1345f757f3fSDimitry Andric } 1355f757f3fSDimitry Andric 1365f757f3fSDimitry Andric if (Triple.isOSWindows()) { 1375f757f3fSDimitry Andric switch (Triple.getArch()) { 1385f757f3fSDimitry Andric case llvm::Triple::x86: 1395f757f3fSDimitry Andric return !clang::driver::tools::areOptimizationsEnabled(Args); 1405f757f3fSDimitry Andric case llvm::Triple::x86_64: 1415f757f3fSDimitry Andric return Triple.isOSBinFormatMachO(); 1425f757f3fSDimitry Andric case llvm::Triple::arm: 1435f757f3fSDimitry Andric case llvm::Triple::thumb: 1445f757f3fSDimitry Andric // Windows on ARM builds with FPO disabled to aid fast stack walking 1455f757f3fSDimitry Andric return true; 1465f757f3fSDimitry Andric default: 1475f757f3fSDimitry Andric // All other supported Windows ISAs use xdata unwind information, so frame 1485f757f3fSDimitry Andric // pointers are not generally useful. 1495f757f3fSDimitry Andric return false; 1505f757f3fSDimitry Andric } 1515f757f3fSDimitry Andric } 1525f757f3fSDimitry Andric 1535f757f3fSDimitry Andric return true; 1545f757f3fSDimitry Andric } 1555f757f3fSDimitry Andric 156*0fca6ea1SDimitry Andric static bool useLeafFramePointerForTargetByDefault(const llvm::Triple &Triple) { 157*0fca6ea1SDimitry Andric if (Triple.isAArch64() || Triple.isPS() || Triple.isVE() || 158*0fca6ea1SDimitry Andric (Triple.isAndroid() && !Triple.isARM())) 159*0fca6ea1SDimitry Andric return false; 160*0fca6ea1SDimitry Andric 161*0fca6ea1SDimitry Andric return true; 162*0fca6ea1SDimitry Andric } 163*0fca6ea1SDimitry Andric 1645f757f3fSDimitry Andric static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) { 1655f757f3fSDimitry Andric switch (Triple.getArch()) { 1665f757f3fSDimitry Andric default: 1675f757f3fSDimitry Andric return false; 1685f757f3fSDimitry Andric case llvm::Triple::arm: 1695f757f3fSDimitry Andric case llvm::Triple::thumb: 1705f757f3fSDimitry Andric // ARM Darwin targets require a frame pointer to be always present to aid 1715f757f3fSDimitry Andric // offline debugging via backtraces. 1725f757f3fSDimitry Andric return Triple.isOSDarwin(); 1735f757f3fSDimitry Andric } 1745f757f3fSDimitry Andric } 1755f757f3fSDimitry Andric 176*0fca6ea1SDimitry Andric // True if a target-specific option requires the frame chain to be preserved, 177*0fca6ea1SDimitry Andric // even if new frame records are not created. 178*0fca6ea1SDimitry Andric static bool mustMaintainValidFrameChain(const llvm::opt::ArgList &Args, 179*0fca6ea1SDimitry Andric const llvm::Triple &Triple) { 180*0fca6ea1SDimitry Andric if (Triple.isARM() || Triple.isThumb()) { 181*0fca6ea1SDimitry Andric // For 32-bit Arm, the -mframe-chain=aapcs and -mframe-chain=aapcs+leaf 182*0fca6ea1SDimitry Andric // options require the frame pointer register to be reserved (or point to a 183*0fca6ea1SDimitry Andric // new AAPCS-compilant frame record), even with -fno-omit-frame-pointer. 184*0fca6ea1SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mframe_chain)) { 185*0fca6ea1SDimitry Andric StringRef V = A->getValue(); 186*0fca6ea1SDimitry Andric return V != "none"; 187*0fca6ea1SDimitry Andric } 188*0fca6ea1SDimitry Andric return false; 189*0fca6ea1SDimitry Andric } 190*0fca6ea1SDimitry Andric return false; 191*0fca6ea1SDimitry Andric } 192*0fca6ea1SDimitry Andric 193*0fca6ea1SDimitry Andric // True if a target-specific option causes -fno-omit-frame-pointer to also 194*0fca6ea1SDimitry Andric // cause frame records to be created in leaf functions. 195*0fca6ea1SDimitry Andric static bool framePointerImpliesLeafFramePointer(const llvm::opt::ArgList &Args, 196*0fca6ea1SDimitry Andric const llvm::Triple &Triple) { 197*0fca6ea1SDimitry Andric if (Triple.isARM() || Triple.isThumb()) { 198*0fca6ea1SDimitry Andric // For 32-bit Arm, the -mframe-chain=aapcs+leaf option causes the 199*0fca6ea1SDimitry Andric // -fno-omit-frame-pointer optiion to imply -mno-omit-leaf-frame-pointer, 200*0fca6ea1SDimitry Andric // but does not by itself imply either option. 201*0fca6ea1SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mframe_chain)) { 202*0fca6ea1SDimitry Andric StringRef V = A->getValue(); 203*0fca6ea1SDimitry Andric return V == "aapcs+leaf"; 204*0fca6ea1SDimitry Andric } 205*0fca6ea1SDimitry Andric return false; 206*0fca6ea1SDimitry Andric } 207*0fca6ea1SDimitry Andric return false; 208*0fca6ea1SDimitry Andric } 209*0fca6ea1SDimitry Andric 2105f757f3fSDimitry Andric clang::CodeGenOptions::FramePointerKind 2115f757f3fSDimitry Andric getFramePointerKind(const llvm::opt::ArgList &Args, 2125f757f3fSDimitry Andric const llvm::Triple &Triple) { 213*0fca6ea1SDimitry Andric // There are three things to consider here: 214*0fca6ea1SDimitry Andric // * Should a frame record be created for non-leaf functions? 215*0fca6ea1SDimitry Andric // * Should a frame record be created for leaf functions? 216*0fca6ea1SDimitry Andric // * Is the frame pointer register reserved, i.e. must it always point to 217*0fca6ea1SDimitry Andric // either a new, valid frame record or be un-modified? 2185f757f3fSDimitry Andric // 219*0fca6ea1SDimitry Andric // Not all combinations of these are valid: 220*0fca6ea1SDimitry Andric // * It's not useful to have leaf frame records without non-leaf ones. 221*0fca6ea1SDimitry Andric // * It's not useful to have frame records without reserving the frame 222*0fca6ea1SDimitry Andric // pointer. 2235f757f3fSDimitry Andric // 224*0fca6ea1SDimitry Andric // | Non-leaf | Leaf | Reserved | 225*0fca6ea1SDimitry Andric // | N | N | N | FramePointerKind::None 226*0fca6ea1SDimitry Andric // | N | N | Y | FramePointerKind::Reserved 227*0fca6ea1SDimitry Andric // | N | Y | N | Invalid 228*0fca6ea1SDimitry Andric // | N | Y | Y | Invalid 229*0fca6ea1SDimitry Andric // | Y | N | N | Invalid 230*0fca6ea1SDimitry Andric // | Y | N | Y | FramePointerKind::NonLeaf 231*0fca6ea1SDimitry Andric // | Y | Y | N | Invalid 232*0fca6ea1SDimitry Andric // | Y | Y | Y | FramePointerKind::All 233*0fca6ea1SDimitry Andric // 234*0fca6ea1SDimitry Andric // The FramePointerKind::Reserved case is currently only reachable for Arm, 235*0fca6ea1SDimitry Andric // which has the -mframe-chain= option which can (in combination with 236*0fca6ea1SDimitry Andric // -fno-omit-frame-pointer) specify that the frame chain must be valid, 237*0fca6ea1SDimitry Andric // without requiring new frame records to be created. 2385f757f3fSDimitry Andric 239*0fca6ea1SDimitry Andric bool DefaultFP = useFramePointerForTargetByDefault(Args, Triple); 240*0fca6ea1SDimitry Andric bool EnableFP = 241*0fca6ea1SDimitry Andric mustUseNonLeafFramePointerForTarget(Triple) || 242*0fca6ea1SDimitry Andric Args.hasFlag(clang::driver::options::OPT_fno_omit_frame_pointer, 243*0fca6ea1SDimitry Andric clang::driver::options::OPT_fomit_frame_pointer, DefaultFP); 244*0fca6ea1SDimitry Andric 245*0fca6ea1SDimitry Andric bool DefaultLeafFP = 246*0fca6ea1SDimitry Andric useLeafFramePointerForTargetByDefault(Triple) || 247*0fca6ea1SDimitry Andric (EnableFP && framePointerImpliesLeafFramePointer(Args, Triple)); 248*0fca6ea1SDimitry Andric bool EnableLeafFP = Args.hasFlag( 2495f757f3fSDimitry Andric clang::driver::options::OPT_mno_omit_leaf_frame_pointer, 250*0fca6ea1SDimitry Andric clang::driver::options::OPT_momit_leaf_frame_pointer, DefaultLeafFP); 251*0fca6ea1SDimitry Andric 252*0fca6ea1SDimitry Andric bool FPRegReserved = EnableFP || mustMaintainValidFrameChain(Args, Triple); 253*0fca6ea1SDimitry Andric 254*0fca6ea1SDimitry Andric if (EnableFP) { 255*0fca6ea1SDimitry Andric if (EnableLeafFP) 2565f757f3fSDimitry Andric return clang::CodeGenOptions::FramePointerKind::All; 257*0fca6ea1SDimitry Andric return clang::CodeGenOptions::FramePointerKind::NonLeaf; 2585f757f3fSDimitry Andric } 259*0fca6ea1SDimitry Andric if (FPRegReserved) 260*0fca6ea1SDimitry Andric return clang::CodeGenOptions::FramePointerKind::Reserved; 2615f757f3fSDimitry Andric return clang::CodeGenOptions::FramePointerKind::None; 2625f757f3fSDimitry Andric } 2635f757f3fSDimitry Andric 264bdd1243dSDimitry Andric static void renderRpassOptions(const ArgList &Args, ArgStringList &CmdArgs, 265bdd1243dSDimitry Andric const StringRef PluginOptPrefix) { 266e8d8bef9SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ)) 267bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + 268bdd1243dSDimitry Andric "-pass-remarks=" + A->getValue())); 269e8d8bef9SDimitry Andric 270e8d8bef9SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ)) 271e8d8bef9SDimitry Andric CmdArgs.push_back(Args.MakeArgString( 272bdd1243dSDimitry Andric Twine(PluginOptPrefix) + "-pass-remarks-missed=" + A->getValue())); 273e8d8bef9SDimitry Andric 274e8d8bef9SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ)) 275e8d8bef9SDimitry Andric CmdArgs.push_back(Args.MakeArgString( 276bdd1243dSDimitry Andric Twine(PluginOptPrefix) + "-pass-remarks-analysis=" + A->getValue())); 277e8d8bef9SDimitry Andric } 278e8d8bef9SDimitry Andric 279e8d8bef9SDimitry Andric static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs, 280e8d8bef9SDimitry Andric const llvm::Triple &Triple, 281e8d8bef9SDimitry Andric const InputInfo &Input, 282bdd1243dSDimitry Andric const InputInfo &Output, 283bdd1243dSDimitry Andric const StringRef PluginOptPrefix) { 284e8d8bef9SDimitry Andric StringRef Format = "yaml"; 285e8d8bef9SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ)) 286e8d8bef9SDimitry Andric Format = A->getValue(); 287e8d8bef9SDimitry Andric 288e8d8bef9SDimitry Andric SmallString<128> F; 289e8d8bef9SDimitry Andric const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ); 290e8d8bef9SDimitry Andric if (A) 291e8d8bef9SDimitry Andric F = A->getValue(); 292e8d8bef9SDimitry Andric else if (Output.isFilename()) 293e8d8bef9SDimitry Andric F = Output.getFilename(); 294e8d8bef9SDimitry Andric 295e8d8bef9SDimitry Andric assert(!F.empty() && "Cannot determine remarks output name."); 296e8d8bef9SDimitry Andric // Append "opt.ld.<format>" to the end of the file name. 297bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + 298bdd1243dSDimitry Andric "opt-remarks-filename=" + F + 299bdd1243dSDimitry Andric ".opt.ld." + Format)); 300e8d8bef9SDimitry Andric 301e8d8bef9SDimitry Andric if (const Arg *A = 302e8d8bef9SDimitry Andric Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) 303e8d8bef9SDimitry Andric CmdArgs.push_back(Args.MakeArgString( 304bdd1243dSDimitry Andric Twine(PluginOptPrefix) + "opt-remarks-passes=" + A->getValue())); 305e8d8bef9SDimitry Andric 306bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + 307bdd1243dSDimitry Andric "opt-remarks-format=" + Format.data())); 308e8d8bef9SDimitry Andric } 309e8d8bef9SDimitry Andric 310e8d8bef9SDimitry Andric static void renderRemarksHotnessOptions(const ArgList &Args, 311bdd1243dSDimitry Andric ArgStringList &CmdArgs, 312bdd1243dSDimitry Andric const StringRef PluginOptPrefix) { 313e8d8bef9SDimitry Andric if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness, 314e8d8bef9SDimitry Andric options::OPT_fno_diagnostics_show_hotness, false)) 315bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + 316bdd1243dSDimitry Andric "opt-remarks-with-hotness")); 317e8d8bef9SDimitry Andric 318e8d8bef9SDimitry Andric if (const Arg *A = 319e8d8bef9SDimitry Andric Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) 320bdd1243dSDimitry Andric CmdArgs.push_back( 321bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + 322bdd1243dSDimitry Andric "opt-remarks-hotness-threshold=" + A->getValue())); 323e8d8bef9SDimitry Andric } 324e8d8bef9SDimitry Andric 32506c3fb27SDimitry Andric static bool shouldIgnoreUnsupportedTargetFeature(const Arg &TargetFeatureArg, 32606c3fb27SDimitry Andric llvm::Triple T, 32706c3fb27SDimitry Andric StringRef Processor) { 32806c3fb27SDimitry Andric // Warn no-cumode for AMDGCN processors not supporing WGP mode. 32906c3fb27SDimitry Andric if (!T.isAMDGPU()) 33006c3fb27SDimitry Andric return false; 33106c3fb27SDimitry Andric auto GPUKind = T.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Processor) 33206c3fb27SDimitry Andric : llvm::AMDGPU::parseArchR600(Processor); 33306c3fb27SDimitry Andric auto GPUFeatures = T.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(GPUKind) 33406c3fb27SDimitry Andric : llvm::AMDGPU::getArchAttrR600(GPUKind); 33506c3fb27SDimitry Andric if (GPUFeatures & llvm::AMDGPU::FEATURE_WGP) 33606c3fb27SDimitry Andric return false; 33706c3fb27SDimitry Andric return TargetFeatureArg.getOption().matches(options::OPT_mno_cumode); 33806c3fb27SDimitry Andric } 33906c3fb27SDimitry Andric 3400b57cec5SDimitry Andric void tools::addPathIfExists(const Driver &D, const Twine &Path, 3410b57cec5SDimitry Andric ToolChain::path_list &Paths) { 3420b57cec5SDimitry Andric if (D.getVFS().exists(Path)) 3430b57cec5SDimitry Andric Paths.push_back(Path.str()); 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric 34606c3fb27SDimitry Andric void tools::handleTargetFeaturesGroup(const Driver &D, 34706c3fb27SDimitry Andric const llvm::Triple &Triple, 34806c3fb27SDimitry Andric const ArgList &Args, 3490b57cec5SDimitry Andric std::vector<StringRef> &Features, 3500b57cec5SDimitry Andric OptSpecifier Group) { 35106c3fb27SDimitry Andric std::set<StringRef> Warned; 3520b57cec5SDimitry Andric for (const Arg *A : Args.filtered(Group)) { 3530b57cec5SDimitry Andric StringRef Name = A->getOption().getName(); 3540b57cec5SDimitry Andric A->claim(); 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric // Skip over "-m". 3575f757f3fSDimitry Andric assert(Name.starts_with("m") && "Invalid feature name."); 3580b57cec5SDimitry Andric Name = Name.substr(1); 3590b57cec5SDimitry Andric 36006c3fb27SDimitry Andric auto Proc = getCPUName(D, Args, Triple); 36106c3fb27SDimitry Andric if (shouldIgnoreUnsupportedTargetFeature(*A, Triple, Proc)) { 36206c3fb27SDimitry Andric if (Warned.count(Name) == 0) { 36306c3fb27SDimitry Andric D.getDiags().Report( 36406c3fb27SDimitry Andric clang::diag::warn_drv_unsupported_option_for_processor) 36506c3fb27SDimitry Andric << A->getAsString(Args) << Proc; 36606c3fb27SDimitry Andric Warned.insert(Name); 36706c3fb27SDimitry Andric } 36806c3fb27SDimitry Andric continue; 36906c3fb27SDimitry Andric } 37006c3fb27SDimitry Andric 371*0fca6ea1SDimitry Andric bool IsNegative = Name.consume_front("no-"); 37206c3fb27SDimitry Andric 3730b57cec5SDimitry Andric Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name)); 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 37781ad6265SDimitry Andric SmallVector<StringRef> 37881ad6265SDimitry Andric tools::unifyTargetFeatures(ArrayRef<StringRef> Features) { 37981ad6265SDimitry Andric // Only add a feature if it hasn't been seen before starting from the end. 38081ad6265SDimitry Andric SmallVector<StringRef> UnifiedFeatures; 38181ad6265SDimitry Andric llvm::DenseSet<StringRef> UsedFeatures; 38281ad6265SDimitry Andric for (StringRef Feature : llvm::reverse(Features)) { 38381ad6265SDimitry Andric if (UsedFeatures.insert(Feature.drop_front()).second) 38481ad6265SDimitry Andric UnifiedFeatures.insert(UnifiedFeatures.begin(), Feature); 3855ffd83dbSDimitry Andric } 3865ffd83dbSDimitry Andric 3875ffd83dbSDimitry Andric return UnifiedFeatures; 3885ffd83dbSDimitry Andric } 3895ffd83dbSDimitry Andric 3900b57cec5SDimitry Andric void tools::addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs, 3910b57cec5SDimitry Andric const char *ArgName, const char *EnvVar) { 3920b57cec5SDimitry Andric const char *DirList = ::getenv(EnvVar); 3930b57cec5SDimitry Andric bool CombinedArg = false; 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric if (!DirList) 3960b57cec5SDimitry Andric return; // Nothing to do. 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric StringRef Name(ArgName); 399*0fca6ea1SDimitry Andric if (Name == "-I" || Name == "-L" || Name.empty()) 4000b57cec5SDimitry Andric CombinedArg = true; 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric StringRef Dirs(DirList); 4030b57cec5SDimitry Andric if (Dirs.empty()) // Empty string should not add '.'. 4040b57cec5SDimitry Andric return; 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric StringRef::size_type Delim; 4070b57cec5SDimitry Andric while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) { 4080b57cec5SDimitry Andric if (Delim == 0) { // Leading colon. 4090b57cec5SDimitry Andric if (CombinedArg) { 4100b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + ".")); 4110b57cec5SDimitry Andric } else { 4120b57cec5SDimitry Andric CmdArgs.push_back(ArgName); 4130b57cec5SDimitry Andric CmdArgs.push_back("."); 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric } else { 4160b57cec5SDimitry Andric if (CombinedArg) { 4170b57cec5SDimitry Andric CmdArgs.push_back( 4180b57cec5SDimitry Andric Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim))); 4190b57cec5SDimitry Andric } else { 4200b57cec5SDimitry Andric CmdArgs.push_back(ArgName); 4210b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim))); 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric } 4240b57cec5SDimitry Andric Dirs = Dirs.substr(Delim + 1); 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric if (Dirs.empty()) { // Trailing colon. 4280b57cec5SDimitry Andric if (CombinedArg) { 4290b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + ".")); 4300b57cec5SDimitry Andric } else { 4310b57cec5SDimitry Andric CmdArgs.push_back(ArgName); 4320b57cec5SDimitry Andric CmdArgs.push_back("."); 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric } else { // Add the last path. 4350b57cec5SDimitry Andric if (CombinedArg) { 4360b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs)); 4370b57cec5SDimitry Andric } else { 4380b57cec5SDimitry Andric CmdArgs.push_back(ArgName); 4390b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Dirs)); 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, 4450b57cec5SDimitry Andric const ArgList &Args, ArgStringList &CmdArgs, 4460b57cec5SDimitry Andric const JobAction &JA) { 4470b57cec5SDimitry Andric const Driver &D = TC.getDriver(); 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric // Add extra linker input arguments which are not treated as inputs 4500b57cec5SDimitry Andric // (constructed via -Xarch_). 4510b57cec5SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input); 4520b57cec5SDimitry Andric 453a7dea167SDimitry Andric // LIBRARY_PATH are included before user inputs and only supported on native 454a7dea167SDimitry Andric // toolchains. 455a7dea167SDimitry Andric if (!TC.isCrossCompiling()) 456a7dea167SDimitry Andric addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); 457a7dea167SDimitry Andric 4580b57cec5SDimitry Andric for (const auto &II : Inputs) { 4595ffd83dbSDimitry Andric // If the current tool chain refers to an OpenMP offloading host, we 4605ffd83dbSDimitry Andric // should ignore inputs that refer to OpenMP offloading devices - 4610b57cec5SDimitry Andric // they will be embedded according to a proper linker script. 4620b57cec5SDimitry Andric if (auto *IA = II.getAction()) 4630b57cec5SDimitry Andric if ((JA.isHostOffloading(Action::OFK_OpenMP) && 4645ffd83dbSDimitry Andric IA->isDeviceOffloading(Action::OFK_OpenMP))) 4650b57cec5SDimitry Andric continue; 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric if (!TC.HasNativeLLVMSupport() && types::isLLVMIR(II.getType())) 4680b57cec5SDimitry Andric // Don't try to pass LLVM inputs unless we have native support. 4690b57cec5SDimitry Andric D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString(); 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric // Add filenames immediately. 4720b57cec5SDimitry Andric if (II.isFilename()) { 4730b57cec5SDimitry Andric CmdArgs.push_back(II.getFilename()); 4740b57cec5SDimitry Andric continue; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 47781ad6265SDimitry Andric // In some error cases, the input could be Nothing; skip those. 47881ad6265SDimitry Andric if (II.isNothing()) 47981ad6265SDimitry Andric continue; 48081ad6265SDimitry Andric 4810b57cec5SDimitry Andric // Otherwise, this is a linker input argument. 4820b57cec5SDimitry Andric const Arg &A = II.getInputArg(); 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric // Handle reserved library options. 4850b57cec5SDimitry Andric if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) 4860b57cec5SDimitry Andric TC.AddCXXStdlibLibArgs(Args, CmdArgs); 4870b57cec5SDimitry Andric else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext)) 4880b57cec5SDimitry Andric TC.AddCCKextLibArgs(Args, CmdArgs); 48906c3fb27SDimitry Andric else 4900b57cec5SDimitry Andric A.renderAsInput(Args, CmdArgs); 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric } 4930b57cec5SDimitry Andric 49419587d74SEd Maste void tools::addLinkerCompressDebugSectionsOption( 49519587d74SEd Maste const ToolChain &TC, const llvm::opt::ArgList &Args, 49619587d74SEd Maste llvm::opt::ArgStringList &CmdArgs) { 49719587d74SEd Maste // GNU ld supports --compress-debug-sections=none|zlib|zlib-gnu|zlib-gabi 49804eeddc0SDimitry Andric // whereas zlib is an alias to zlib-gabi and zlib-gnu is obsoleted. Therefore 49904eeddc0SDimitry Andric // -gz=none|zlib are translated to --compress-debug-sections=none|zlib. -gz 50004eeddc0SDimitry Andric // is not translated since ld --compress-debug-sections option requires an 50119587d74SEd Maste // argument. 50219587d74SEd Maste if (const Arg *A = Args.getLastArg(options::OPT_gz_EQ)) { 50319587d74SEd Maste StringRef V = A->getValue(); 504bdd1243dSDimitry Andric if (V == "none" || V == "zlib" || V == "zstd") 50519587d74SEd Maste CmdArgs.push_back(Args.MakeArgString("--compress-debug-sections=" + V)); 50619587d74SEd Maste else 50719587d74SEd Maste TC.getDriver().Diag(diag::err_drv_unsupported_option_argument) 508bdd1243dSDimitry Andric << A->getSpelling() << V; 50919587d74SEd Maste } 51019587d74SEd Maste } 51119587d74SEd Maste 5120b57cec5SDimitry Andric void tools::AddTargetFeature(const ArgList &Args, 5130b57cec5SDimitry Andric std::vector<StringRef> &Features, 5140b57cec5SDimitry Andric OptSpecifier OnOpt, OptSpecifier OffOpt, 5150b57cec5SDimitry Andric StringRef FeatureName) { 5160b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) { 5170b57cec5SDimitry Andric if (A->getOption().matches(OnOpt)) 5180b57cec5SDimitry Andric Features.push_back(Args.MakeArgString("+" + FeatureName)); 5190b57cec5SDimitry Andric else 5200b57cec5SDimitry Andric Features.push_back(Args.MakeArgString("-" + FeatureName)); 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric 524e8d8bef9SDimitry Andric /// Get the (LLVM) name of the AMDGPU gpu we are targeting. 525e8d8bef9SDimitry Andric static std::string getAMDGPUTargetGPU(const llvm::Triple &T, 526e8d8bef9SDimitry Andric const ArgList &Args) { 52706c3fb27SDimitry Andric Arg *MArch = Args.getLastArg(options::OPT_march_EQ); 5280b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { 529e8d8bef9SDimitry Andric auto GPUName = getProcessorFromTargetID(T, A->getValue()); 530e8d8bef9SDimitry Andric return llvm::StringSwitch<std::string>(GPUName) 5310b57cec5SDimitry Andric .Cases("rv630", "rv635", "r600") 5320b57cec5SDimitry Andric .Cases("rv610", "rv620", "rs780", "rs880") 5330b57cec5SDimitry Andric .Case("rv740", "rv770") 5340b57cec5SDimitry Andric .Case("palm", "cedar") 5350b57cec5SDimitry Andric .Cases("sumo", "sumo2", "sumo") 5360b57cec5SDimitry Andric .Case("hemlock", "cypress") 5370b57cec5SDimitry Andric .Case("aruba", "cayman") 538e8d8bef9SDimitry Andric .Default(GPUName.str()); 5390b57cec5SDimitry Andric } 54006c3fb27SDimitry Andric if (MArch) 54106c3fb27SDimitry Andric return getProcessorFromTargetID(T, MArch->getValue()).str(); 5420b57cec5SDimitry Andric return ""; 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric static std::string getLanaiTargetCPU(const ArgList &Args) { 5460b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { 5470b57cec5SDimitry Andric return A->getValue(); 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric return ""; 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric /// Get the (LLVM) name of the WebAssembly cpu we are targeting. 5530b57cec5SDimitry Andric static StringRef getWebAssemblyTargetCPU(const ArgList &Args) { 5540b57cec5SDimitry Andric // If we have -mcpu=, use that. 5550b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { 5560b57cec5SDimitry Andric StringRef CPU = A->getValue(); 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric #ifdef __wasm__ 5590b57cec5SDimitry Andric // Handle "native" by examining the host. "native" isn't meaningful when 5600b57cec5SDimitry Andric // cross compiling, so only support this when the host is also WebAssembly. 5610b57cec5SDimitry Andric if (CPU == "native") 5620b57cec5SDimitry Andric return llvm::sys::getHostCPUName(); 5630b57cec5SDimitry Andric #endif 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric return CPU; 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric return "generic"; 5690b57cec5SDimitry Andric } 5700b57cec5SDimitry Andric 571349cc55cSDimitry Andric std::string tools::getCPUName(const Driver &D, const ArgList &Args, 572349cc55cSDimitry Andric const llvm::Triple &T, bool FromAs) { 5730b57cec5SDimitry Andric Arg *A; 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric switch (T.getArch()) { 5760b57cec5SDimitry Andric default: 5770b57cec5SDimitry Andric return ""; 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric case llvm::Triple::aarch64: 580480093f4SDimitry Andric case llvm::Triple::aarch64_32: 5810b57cec5SDimitry Andric case llvm::Triple::aarch64_be: 5820b57cec5SDimitry Andric return aarch64::getAArch64TargetCPU(Args, T, A); 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric case llvm::Triple::arm: 5850b57cec5SDimitry Andric case llvm::Triple::armeb: 5860b57cec5SDimitry Andric case llvm::Triple::thumb: 5870b57cec5SDimitry Andric case llvm::Triple::thumbeb: { 5880b57cec5SDimitry Andric StringRef MArch, MCPU; 5890b57cec5SDimitry Andric arm::getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs); 5900b57cec5SDimitry Andric return arm::getARMTargetCPU(MCPU, MArch, T); 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric case llvm::Triple::avr: 5940b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_mmcu_EQ)) 5950b57cec5SDimitry Andric return A->getValue(); 5960b57cec5SDimitry Andric return ""; 5970b57cec5SDimitry Andric 598fe6060f1SDimitry Andric case llvm::Triple::m68k: 599fe6060f1SDimitry Andric return m68k::getM68kTargetCPU(Args); 600fe6060f1SDimitry Andric 6010b57cec5SDimitry Andric case llvm::Triple::mips: 6020b57cec5SDimitry Andric case llvm::Triple::mipsel: 6030b57cec5SDimitry Andric case llvm::Triple::mips64: 6040b57cec5SDimitry Andric case llvm::Triple::mips64el: { 6050b57cec5SDimitry Andric StringRef CPUName; 6060b57cec5SDimitry Andric StringRef ABIName; 6070b57cec5SDimitry Andric mips::getMipsCPUAndABI(Args, T, CPUName, ABIName); 6085ffd83dbSDimitry Andric return std::string(CPUName); 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric case llvm::Triple::nvptx: 6120b57cec5SDimitry Andric case llvm::Triple::nvptx64: 6130b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) 6140b57cec5SDimitry Andric return A->getValue(); 6150b57cec5SDimitry Andric return ""; 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric case llvm::Triple::ppc: 618e8d8bef9SDimitry Andric case llvm::Triple::ppcle: 6190b57cec5SDimitry Andric case llvm::Triple::ppc64: 620bdd1243dSDimitry Andric case llvm::Triple::ppc64le: 62106c3fb27SDimitry Andric return ppc::getPPCTargetCPU(D, Args, T); 6225ffd83dbSDimitry Andric 62381ad6265SDimitry Andric case llvm::Triple::csky: 62481ad6265SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) 62581ad6265SDimitry Andric return A->getValue(); 62681ad6265SDimitry Andric else if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) 62781ad6265SDimitry Andric return A->getValue(); 62881ad6265SDimitry Andric else 62981ad6265SDimitry Andric return "ck810"; 630590d96feSDimitry Andric case llvm::Triple::riscv32: 631590d96feSDimitry Andric case llvm::Triple::riscv64: 632bdd1243dSDimitry Andric return riscv::getRISCVTargetCPU(Args, T); 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric case llvm::Triple::bpfel: 6350b57cec5SDimitry Andric case llvm::Triple::bpfeb: 63661cfbce3SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) 63761cfbce3SDimitry Andric return A->getValue(); 63861cfbce3SDimitry Andric return ""; 63961cfbce3SDimitry Andric 6400b57cec5SDimitry Andric case llvm::Triple::sparc: 6410b57cec5SDimitry Andric case llvm::Triple::sparcel: 6420b57cec5SDimitry Andric case llvm::Triple::sparcv9: 64361cfbce3SDimitry Andric return sparc::getSparcTargetCPU(D, Args, T); 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric case llvm::Triple::x86: 6460b57cec5SDimitry Andric case llvm::Triple::x86_64: 647349cc55cSDimitry Andric return x86::getX86TargetCPU(D, Args, T); 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric case llvm::Triple::hexagon: 6500b57cec5SDimitry Andric return "hexagon" + 6510b57cec5SDimitry Andric toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str(); 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric case llvm::Triple::lanai: 6540b57cec5SDimitry Andric return getLanaiTargetCPU(Args); 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric case llvm::Triple::systemz: 6570b57cec5SDimitry Andric return systemz::getSystemZTargetCPU(Args); 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric case llvm::Triple::r600: 6600b57cec5SDimitry Andric case llvm::Triple::amdgcn: 661e8d8bef9SDimitry Andric return getAMDGPUTargetGPU(T, Args); 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric case llvm::Triple::wasm32: 6640b57cec5SDimitry Andric case llvm::Triple::wasm64: 6655ffd83dbSDimitry Andric return std::string(getWebAssemblyTargetCPU(Args)); 6668a4dda33SDimitry Andric 6678a4dda33SDimitry Andric case llvm::Triple::loongarch32: 6688a4dda33SDimitry Andric case llvm::Triple::loongarch64: 6698a4dda33SDimitry Andric return loongarch::getLoongArchTargetCPU(Args, T); 6700b57cec5SDimitry Andric } 6710b57cec5SDimitry Andric } 6720b57cec5SDimitry Andric 67306c3fb27SDimitry Andric static void getWebAssemblyTargetFeatures(const Driver &D, 67406c3fb27SDimitry Andric const llvm::Triple &Triple, 67506c3fb27SDimitry Andric const ArgList &Args, 676bdd1243dSDimitry Andric std::vector<StringRef> &Features) { 67706c3fb27SDimitry Andric handleTargetFeaturesGroup(D, Triple, Args, Features, 67806c3fb27SDimitry Andric options::OPT_m_wasm_Features_Group); 679bdd1243dSDimitry Andric } 680bdd1243dSDimitry Andric 681bdd1243dSDimitry Andric void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple, 682bdd1243dSDimitry Andric const ArgList &Args, ArgStringList &CmdArgs, 683bdd1243dSDimitry Andric bool ForAS, bool IsAux) { 684bdd1243dSDimitry Andric std::vector<StringRef> Features; 685bdd1243dSDimitry Andric switch (Triple.getArch()) { 686bdd1243dSDimitry Andric default: 687bdd1243dSDimitry Andric break; 688bdd1243dSDimitry Andric case llvm::Triple::mips: 689bdd1243dSDimitry Andric case llvm::Triple::mipsel: 690bdd1243dSDimitry Andric case llvm::Triple::mips64: 691bdd1243dSDimitry Andric case llvm::Triple::mips64el: 692bdd1243dSDimitry Andric mips::getMIPSTargetFeatures(D, Triple, Args, Features); 693bdd1243dSDimitry Andric break; 694bdd1243dSDimitry Andric case llvm::Triple::arm: 695bdd1243dSDimitry Andric case llvm::Triple::armeb: 696bdd1243dSDimitry Andric case llvm::Triple::thumb: 697bdd1243dSDimitry Andric case llvm::Triple::thumbeb: 698bdd1243dSDimitry Andric arm::getARMTargetFeatures(D, Triple, Args, Features, ForAS); 699bdd1243dSDimitry Andric break; 700bdd1243dSDimitry Andric case llvm::Triple::ppc: 701bdd1243dSDimitry Andric case llvm::Triple::ppcle: 702bdd1243dSDimitry Andric case llvm::Triple::ppc64: 703bdd1243dSDimitry Andric case llvm::Triple::ppc64le: 704bdd1243dSDimitry Andric ppc::getPPCTargetFeatures(D, Triple, Args, Features); 705bdd1243dSDimitry Andric break; 706bdd1243dSDimitry Andric case llvm::Triple::riscv32: 707bdd1243dSDimitry Andric case llvm::Triple::riscv64: 708bdd1243dSDimitry Andric riscv::getRISCVTargetFeatures(D, Triple, Args, Features); 709bdd1243dSDimitry Andric break; 710bdd1243dSDimitry Andric case llvm::Triple::systemz: 711bdd1243dSDimitry Andric systemz::getSystemZTargetFeatures(D, Args, Features); 712bdd1243dSDimitry Andric break; 713bdd1243dSDimitry Andric case llvm::Triple::aarch64: 714bdd1243dSDimitry Andric case llvm::Triple::aarch64_32: 715bdd1243dSDimitry Andric case llvm::Triple::aarch64_be: 716bdd1243dSDimitry Andric aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS); 717bdd1243dSDimitry Andric break; 718bdd1243dSDimitry Andric case llvm::Triple::x86: 719bdd1243dSDimitry Andric case llvm::Triple::x86_64: 720bdd1243dSDimitry Andric x86::getX86TargetFeatures(D, Triple, Args, Features); 721bdd1243dSDimitry Andric break; 722bdd1243dSDimitry Andric case llvm::Triple::hexagon: 72306c3fb27SDimitry Andric hexagon::getHexagonTargetFeatures(D, Triple, Args, Features); 724bdd1243dSDimitry Andric break; 725bdd1243dSDimitry Andric case llvm::Triple::wasm32: 726bdd1243dSDimitry Andric case llvm::Triple::wasm64: 72706c3fb27SDimitry Andric getWebAssemblyTargetFeatures(D, Triple, Args, Features); 728bdd1243dSDimitry Andric break; 729bdd1243dSDimitry Andric case llvm::Triple::sparc: 730bdd1243dSDimitry Andric case llvm::Triple::sparcel: 731bdd1243dSDimitry Andric case llvm::Triple::sparcv9: 732bdd1243dSDimitry Andric sparc::getSparcTargetFeatures(D, Args, Features); 733bdd1243dSDimitry Andric break; 734bdd1243dSDimitry Andric case llvm::Triple::r600: 735bdd1243dSDimitry Andric case llvm::Triple::amdgcn: 736bdd1243dSDimitry Andric amdgpu::getAMDGPUTargetFeatures(D, Triple, Args, Features); 737bdd1243dSDimitry Andric break; 738bdd1243dSDimitry Andric case llvm::Triple::nvptx: 739bdd1243dSDimitry Andric case llvm::Triple::nvptx64: 740bdd1243dSDimitry Andric NVPTX::getNVPTXTargetFeatures(D, Triple, Args, Features); 741bdd1243dSDimitry Andric break; 742bdd1243dSDimitry Andric case llvm::Triple::m68k: 743bdd1243dSDimitry Andric m68k::getM68kTargetFeatures(D, Triple, Args, Features); 744bdd1243dSDimitry Andric break; 745bdd1243dSDimitry Andric case llvm::Triple::msp430: 746bdd1243dSDimitry Andric msp430::getMSP430TargetFeatures(D, Args, Features); 747bdd1243dSDimitry Andric break; 748bdd1243dSDimitry Andric case llvm::Triple::ve: 749bdd1243dSDimitry Andric ve::getVETargetFeatures(D, Args, Features); 750bdd1243dSDimitry Andric break; 751bdd1243dSDimitry Andric case llvm::Triple::csky: 752bdd1243dSDimitry Andric csky::getCSKYTargetFeatures(D, Triple, Args, CmdArgs, Features); 753bdd1243dSDimitry Andric break; 754bdd1243dSDimitry Andric case llvm::Triple::loongarch32: 755bdd1243dSDimitry Andric case llvm::Triple::loongarch64: 756bdd1243dSDimitry Andric loongarch::getLoongArchTargetFeatures(D, Triple, Args, Features); 757bdd1243dSDimitry Andric break; 758bdd1243dSDimitry Andric } 759bdd1243dSDimitry Andric 760bdd1243dSDimitry Andric for (auto Feature : unifyTargetFeatures(Features)) { 761bdd1243dSDimitry Andric CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature"); 762bdd1243dSDimitry Andric CmdArgs.push_back(Feature.data()); 763bdd1243dSDimitry Andric } 764bdd1243dSDimitry Andric } 765bdd1243dSDimitry Andric 7665ffd83dbSDimitry Andric llvm::StringRef tools::getLTOParallelism(const ArgList &Args, const Driver &D) { 7670b57cec5SDimitry Andric Arg *LtoJobsArg = Args.getLastArg(options::OPT_flto_jobs_EQ); 7685ffd83dbSDimitry Andric if (!LtoJobsArg) 7695ffd83dbSDimitry Andric return {}; 7705ffd83dbSDimitry Andric if (!llvm::get_threadpool_strategy(LtoJobsArg->getValue())) 7715ffd83dbSDimitry Andric D.Diag(diag::err_drv_invalid_int_value) 7725ffd83dbSDimitry Andric << LtoJobsArg->getAsString(Args) << LtoJobsArg->getValue(); 7735ffd83dbSDimitry Andric return LtoJobsArg->getValue(); 7740b57cec5SDimitry Andric } 7750b57cec5SDimitry Andric 7765f757f3fSDimitry Andric // PS4/PS5 uses -ffunction-sections and -fdata-sections by default. 7770b57cec5SDimitry Andric bool tools::isUseSeparateSections(const llvm::Triple &Triple) { 7785f757f3fSDimitry Andric return Triple.isPS(); 7790b57cec5SDimitry Andric } 7800b57cec5SDimitry Andric 781b3edf446SDimitry Andric bool tools::isTLSDESCEnabled(const ToolChain &TC, 782b3edf446SDimitry Andric const llvm::opt::ArgList &Args) { 783b3edf446SDimitry Andric const llvm::Triple &Triple = TC.getEffectiveTriple(); 784b3edf446SDimitry Andric Arg *A = Args.getLastArg(options::OPT_mtls_dialect_EQ); 785b3edf446SDimitry Andric if (!A) 786b3edf446SDimitry Andric return Triple.hasDefaultTLSDESC(); 787b3edf446SDimitry Andric StringRef V = A->getValue(); 788b3edf446SDimitry Andric bool SupportedArgument = false, EnableTLSDESC = false; 789b3edf446SDimitry Andric bool Unsupported = !Triple.isOSBinFormatELF(); 790*0fca6ea1SDimitry Andric if (Triple.isLoongArch() || Triple.isRISCV()) { 791b3edf446SDimitry Andric SupportedArgument = V == "desc" || V == "trad"; 792b3edf446SDimitry Andric EnableTLSDESC = V == "desc"; 793b3edf446SDimitry Andric } else if (Triple.isX86()) { 794*0fca6ea1SDimitry Andric SupportedArgument = V == "gnu" || V == "gnu2"; 795*0fca6ea1SDimitry Andric EnableTLSDESC = V == "gnu2"; 796b3edf446SDimitry Andric } else { 797b3edf446SDimitry Andric Unsupported = true; 798b3edf446SDimitry Andric } 799b3edf446SDimitry Andric if (Unsupported) { 800b3edf446SDimitry Andric TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) 801b3edf446SDimitry Andric << A->getSpelling() << Triple.getTriple(); 802b3edf446SDimitry Andric } else if (!SupportedArgument) { 803b3edf446SDimitry Andric TC.getDriver().Diag(diag::err_drv_unsupported_option_argument_for_target) 804b3edf446SDimitry Andric << A->getSpelling() << V << Triple.getTriple(); 805b3edf446SDimitry Andric } 806b3edf446SDimitry Andric return EnableTLSDESC; 807b3edf446SDimitry Andric } 808b3edf446SDimitry Andric 8095ffd83dbSDimitry Andric void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, 8100b57cec5SDimitry Andric ArgStringList &CmdArgs, const InputInfo &Output, 8110b57cec5SDimitry Andric const InputInfo &Input, bool IsThinLTO) { 812*0fca6ea1SDimitry Andric const llvm::Triple &Triple = ToolChain.getTriple(); 813*0fca6ea1SDimitry Andric const bool IsOSAIX = Triple.isOSAIX(); 814*0fca6ea1SDimitry Andric const bool IsAMDGCN = Triple.isAMDGCN(); 8155ffd83dbSDimitry Andric const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); 8165ffd83dbSDimitry Andric const Driver &D = ToolChain.getDriver(); 8177a6dacacSDimitry Andric const bool IsFatLTO = Args.hasArg(options::OPT_ffat_lto_objects); 8187a6dacacSDimitry Andric const bool IsUnifiedLTO = Args.hasArg(options::OPT_funified_lto); 8195ffd83dbSDimitry Andric if (llvm::sys::path::filename(Linker) != "ld.lld" && 820*0fca6ea1SDimitry Andric llvm::sys::path::stem(Linker) != "ld.lld" && !Triple.isOSOpenBSD()) { 8215ffd83dbSDimitry Andric // Tell the linker to load the plugin. This has to come before 822bdd1243dSDimitry Andric // AddLinkerInputs as gold requires -plugin and AIX ld requires -bplugin to 823bdd1243dSDimitry Andric // come before any -plugin-opt/-bplugin_opt that -Wl might forward. 824bdd1243dSDimitry Andric const char *PluginPrefix = IsOSAIX ? "-bplugin:" : ""; 825bdd1243dSDimitry Andric const char *PluginName = IsOSAIX ? "/libLTO" : "/LLVMgold"; 826bdd1243dSDimitry Andric 827bdd1243dSDimitry Andric if (!IsOSAIX) 8280b57cec5SDimitry Andric CmdArgs.push_back("-plugin"); 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric #if defined(_WIN32) 8310b57cec5SDimitry Andric const char *Suffix = ".dll"; 8320b57cec5SDimitry Andric #elif defined(__APPLE__) 8330b57cec5SDimitry Andric const char *Suffix = ".dylib"; 8340b57cec5SDimitry Andric #else 8350b57cec5SDimitry Andric const char *Suffix = ".so"; 8360b57cec5SDimitry Andric #endif 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric SmallString<1024> Plugin; 839bdd1243dSDimitry Andric llvm::sys::path::native(Twine(D.Dir) + 840bdd1243dSDimitry Andric "/../" CLANG_INSTALL_LIBDIR_BASENAME + 841bdd1243dSDimitry Andric PluginName + Suffix, 8420b57cec5SDimitry Andric Plugin); 843bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginPrefix) + Plugin)); 8445f757f3fSDimitry Andric } else { 8455f757f3fSDimitry Andric // Tell LLD to find and use .llvm.lto section in regular relocatable object 8465f757f3fSDimitry Andric // files 8477a6dacacSDimitry Andric if (IsFatLTO) 8485f757f3fSDimitry Andric CmdArgs.push_back("--fat-lto-objects"); 849bdd1243dSDimitry Andric } 850bdd1243dSDimitry Andric 851bdd1243dSDimitry Andric const char *PluginOptPrefix = IsOSAIX ? "-bplugin_opt:" : "-plugin-opt="; 852bdd1243dSDimitry Andric const char *ExtraDash = IsOSAIX ? "-" : ""; 8535f757f3fSDimitry Andric const char *ParallelismOpt = IsOSAIX ? "-threads=" : "jobs="; 854bdd1243dSDimitry Andric 855bdd1243dSDimitry Andric // Note, this solution is far from perfect, better to encode it into IR 856bdd1243dSDimitry Andric // metadata, but this may not be worth it, since it looks like aranges is on 857bdd1243dSDimitry Andric // the way out. 858bdd1243dSDimitry Andric if (Args.hasArg(options::OPT_gdwarf_aranges)) { 859bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + 860bdd1243dSDimitry Andric "-generate-arange-section")); 8615ffd83dbSDimitry Andric } 8620b57cec5SDimitry Andric 863b3edf446SDimitry Andric // Pass vector library arguments to LTO. 864b3edf446SDimitry Andric Arg *ArgVecLib = Args.getLastArg(options::OPT_fveclib); 865b3edf446SDimitry Andric if (ArgVecLib && ArgVecLib->getNumValues() == 1) { 866b3edf446SDimitry Andric // Map the vector library names from clang front-end to opt front-end. The 867b3edf446SDimitry Andric // values are taken from the TargetLibraryInfo class command line options. 868b3edf446SDimitry Andric std::optional<StringRef> OptVal = 869b3edf446SDimitry Andric llvm::StringSwitch<std::optional<StringRef>>(ArgVecLib->getValue()) 870b3edf446SDimitry Andric .Case("Accelerate", "Accelerate") 871b3edf446SDimitry Andric .Case("LIBMVEC", "LIBMVEC-X86") 872b3edf446SDimitry Andric .Case("MASSV", "MASSV") 873b3edf446SDimitry Andric .Case("SVML", "SVML") 874b3edf446SDimitry Andric .Case("SLEEF", "sleefgnuabi") 875b3edf446SDimitry Andric .Case("Darwin_libsystem_m", "Darwin_libsystem_m") 876b3edf446SDimitry Andric .Case("ArmPL", "ArmPL") 877b3edf446SDimitry Andric .Case("none", "none") 878b3edf446SDimitry Andric .Default(std::nullopt); 879b3edf446SDimitry Andric 880b3edf446SDimitry Andric if (OptVal) 881b3edf446SDimitry Andric CmdArgs.push_back(Args.MakeArgString( 882b3edf446SDimitry Andric Twine(PluginOptPrefix) + "-vector-library=" + OptVal.value())); 883b3edf446SDimitry Andric } 884b3edf446SDimitry Andric 8850b57cec5SDimitry Andric // Try to pass driver level flags relevant to LTO code generation down to 8860b57cec5SDimitry Andric // the plugin. 8870b57cec5SDimitry Andric 8880b57cec5SDimitry Andric // Handle flags for selecting CPU variants. 889*0fca6ea1SDimitry Andric std::string CPU = getCPUName(D, Args, Triple); 8900b57cec5SDimitry Andric if (!CPU.empty()) 891bdd1243dSDimitry Andric CmdArgs.push_back( 892bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "mcpu=" + CPU)); 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { 8955ffd83dbSDimitry Andric // The optimization level matches 8965ffd83dbSDimitry Andric // CompilerInvocation.cpp:getOptimizationLevel(). 8970b57cec5SDimitry Andric StringRef OOpt; 8980b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_O4) || 8990b57cec5SDimitry Andric A->getOption().matches(options::OPT_Ofast)) 9000b57cec5SDimitry Andric OOpt = "3"; 9015ffd83dbSDimitry Andric else if (A->getOption().matches(options::OPT_O)) { 9020b57cec5SDimitry Andric OOpt = A->getValue(); 9035ffd83dbSDimitry Andric if (OOpt == "g") 9045ffd83dbSDimitry Andric OOpt = "1"; 9055ffd83dbSDimitry Andric else if (OOpt == "s" || OOpt == "z") 9065ffd83dbSDimitry Andric OOpt = "2"; 9075ffd83dbSDimitry Andric } else if (A->getOption().matches(options::OPT_O0)) 9080b57cec5SDimitry Andric OOpt = "0"; 90906c3fb27SDimitry Andric if (!OOpt.empty()) { 910bdd1243dSDimitry Andric CmdArgs.push_back( 911bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "O" + OOpt)); 91206c3fb27SDimitry Andric if (IsAMDGCN) 91306c3fb27SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine("--lto-CGO") + OOpt)); 91406c3fb27SDimitry Andric } 9150b57cec5SDimitry Andric } 9160b57cec5SDimitry Andric 917bdd1243dSDimitry Andric if (Args.hasArg(options::OPT_gsplit_dwarf)) 918bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString( 919bdd1243dSDimitry Andric Twine(PluginOptPrefix) + "dwo_dir=" + Output.getFilename() + "_dwo")); 9200b57cec5SDimitry Andric 92106c3fb27SDimitry Andric if (IsThinLTO && !IsOSAIX) 922bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + "thinlto")); 92306c3fb27SDimitry Andric else if (IsThinLTO && IsOSAIX) 92406c3fb27SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine("-bdbg:thinlto"))); 92506c3fb27SDimitry Andric 9265f757f3fSDimitry Andric // Matrix intrinsic lowering happens at link time with ThinLTO. Enable 9275f757f3fSDimitry Andric // LowerMatrixIntrinsicsPass, which is transitively called by 9285f757f3fSDimitry Andric // buildThinLTODefaultPipeline under EnableMatrix. 9297a6dacacSDimitry Andric if ((IsThinLTO || IsFatLTO || IsUnifiedLTO) && 9307a6dacacSDimitry Andric Args.hasArg(options::OPT_fenable_matrix)) 9315f757f3fSDimitry Andric CmdArgs.push_back( 9325f757f3fSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-enable-matrix")); 9330b57cec5SDimitry Andric 9345ffd83dbSDimitry Andric StringRef Parallelism = getLTOParallelism(Args, D); 9355ffd83dbSDimitry Andric if (!Parallelism.empty()) 9365f757f3fSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + 9375f757f3fSDimitry Andric ParallelismOpt + Parallelism)); 9385f757f3fSDimitry Andric 9395f757f3fSDimitry Andric // Pass down GlobalISel options. 9405f757f3fSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel, 9415f757f3fSDimitry Andric options::OPT_fno_global_isel)) { 9425f757f3fSDimitry Andric // Parsing -fno-global-isel explicitly gives architectures that enable GISel 9435f757f3fSDimitry Andric // by default a chance to disable it. 9445f757f3fSDimitry Andric CmdArgs.push_back(Args.MakeArgString( 9455f757f3fSDimitry Andric Twine(PluginOptPrefix) + "-global-isel=" + 9465f757f3fSDimitry Andric (A->getOption().matches(options::OPT_fglobal_isel) ? "1" : "0"))); 9475f757f3fSDimitry Andric } 94881ad6265SDimitry Andric 9490b57cec5SDimitry Andric // If an explicit debugger tuning argument appeared, pass it along. 950bdd1243dSDimitry Andric if (Arg *A = 951bdd1243dSDimitry Andric Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) { 9520b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_glldb)) 953bdd1243dSDimitry Andric CmdArgs.push_back( 954bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=lldb")); 9550b57cec5SDimitry Andric else if (A->getOption().matches(options::OPT_gsce)) 956bdd1243dSDimitry Andric CmdArgs.push_back( 957bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=sce")); 958fe6060f1SDimitry Andric else if (A->getOption().matches(options::OPT_gdbx)) 959bdd1243dSDimitry Andric CmdArgs.push_back( 960bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=dbx")); 9610b57cec5SDimitry Andric else 962bdd1243dSDimitry Andric CmdArgs.push_back( 963bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=gdb")); 964bdd1243dSDimitry Andric } 965bdd1243dSDimitry Andric 966bdd1243dSDimitry Andric if (IsOSAIX) { 96706c3fb27SDimitry Andric if (!ToolChain.useIntegratedAs()) 96806c3fb27SDimitry Andric CmdArgs.push_back( 96906c3fb27SDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-no-integrated-as=1")); 97006c3fb27SDimitry Andric 971bdd1243dSDimitry Andric // On AIX, clang assumes strict-dwarf is true if any debug option is 972bdd1243dSDimitry Andric // specified, unless it is told explicitly not to assume so. 973bdd1243dSDimitry Andric Arg *A = Args.getLastArg(options::OPT_g_Group); 974bdd1243dSDimitry Andric bool EnableDebugInfo = A && !A->getOption().matches(options::OPT_g0) && 975bdd1243dSDimitry Andric !A->getOption().matches(options::OPT_ggdb0); 976bdd1243dSDimitry Andric if (EnableDebugInfo && Args.hasFlag(options::OPT_gstrict_dwarf, 977bdd1243dSDimitry Andric options::OPT_gno_strict_dwarf, true)) 978bdd1243dSDimitry Andric CmdArgs.push_back( 979bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-strict-dwarf=true")); 980bdd1243dSDimitry Andric 98106c3fb27SDimitry Andric for (const Arg *A : Args.filtered_reverse(options::OPT_mabi_EQ)) { 98206c3fb27SDimitry Andric StringRef V = A->getValue(); 98306c3fb27SDimitry Andric if (V == "vec-default") 98406c3fb27SDimitry Andric break; 98506c3fb27SDimitry Andric if (V == "vec-extabi") { 986bdd1243dSDimitry Andric CmdArgs.push_back( 987bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-vec-extabi")); 98806c3fb27SDimitry Andric break; 98906c3fb27SDimitry Andric } 99006c3fb27SDimitry Andric } 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric 9930b57cec5SDimitry Andric bool UseSeparateSections = 9940b57cec5SDimitry Andric isUseSeparateSections(ToolChain.getEffectiveTriple()); 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric if (Args.hasFlag(options::OPT_ffunction_sections, 997bdd1243dSDimitry Andric options::OPT_fno_function_sections, UseSeparateSections)) 998bdd1243dSDimitry Andric CmdArgs.push_back( 999bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-function-sections=1")); 1000bdd1243dSDimitry Andric else if (Args.hasArg(options::OPT_fno_function_sections)) 1001bdd1243dSDimitry Andric CmdArgs.push_back( 1002bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-function-sections=0")); 10030b57cec5SDimitry Andric 100406c3fb27SDimitry Andric bool DataSectionsTurnedOff = false; 10050b57cec5SDimitry Andric if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections, 100606c3fb27SDimitry Andric UseSeparateSections)) { 1007bdd1243dSDimitry Andric CmdArgs.push_back( 1008bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-data-sections=1")); 100906c3fb27SDimitry Andric } else if (Args.hasArg(options::OPT_fno_data_sections)) { 101006c3fb27SDimitry Andric DataSectionsTurnedOff = true; 1011bdd1243dSDimitry Andric CmdArgs.push_back( 1012bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-data-sections=0")); 101306c3fb27SDimitry Andric } 101406c3fb27SDimitry Andric 101506c3fb27SDimitry Andric if (Args.hasArg(options::OPT_mxcoff_roptr) || 101606c3fb27SDimitry Andric Args.hasArg(options::OPT_mno_xcoff_roptr)) { 101706c3fb27SDimitry Andric bool HasRoptr = Args.hasFlag(options::OPT_mxcoff_roptr, 101806c3fb27SDimitry Andric options::OPT_mno_xcoff_roptr, false); 101906c3fb27SDimitry Andric StringRef OptStr = HasRoptr ? "-mxcoff-roptr" : "-mno-xcoff-roptr"; 102006c3fb27SDimitry Andric if (!IsOSAIX) 102106c3fb27SDimitry Andric D.Diag(diag::err_drv_unsupported_opt_for_target) 1022*0fca6ea1SDimitry Andric << OptStr << Triple.str(); 102306c3fb27SDimitry Andric 102406c3fb27SDimitry Andric if (HasRoptr) { 102506c3fb27SDimitry Andric // The data sections option is on by default on AIX. We only need to error 102606c3fb27SDimitry Andric // out when -fno-data-sections is specified explicitly to turn off data 102706c3fb27SDimitry Andric // sections. 102806c3fb27SDimitry Andric if (DataSectionsTurnedOff) 102906c3fb27SDimitry Andric D.Diag(diag::err_roptr_requires_data_sections); 103006c3fb27SDimitry Andric 103106c3fb27SDimitry Andric CmdArgs.push_back( 103206c3fb27SDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-mxcoff-roptr")); 103306c3fb27SDimitry Andric } 103406c3fb27SDimitry Andric } 10350b57cec5SDimitry Andric 103681ad6265SDimitry Andric // Pass an option to enable split machine functions. 103781ad6265SDimitry Andric if (auto *A = Args.getLastArg(options::OPT_fsplit_machine_functions, 103881ad6265SDimitry Andric options::OPT_fno_split_machine_functions)) { 103981ad6265SDimitry Andric if (A->getOption().matches(options::OPT_fsplit_machine_functions)) 1040bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + 1041bdd1243dSDimitry Andric "-split-machine-functions")); 104281ad6265SDimitry Andric } 104381ad6265SDimitry Andric 10440b57cec5SDimitry Andric if (Arg *A = getLastProfileSampleUseArg(Args)) { 10450b57cec5SDimitry Andric StringRef FName = A->getValue(); 10460b57cec5SDimitry Andric if (!llvm::sys::fs::exists(FName)) 10475ffd83dbSDimitry Andric D.Diag(diag::err_drv_no_such_file) << FName; 10480b57cec5SDimitry Andric else 1049bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + 1050bdd1243dSDimitry Andric "sample-profile=" + FName)); 10510b57cec5SDimitry Andric } 10520b57cec5SDimitry Andric 105306c3fb27SDimitry Andric if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) { 1054bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + 1055bdd1243dSDimitry Andric "cs-profile-generate")); 10560b57cec5SDimitry Andric if (CSPGOGenerateArg->getOption().matches( 10570b57cec5SDimitry Andric options::OPT_fcs_profile_generate_EQ)) { 10580b57cec5SDimitry Andric SmallString<128> Path(CSPGOGenerateArg->getValue()); 10590b57cec5SDimitry Andric llvm::sys::path::append(Path, "default_%m.profraw"); 1060bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + 1061bdd1243dSDimitry Andric "cs-profile-path=" + Path)); 10620b57cec5SDimitry Andric } else 10630b57cec5SDimitry Andric CmdArgs.push_back( 1064bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + 1065bdd1243dSDimitry Andric "cs-profile-path=default_%m.profraw")); 106606c3fb27SDimitry Andric } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) { 10670b57cec5SDimitry Andric SmallString<128> Path( 10680b57cec5SDimitry Andric ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue()); 10690b57cec5SDimitry Andric if (Path.empty() || llvm::sys::fs::is_directory(Path)) 10700b57cec5SDimitry Andric llvm::sys::path::append(Path, "default.profdata"); 1071bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + 1072bdd1243dSDimitry Andric "cs-profile-path=" + Path)); 10730b57cec5SDimitry Andric } 10740b57cec5SDimitry Andric 1075bdd1243dSDimitry Andric // This controls whether or not we perform JustMyCode instrumentation. 1076bdd1243dSDimitry Andric if (Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false)) { 1077bdd1243dSDimitry Andric if (ToolChain.getEffectiveTriple().isOSBinFormatELF()) 1078bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + 1079bdd1243dSDimitry Andric "-enable-jmc-instrument")); 1080bdd1243dSDimitry Andric else 1081bdd1243dSDimitry Andric D.Diag(clang::diag::warn_drv_fjmc_for_elf_only); 1082bdd1243dSDimitry Andric } 1083bdd1243dSDimitry Andric 108406c3fb27SDimitry Andric if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls, 1085*0fca6ea1SDimitry Andric Triple.hasDefaultEmulatedTLS())) { 108606c3fb27SDimitry Andric CmdArgs.push_back( 108706c3fb27SDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-emulated-tls")); 1088cbe9438cSDimitry Andric } 1089b3edf446SDimitry Andric if (isTLSDESCEnabled(ToolChain, Args)) 1090b3edf446SDimitry Andric CmdArgs.push_back( 1091b3edf446SDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-enable-tlsdesc")); 1092cbe9438cSDimitry Andric 1093bdd1243dSDimitry Andric if (Args.hasFlag(options::OPT_fstack_size_section, 1094bdd1243dSDimitry Andric options::OPT_fno_stack_size_section, false)) 1095bdd1243dSDimitry Andric CmdArgs.push_back( 1096bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "-stack-size-section")); 1097bdd1243dSDimitry Andric 10980b57cec5SDimitry Andric // Setup statistics file output. 10995ffd83dbSDimitry Andric SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D); 11000b57cec5SDimitry Andric if (!StatsFile.empty()) 11010b57cec5SDimitry Andric CmdArgs.push_back( 1102bdd1243dSDimitry Andric Args.MakeArgString(Twine(PluginOptPrefix) + "stats-file=" + StatsFile)); 11035ffd83dbSDimitry Andric 1104bdd1243dSDimitry Andric // Setup crash diagnostics dir. 1105bdd1243dSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir)) 1106bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString( 1107bdd1243dSDimitry Andric Twine(PluginOptPrefix) + "-crash-diagnostics-dir=" + A->getValue())); 1108bdd1243dSDimitry Andric 1109bdd1243dSDimitry Andric addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/true, PluginOptPrefix); 1110e8d8bef9SDimitry Andric 1111e8d8bef9SDimitry Andric // Handle remark diagnostics on screen options: '-Rpass-*'. 1112bdd1243dSDimitry Andric renderRpassOptions(Args, CmdArgs, PluginOptPrefix); 1113e8d8bef9SDimitry Andric 1114e8d8bef9SDimitry Andric // Handle serialized remarks options: '-fsave-optimization-record' 1115e8d8bef9SDimitry Andric // and '-foptimization-record-*'. 1116e8d8bef9SDimitry Andric if (willEmitRemarks(Args)) 1117e8d8bef9SDimitry Andric renderRemarksOptions(Args, CmdArgs, ToolChain.getEffectiveTriple(), Input, 1118bdd1243dSDimitry Andric Output, PluginOptPrefix); 1119e8d8bef9SDimitry Andric 1120e8d8bef9SDimitry Andric // Handle remarks hotness/threshold related options. 1121bdd1243dSDimitry Andric renderRemarksHotnessOptions(Args, CmdArgs, PluginOptPrefix); 1122e8d8bef9SDimitry Andric 1123e8d8bef9SDimitry Andric addMachineOutlinerArgs(D, Args, CmdArgs, ToolChain.getEffectiveTriple(), 1124bdd1243dSDimitry Andric /*IsLTO=*/true, PluginOptPrefix); 1125*0fca6ea1SDimitry Andric 1126*0fca6ea1SDimitry Andric for (const Arg *A : Args.filtered(options::OPT_Wa_COMMA)) { 1127*0fca6ea1SDimitry Andric bool Crel = false; 1128*0fca6ea1SDimitry Andric for (StringRef V : A->getValues()) { 1129*0fca6ea1SDimitry Andric if (V == "--crel") 1130*0fca6ea1SDimitry Andric Crel = true; 1131*0fca6ea1SDimitry Andric else if (V == "--no-crel") 1132*0fca6ea1SDimitry Andric Crel = false; 1133*0fca6ea1SDimitry Andric else 1134*0fca6ea1SDimitry Andric continue; 1135*0fca6ea1SDimitry Andric A->claim(); 1136*0fca6ea1SDimitry Andric } 1137*0fca6ea1SDimitry Andric if (Crel) { 1138*0fca6ea1SDimitry Andric if (Triple.isOSBinFormatELF() && !Triple.isMIPS()) { 1139*0fca6ea1SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + "-crel")); 1140*0fca6ea1SDimitry Andric } else { 1141*0fca6ea1SDimitry Andric D.Diag(diag::err_drv_unsupported_opt_for_target) 1142*0fca6ea1SDimitry Andric << "-Wa,--crel" << D.getTargetTriple(); 1143*0fca6ea1SDimitry Andric } 1144*0fca6ea1SDimitry Andric } 1145*0fca6ea1SDimitry Andric } 11460b57cec5SDimitry Andric } 11470b57cec5SDimitry Andric 11485f757f3fSDimitry Andric /// Adds the '-lcgpu' and '-lmgpu' libraries to the compilation to include the 11495f757f3fSDimitry Andric /// LLVM C library for GPUs. 1150*0fca6ea1SDimitry Andric static void addOpenMPDeviceLibC(const Compilation &C, const ArgList &Args, 11515f757f3fSDimitry Andric ArgStringList &CmdArgs) { 11525f757f3fSDimitry Andric if (Args.hasArg(options::OPT_nogpulib) || Args.hasArg(options::OPT_nolibc)) 11535f757f3fSDimitry Andric return; 11545f757f3fSDimitry Andric 11555f757f3fSDimitry Andric // Check the resource directory for the LLVM libc GPU declarations. If it's 11565f757f3fSDimitry Andric // found we can assume that LLVM was built with support for the GPU libc. 1157*0fca6ea1SDimitry Andric SmallString<256> LibCDecls(C.getDriver().ResourceDir); 11585f757f3fSDimitry Andric llvm::sys::path::append(LibCDecls, "include", "llvm_libc_wrappers", 11595f757f3fSDimitry Andric "llvm-libc-decls"); 11605f757f3fSDimitry Andric bool HasLibC = llvm::sys::fs::exists(LibCDecls) && 11615f757f3fSDimitry Andric llvm::sys::fs::is_directory(LibCDecls); 1162*0fca6ea1SDimitry Andric if (!Args.hasFlag(options::OPT_gpulibc, options::OPT_nogpulibc, HasLibC)) 1163*0fca6ea1SDimitry Andric return; 1164*0fca6ea1SDimitry Andric 1165*0fca6ea1SDimitry Andric SmallVector<const ToolChain *> ToolChains; 1166*0fca6ea1SDimitry Andric auto TCRange = C.getOffloadToolChains(Action::OFK_OpenMP); 1167*0fca6ea1SDimitry Andric for (auto TI = TCRange.first, TE = TCRange.second; TI != TE; ++TI) 1168*0fca6ea1SDimitry Andric ToolChains.push_back(TI->second); 1169*0fca6ea1SDimitry Andric 1170*0fca6ea1SDimitry Andric if (llvm::any_of(ToolChains, [](const ToolChain *TC) { 1171*0fca6ea1SDimitry Andric return TC->getTriple().isAMDGPU(); 1172*0fca6ea1SDimitry Andric })) { 1173*0fca6ea1SDimitry Andric CmdArgs.push_back("-lcgpu-amdgpu"); 1174*0fca6ea1SDimitry Andric CmdArgs.push_back("-lmgpu-amdgpu"); 1175*0fca6ea1SDimitry Andric } 1176*0fca6ea1SDimitry Andric if (llvm::any_of(ToolChains, [](const ToolChain *TC) { 1177*0fca6ea1SDimitry Andric return TC->getTriple().isNVPTX(); 1178*0fca6ea1SDimitry Andric })) { 1179*0fca6ea1SDimitry Andric CmdArgs.push_back("-lcgpu-nvptx"); 1180*0fca6ea1SDimitry Andric CmdArgs.push_back("-lmgpu-nvptx"); 11815f757f3fSDimitry Andric } 11825f757f3fSDimitry Andric } 11835f757f3fSDimitry Andric 11842a66634dSDimitry Andric void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC, 11852a66634dSDimitry Andric const ArgList &Args, 11862a66634dSDimitry Andric ArgStringList &CmdArgs) { 11872a66634dSDimitry Andric // Default to clang lib / lib64 folder, i.e. the same location as device 11882a66634dSDimitry Andric // runtime. 11892a66634dSDimitry Andric SmallString<256> DefaultLibPath = 11902a66634dSDimitry Andric llvm::sys::path::parent_path(TC.getDriver().Dir); 1191bdd1243dSDimitry Andric llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME); 11922a66634dSDimitry Andric CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath)); 11932a66634dSDimitry Andric } 11942a66634dSDimitry Andric 11950b57cec5SDimitry Andric void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, 11960b57cec5SDimitry Andric ArgStringList &CmdArgs) { 11970b57cec5SDimitry Andric if (!Args.hasFlag(options::OPT_frtlib_add_rpath, 11985f757f3fSDimitry Andric options::OPT_fno_rtlib_add_rpath, false)) 11990b57cec5SDimitry Andric return; 12000b57cec5SDimitry Andric 1201*0fca6ea1SDimitry Andric SmallVector<std::string> CandidateRPaths(TC.getArchSpecificLibPaths()); 1202*0fca6ea1SDimitry Andric if (const auto CandidateRPath = TC.getStdlibPath()) 1203*0fca6ea1SDimitry Andric CandidateRPaths.emplace_back(*CandidateRPath); 1204*0fca6ea1SDimitry Andric 1205*0fca6ea1SDimitry Andric for (const auto &CandidateRPath : CandidateRPaths) { 12060b57cec5SDimitry Andric if (TC.getVFS().exists(CandidateRPath)) { 12070b57cec5SDimitry Andric CmdArgs.push_back("-rpath"); 1208349cc55cSDimitry Andric CmdArgs.push_back(Args.MakeArgString(CandidateRPath)); 12090b57cec5SDimitry Andric } 12100b57cec5SDimitry Andric } 121106c3fb27SDimitry Andric } 12120b57cec5SDimitry Andric 1213*0fca6ea1SDimitry Andric bool tools::addOpenMPRuntime(const Compilation &C, ArgStringList &CmdArgs, 1214*0fca6ea1SDimitry Andric const ToolChain &TC, const ArgList &Args, 1215*0fca6ea1SDimitry Andric bool ForceStaticHostRuntime, bool IsOffloadingHost, 1216*0fca6ea1SDimitry Andric bool GompNeedsRT) { 12170b57cec5SDimitry Andric if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 12180b57cec5SDimitry Andric options::OPT_fno_openmp, false)) 12190b57cec5SDimitry Andric return false; 12200b57cec5SDimitry Andric 1221a7dea167SDimitry Andric Driver::OpenMPRuntimeKind RTKind = TC.getDriver().getOpenMPRuntime(Args); 1222a7dea167SDimitry Andric 1223a7dea167SDimitry Andric if (RTKind == Driver::OMPRT_Unknown) 1224a7dea167SDimitry Andric // Already diagnosed. 1225a7dea167SDimitry Andric return false; 1226a7dea167SDimitry Andric 1227a7dea167SDimitry Andric if (ForceStaticHostRuntime) 1228a7dea167SDimitry Andric CmdArgs.push_back("-Bstatic"); 1229a7dea167SDimitry Andric 1230a7dea167SDimitry Andric switch (RTKind) { 12310b57cec5SDimitry Andric case Driver::OMPRT_OMP: 12320b57cec5SDimitry Andric CmdArgs.push_back("-lomp"); 12330b57cec5SDimitry Andric break; 12340b57cec5SDimitry Andric case Driver::OMPRT_GOMP: 12350b57cec5SDimitry Andric CmdArgs.push_back("-lgomp"); 12360b57cec5SDimitry Andric break; 12370b57cec5SDimitry Andric case Driver::OMPRT_IOMP5: 12380b57cec5SDimitry Andric CmdArgs.push_back("-liomp5"); 12390b57cec5SDimitry Andric break; 12400b57cec5SDimitry Andric case Driver::OMPRT_Unknown: 1241a7dea167SDimitry Andric break; 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric 1244a7dea167SDimitry Andric if (ForceStaticHostRuntime) 1245a7dea167SDimitry Andric CmdArgs.push_back("-Bdynamic"); 1246a7dea167SDimitry Andric 1247a7dea167SDimitry Andric if (RTKind == Driver::OMPRT_GOMP && GompNeedsRT) 1248a7dea167SDimitry Andric CmdArgs.push_back("-lrt"); 1249a7dea167SDimitry Andric 12500b57cec5SDimitry Andric if (IsOffloadingHost) 12510b57cec5SDimitry Andric CmdArgs.push_back("-lomptarget"); 12520b57cec5SDimitry Andric 1253bdd1243dSDimitry Andric if (IsOffloadingHost && !Args.hasArg(options::OPT_nogpulib)) 125481ad6265SDimitry Andric CmdArgs.push_back("-lomptarget.devicertl"); 125581ad6265SDimitry Andric 12565f757f3fSDimitry Andric if (IsOffloadingHost) 1257*0fca6ea1SDimitry Andric addOpenMPDeviceLibC(C, Args, CmdArgs); 12585f757f3fSDimitry Andric 12590b57cec5SDimitry Andric addArchSpecificRPath(TC, Args, CmdArgs); 12602a66634dSDimitry Andric addOpenMPRuntimeLibraryPath(TC, Args, CmdArgs); 12611fd87a68SDimitry Andric 12620b57cec5SDimitry Andric return true; 12630b57cec5SDimitry Andric } 12640b57cec5SDimitry Andric 12655f757f3fSDimitry Andric /// Add Fortran runtime libs 12665f757f3fSDimitry Andric void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args, 12675f757f3fSDimitry Andric llvm::opt::ArgStringList &CmdArgs) { 1268*0fca6ea1SDimitry Andric // Link FortranRuntime and FortranDecimal 12695f757f3fSDimitry Andric // These are handled earlier on Windows by telling the frontend driver to 12705f757f3fSDimitry Andric // add the correct libraries to link against as dependents in the object 12715f757f3fSDimitry Andric // file. 12725f757f3fSDimitry Andric if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) { 1273*0fca6ea1SDimitry Andric StringRef F128LibName = TC.getDriver().getFlangF128MathLibrary(); 1274*0fca6ea1SDimitry Andric F128LibName.consume_front_insensitive("lib"); 1275*0fca6ea1SDimitry Andric if (!F128LibName.empty()) { 1276*0fca6ea1SDimitry Andric bool AsNeeded = !TC.getTriple().isOSAIX(); 1277*0fca6ea1SDimitry Andric CmdArgs.push_back("-lFortranFloat128Math"); 1278*0fca6ea1SDimitry Andric if (AsNeeded) 1279*0fca6ea1SDimitry Andric addAsNeededOption(TC, Args, CmdArgs, /*as_needed=*/true); 1280*0fca6ea1SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-l" + F128LibName)); 1281*0fca6ea1SDimitry Andric if (AsNeeded) 1282*0fca6ea1SDimitry Andric addAsNeededOption(TC, Args, CmdArgs, /*as_needed=*/false); 1283*0fca6ea1SDimitry Andric } 128481ad6265SDimitry Andric CmdArgs.push_back("-lFortranRuntime"); 128581ad6265SDimitry Andric CmdArgs.push_back("-lFortranDecimal"); 128681ad6265SDimitry Andric } 128781ad6265SDimitry Andric } 128881ad6265SDimitry Andric 128981ad6265SDimitry Andric void tools::addFortranRuntimeLibraryPath(const ToolChain &TC, 129081ad6265SDimitry Andric const llvm::opt::ArgList &Args, 129181ad6265SDimitry Andric ArgStringList &CmdArgs) { 129281ad6265SDimitry Andric // Default to the <driver-path>/../lib directory. This works fine on the 129381ad6265SDimitry Andric // platforms that we have tested so far. We will probably have to re-fine 129481ad6265SDimitry Andric // this in the future. In particular, on some platforms, we may need to use 129581ad6265SDimitry Andric // lib64 instead of lib. 129681ad6265SDimitry Andric SmallString<256> DefaultLibPath = 129781ad6265SDimitry Andric llvm::sys::path::parent_path(TC.getDriver().Dir); 129881ad6265SDimitry Andric llvm::sys::path::append(DefaultLibPath, "lib"); 129981ad6265SDimitry Andric if (TC.getTriple().isKnownWindowsMSVCEnvironment()) 130081ad6265SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath)); 130181ad6265SDimitry Andric else 130281ad6265SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath)); 130381ad6265SDimitry Andric } 130481ad6265SDimitry Andric 13050b57cec5SDimitry Andric static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args, 13060b57cec5SDimitry Andric ArgStringList &CmdArgs, StringRef Sanitizer, 13070b57cec5SDimitry Andric bool IsShared, bool IsWhole) { 13080b57cec5SDimitry Andric // Wrap any static runtimes that must be forced into executable in 13090b57cec5SDimitry Andric // whole-archive. 13100b57cec5SDimitry Andric if (IsWhole) CmdArgs.push_back("--whole-archive"); 13110b57cec5SDimitry Andric CmdArgs.push_back(TC.getCompilerRTArgString( 13120b57cec5SDimitry Andric Args, Sanitizer, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static)); 13130b57cec5SDimitry Andric if (IsWhole) CmdArgs.push_back("--no-whole-archive"); 13140b57cec5SDimitry Andric 13150b57cec5SDimitry Andric if (IsShared) { 13160b57cec5SDimitry Andric addArchSpecificRPath(TC, Args, CmdArgs); 13170b57cec5SDimitry Andric } 13180b57cec5SDimitry Andric } 13190b57cec5SDimitry Andric 13200b57cec5SDimitry Andric // Tries to use a file with the list of dynamic symbols that need to be exported 13210b57cec5SDimitry Andric // from the runtime library. Returns true if the file was found. 13220b57cec5SDimitry Andric static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args, 13230b57cec5SDimitry Andric ArgStringList &CmdArgs, 13240b57cec5SDimitry Andric StringRef Sanitizer) { 13255f757f3fSDimitry Andric bool LinkerIsGnuLd = solaris::isLinkerGnuLd(TC, Args); 13265f757f3fSDimitry Andric 13270b57cec5SDimitry Andric // Solaris ld defaults to --export-dynamic behaviour but doesn't support 13280b57cec5SDimitry Andric // the option, so don't try to pass it. 13295f757f3fSDimitry Andric if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd) 13300b57cec5SDimitry Andric return true; 13310b57cec5SDimitry Andric SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer)); 13320b57cec5SDimitry Andric if (llvm::sys::fs::exists(SanRT + ".syms")) { 13330b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms")); 13340b57cec5SDimitry Andric return true; 13350b57cec5SDimitry Andric } 13360b57cec5SDimitry Andric return false; 13370b57cec5SDimitry Andric } 13380b57cec5SDimitry Andric 13395f757f3fSDimitry Andric void tools::addAsNeededOption(const ToolChain &TC, 13405f757f3fSDimitry Andric const llvm::opt::ArgList &Args, 13415f757f3fSDimitry Andric llvm::opt::ArgStringList &CmdArgs, 13425f757f3fSDimitry Andric bool as_needed) { 1343fe6060f1SDimitry Andric assert(!TC.getTriple().isOSAIX() && 1344fe6060f1SDimitry Andric "AIX linker does not support any form of --as-needed option yet."); 13455f757f3fSDimitry Andric bool LinkerIsGnuLd = solaris::isLinkerGnuLd(TC, Args); 1346fe6060f1SDimitry Andric 1347e8d8bef9SDimitry Andric // While the Solaris 11.2 ld added --as-needed/--no-as-needed as aliases 1348e8d8bef9SDimitry Andric // for the native forms -z ignore/-z record, they are missing in Illumos, 1349e8d8bef9SDimitry Andric // so always use the native form. 13505f757f3fSDimitry Andric // GNU ld doesn't support -z ignore/-z record, so don't use them even on 13515f757f3fSDimitry Andric // Solaris. 13525f757f3fSDimitry Andric if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd) { 13535f757f3fSDimitry Andric CmdArgs.push_back("-z"); 13545f757f3fSDimitry Andric CmdArgs.push_back(as_needed ? "ignore" : "record"); 13555f757f3fSDimitry Andric } else { 13565f757f3fSDimitry Andric CmdArgs.push_back(as_needed ? "--as-needed" : "--no-as-needed"); 13575f757f3fSDimitry Andric } 1358e8d8bef9SDimitry Andric } 1359e8d8bef9SDimitry Andric 13600b57cec5SDimitry Andric void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, 13615f757f3fSDimitry Andric const llvm::opt::ArgList &Args, 13620b57cec5SDimitry Andric ArgStringList &CmdArgs) { 13630b57cec5SDimitry Andric // Force linking against the system libraries sanitizers depends on 13640b57cec5SDimitry Andric // (see PR15823 why this is necessary). 13655f757f3fSDimitry Andric addAsNeededOption(TC, Args, CmdArgs, false); 13660b57cec5SDimitry Andric // There's no libpthread or librt on RTEMS & Android. 13670b57cec5SDimitry Andric if (TC.getTriple().getOS() != llvm::Triple::RTEMS && 136806c3fb27SDimitry Andric !TC.getTriple().isAndroid() && !TC.getTriple().isOHOSFamily()) { 13690b57cec5SDimitry Andric CmdArgs.push_back("-lpthread"); 13700b57cec5SDimitry Andric if (!TC.getTriple().isOSOpenBSD()) 13710b57cec5SDimitry Andric CmdArgs.push_back("-lrt"); 13720b57cec5SDimitry Andric } 13730b57cec5SDimitry Andric CmdArgs.push_back("-lm"); 13740b57cec5SDimitry Andric // There's no libdl on all OSes. 1375fe6060f1SDimitry Andric if (!TC.getTriple().isOSFreeBSD() && !TC.getTriple().isOSNetBSD() && 13760b57cec5SDimitry Andric !TC.getTriple().isOSOpenBSD() && 13770b57cec5SDimitry Andric TC.getTriple().getOS() != llvm::Triple::RTEMS) 13780b57cec5SDimitry Andric CmdArgs.push_back("-ldl"); 13790b57cec5SDimitry Andric // Required for backtrace on some OSes 13800b57cec5SDimitry Andric if (TC.getTriple().isOSFreeBSD() || 138169ade1e0SDimitry Andric TC.getTriple().isOSNetBSD() || 138269ade1e0SDimitry Andric TC.getTriple().isOSOpenBSD()) 13830b57cec5SDimitry Andric CmdArgs.push_back("-lexecinfo"); 138481ad6265SDimitry Andric // There is no libresolv on Android, FreeBSD, OpenBSD, etc. On musl 138581ad6265SDimitry Andric // libresolv.a, even if exists, is an empty archive to satisfy POSIX -lresolv 138681ad6265SDimitry Andric // requirement. 138781ad6265SDimitry Andric if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() && 138881ad6265SDimitry Andric !TC.getTriple().isMusl()) 138981ad6265SDimitry Andric CmdArgs.push_back("-lresolv"); 13900b57cec5SDimitry Andric } 13910b57cec5SDimitry Andric 13920b57cec5SDimitry Andric static void 13930b57cec5SDimitry Andric collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, 13940b57cec5SDimitry Andric SmallVectorImpl<StringRef> &SharedRuntimes, 13950b57cec5SDimitry Andric SmallVectorImpl<StringRef> &StaticRuntimes, 13960b57cec5SDimitry Andric SmallVectorImpl<StringRef> &NonWholeStaticRuntimes, 13970b57cec5SDimitry Andric SmallVectorImpl<StringRef> &HelperStaticRuntimes, 13980b57cec5SDimitry Andric SmallVectorImpl<StringRef> &RequiredSymbols) { 1399349cc55cSDimitry Andric const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args); 14000b57cec5SDimitry Andric // Collect shared runtimes. 14010b57cec5SDimitry Andric if (SanArgs.needsSharedRt()) { 1402cb14a3feSDimitry Andric if (SanArgs.needsAsanRt()) { 14030b57cec5SDimitry Andric SharedRuntimes.push_back("asan"); 14040b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid()) 14050b57cec5SDimitry Andric HelperStaticRuntimes.push_back("asan-preinit"); 14060b57cec5SDimitry Andric } 1407cb14a3feSDimitry Andric if (SanArgs.needsMemProfRt()) { 1408e8d8bef9SDimitry Andric SharedRuntimes.push_back("memprof"); 1409e8d8bef9SDimitry Andric if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid()) 1410e8d8bef9SDimitry Andric HelperStaticRuntimes.push_back("memprof-preinit"); 1411e8d8bef9SDimitry Andric } 1412*0fca6ea1SDimitry Andric if (SanArgs.needsNsanRt()) 1413*0fca6ea1SDimitry Andric SharedRuntimes.push_back("nsan"); 1414cb14a3feSDimitry Andric if (SanArgs.needsUbsanRt()) { 14150b57cec5SDimitry Andric if (SanArgs.requiresMinimalRuntime()) 14160b57cec5SDimitry Andric SharedRuntimes.push_back("ubsan_minimal"); 14170b57cec5SDimitry Andric else 14180b57cec5SDimitry Andric SharedRuntimes.push_back("ubsan_standalone"); 14190b57cec5SDimitry Andric } 1420cb14a3feSDimitry Andric if (SanArgs.needsScudoRt()) { 1421bdd1243dSDimitry Andric SharedRuntimes.push_back("scudo_standalone"); 14220b57cec5SDimitry Andric } 1423cb14a3feSDimitry Andric if (SanArgs.needsTsanRt()) 1424e8d8bef9SDimitry Andric SharedRuntimes.push_back("tsan"); 1425cb14a3feSDimitry Andric if (SanArgs.needsHwasanRt()) { 1426fe6060f1SDimitry Andric if (SanArgs.needsHwasanAliasesRt()) 1427fe6060f1SDimitry Andric SharedRuntimes.push_back("hwasan_aliases"); 1428fe6060f1SDimitry Andric else 14290b57cec5SDimitry Andric SharedRuntimes.push_back("hwasan"); 143081ad6265SDimitry Andric if (!Args.hasArg(options::OPT_shared)) 143181ad6265SDimitry Andric HelperStaticRuntimes.push_back("hwasan-preinit"); 14320b57cec5SDimitry Andric } 1433fe6060f1SDimitry Andric } 14340b57cec5SDimitry Andric 14350b57cec5SDimitry Andric // The stats_client library is also statically linked into DSOs. 1436cb14a3feSDimitry Andric if (SanArgs.needsStatsRt()) 14370b57cec5SDimitry Andric StaticRuntimes.push_back("stats_client"); 14380b57cec5SDimitry Andric 14391fd87a68SDimitry Andric // Always link the static runtime regardless of DSO or executable. 14401fd87a68SDimitry Andric if (SanArgs.needsAsanRt()) 14411fd87a68SDimitry Andric HelperStaticRuntimes.push_back("asan_static"); 14421fd87a68SDimitry Andric 14430b57cec5SDimitry Andric // Collect static runtimes. 14445ffd83dbSDimitry Andric if (Args.hasArg(options::OPT_shared)) { 14455ffd83dbSDimitry Andric // Don't link static runtimes into DSOs. 14460b57cec5SDimitry Andric return; 14470b57cec5SDimitry Andric } 14485ffd83dbSDimitry Andric 14495ffd83dbSDimitry Andric // Each static runtime that has a DSO counterpart above is excluded below, 14505ffd83dbSDimitry Andric // but runtimes that exist only as static are not affected by needsSharedRt. 14515ffd83dbSDimitry Andric 1452cb14a3feSDimitry Andric if (!SanArgs.needsSharedRt() && SanArgs.needsAsanRt()) { 14530b57cec5SDimitry Andric StaticRuntimes.push_back("asan"); 14540b57cec5SDimitry Andric if (SanArgs.linkCXXRuntimes()) 14550b57cec5SDimitry Andric StaticRuntimes.push_back("asan_cxx"); 14560b57cec5SDimitry Andric } 14570b57cec5SDimitry Andric 1458cb14a3feSDimitry Andric if (!SanArgs.needsSharedRt() && SanArgs.needsMemProfRt()) { 1459e8d8bef9SDimitry Andric StaticRuntimes.push_back("memprof"); 1460e8d8bef9SDimitry Andric if (SanArgs.linkCXXRuntimes()) 1461e8d8bef9SDimitry Andric StaticRuntimes.push_back("memprof_cxx"); 1462e8d8bef9SDimitry Andric } 1463e8d8bef9SDimitry Andric 1464cb14a3feSDimitry Andric if (!SanArgs.needsSharedRt() && SanArgs.needsHwasanRt()) { 1465fe6060f1SDimitry Andric if (SanArgs.needsHwasanAliasesRt()) { 1466fe6060f1SDimitry Andric StaticRuntimes.push_back("hwasan_aliases"); 1467fe6060f1SDimitry Andric if (SanArgs.linkCXXRuntimes()) 1468fe6060f1SDimitry Andric StaticRuntimes.push_back("hwasan_aliases_cxx"); 1469fe6060f1SDimitry Andric } else { 14700b57cec5SDimitry Andric StaticRuntimes.push_back("hwasan"); 14710b57cec5SDimitry Andric if (SanArgs.linkCXXRuntimes()) 14720b57cec5SDimitry Andric StaticRuntimes.push_back("hwasan_cxx"); 14730b57cec5SDimitry Andric } 1474fe6060f1SDimitry Andric } 1475cb14a3feSDimitry Andric if (SanArgs.needsDfsanRt()) 14760b57cec5SDimitry Andric StaticRuntimes.push_back("dfsan"); 1477cb14a3feSDimitry Andric if (SanArgs.needsLsanRt()) 14780b57cec5SDimitry Andric StaticRuntimes.push_back("lsan"); 1479cb14a3feSDimitry Andric if (SanArgs.needsMsanRt()) { 14800b57cec5SDimitry Andric StaticRuntimes.push_back("msan"); 14810b57cec5SDimitry Andric if (SanArgs.linkCXXRuntimes()) 14820b57cec5SDimitry Andric StaticRuntimes.push_back("msan_cxx"); 14830b57cec5SDimitry Andric } 1484*0fca6ea1SDimitry Andric if (!SanArgs.needsSharedRt() && SanArgs.needsNsanRt()) 1485*0fca6ea1SDimitry Andric StaticRuntimes.push_back("nsan"); 1486cb14a3feSDimitry Andric if (!SanArgs.needsSharedRt() && SanArgs.needsTsanRt()) { 14870b57cec5SDimitry Andric StaticRuntimes.push_back("tsan"); 14880b57cec5SDimitry Andric if (SanArgs.linkCXXRuntimes()) 14890b57cec5SDimitry Andric StaticRuntimes.push_back("tsan_cxx"); 14900b57cec5SDimitry Andric } 1491cb14a3feSDimitry Andric if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt()) { 14920b57cec5SDimitry Andric if (SanArgs.requiresMinimalRuntime()) { 14930b57cec5SDimitry Andric StaticRuntimes.push_back("ubsan_minimal"); 14940b57cec5SDimitry Andric } else { 14950b57cec5SDimitry Andric StaticRuntimes.push_back("ubsan_standalone"); 14960b57cec5SDimitry Andric if (SanArgs.linkCXXRuntimes()) 14970b57cec5SDimitry Andric StaticRuntimes.push_back("ubsan_standalone_cxx"); 14980b57cec5SDimitry Andric } 14990b57cec5SDimitry Andric } 1500cb14a3feSDimitry Andric if (SanArgs.needsSafeStackRt()) { 15010b57cec5SDimitry Andric NonWholeStaticRuntimes.push_back("safestack"); 15020b57cec5SDimitry Andric RequiredSymbols.push_back("__safestack_init"); 15030b57cec5SDimitry Andric } 1504cb14a3feSDimitry Andric if (!(SanArgs.needsSharedRt() && SanArgs.needsUbsanRt())) { 1505cb14a3feSDimitry Andric if (SanArgs.needsCfiRt()) 15060b57cec5SDimitry Andric StaticRuntimes.push_back("cfi"); 1507cb14a3feSDimitry Andric if (SanArgs.needsCfiDiagRt()) { 15080b57cec5SDimitry Andric StaticRuntimes.push_back("cfi_diag"); 15090b57cec5SDimitry Andric if (SanArgs.linkCXXRuntimes()) 15100b57cec5SDimitry Andric StaticRuntimes.push_back("ubsan_standalone_cxx"); 15110b57cec5SDimitry Andric } 15125ffd83dbSDimitry Andric } 1513cb14a3feSDimitry Andric if (SanArgs.needsStatsRt()) { 15140b57cec5SDimitry Andric NonWholeStaticRuntimes.push_back("stats"); 15150b57cec5SDimitry Andric RequiredSymbols.push_back("__sanitizer_stats_register"); 15160b57cec5SDimitry Andric } 1517cb14a3feSDimitry Andric if (!SanArgs.needsSharedRt() && SanArgs.needsScudoRt()) { 1518bdd1243dSDimitry Andric StaticRuntimes.push_back("scudo_standalone"); 15190b57cec5SDimitry Andric if (SanArgs.linkCXXRuntimes()) 1520bdd1243dSDimitry Andric StaticRuntimes.push_back("scudo_standalone_cxx"); 15210b57cec5SDimitry Andric } 15220b57cec5SDimitry Andric } 15230b57cec5SDimitry Andric 15240b57cec5SDimitry Andric // Should be called before we add system libraries (C++ ABI, libstdc++/libc++, 15250b57cec5SDimitry Andric // C runtime, etc). Returns true if sanitizer system deps need to be linked in. 15260b57cec5SDimitry Andric bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, 15270b57cec5SDimitry Andric ArgStringList &CmdArgs) { 1528cb14a3feSDimitry Andric const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args); 15290b57cec5SDimitry Andric SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes, 15300b57cec5SDimitry Andric NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols; 1531cb14a3feSDimitry Andric if (SanArgs.linkRuntimes()) { 15320b57cec5SDimitry Andric collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes, 15330b57cec5SDimitry Andric NonWholeStaticRuntimes, HelperStaticRuntimes, 15340b57cec5SDimitry Andric RequiredSymbols); 1535cb14a3feSDimitry Andric } 15360b57cec5SDimitry Andric 1537*0fca6ea1SDimitry Andric // -u options must be added before the runtime libs that resolve them. 1538*0fca6ea1SDimitry Andric for (auto S : RequiredSymbols) { 1539*0fca6ea1SDimitry Andric CmdArgs.push_back("-u"); 1540*0fca6ea1SDimitry Andric CmdArgs.push_back(Args.MakeArgString(S)); 1541*0fca6ea1SDimitry Andric } 1542*0fca6ea1SDimitry Andric 15430b57cec5SDimitry Andric // Inject libfuzzer dependencies. 1544a7dea167SDimitry Andric if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() && 1545a7dea167SDimitry Andric !Args.hasArg(options::OPT_shared)) { 15460b57cec5SDimitry Andric 15470b57cec5SDimitry Andric addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true); 1548e8d8bef9SDimitry Andric if (SanArgs.needsFuzzerInterceptors()) 1549e8d8bef9SDimitry Andric addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer_interceptors", false, 1550e8d8bef9SDimitry Andric true); 1551e8d8bef9SDimitry Andric if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx)) { 1552e8d8bef9SDimitry Andric bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && 1553e8d8bef9SDimitry Andric !Args.hasArg(options::OPT_static); 1554e8d8bef9SDimitry Andric if (OnlyLibstdcxxStatic) 1555e8d8bef9SDimitry Andric CmdArgs.push_back("-Bstatic"); 15560b57cec5SDimitry Andric TC.AddCXXStdlibLibArgs(Args, CmdArgs); 1557e8d8bef9SDimitry Andric if (OnlyLibstdcxxStatic) 1558e8d8bef9SDimitry Andric CmdArgs.push_back("-Bdynamic"); 1559e8d8bef9SDimitry Andric } 15600b57cec5SDimitry Andric } 15610b57cec5SDimitry Andric 15620b57cec5SDimitry Andric for (auto RT : SharedRuntimes) 15630b57cec5SDimitry Andric addSanitizerRuntime(TC, Args, CmdArgs, RT, true, false); 15640b57cec5SDimitry Andric for (auto RT : HelperStaticRuntimes) 15650b57cec5SDimitry Andric addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true); 15660b57cec5SDimitry Andric bool AddExportDynamic = false; 15670b57cec5SDimitry Andric for (auto RT : StaticRuntimes) { 15680b57cec5SDimitry Andric addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true); 15690b57cec5SDimitry Andric AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT); 15700b57cec5SDimitry Andric } 15710b57cec5SDimitry Andric for (auto RT : NonWholeStaticRuntimes) { 15720b57cec5SDimitry Andric addSanitizerRuntime(TC, Args, CmdArgs, RT, false, false); 15730b57cec5SDimitry Andric AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT); 15740b57cec5SDimitry Andric } 15750b57cec5SDimitry Andric // If there is a static runtime with no dynamic list, force all the symbols 15760b57cec5SDimitry Andric // to be dynamic to be sure we export sanitizer interface functions. 15770b57cec5SDimitry Andric if (AddExportDynamic) 15780b57cec5SDimitry Andric CmdArgs.push_back("--export-dynamic"); 15790b57cec5SDimitry Andric 15800b57cec5SDimitry Andric if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic) 15815ffd83dbSDimitry Andric CmdArgs.push_back("--export-dynamic-symbol=__cfi_check"); 15820b57cec5SDimitry Andric 158381ad6265SDimitry Andric if (SanArgs.hasMemTag()) { 158481ad6265SDimitry Andric if (!TC.getTriple().isAndroid()) { 158581ad6265SDimitry Andric TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) 158681ad6265SDimitry Andric << "-fsanitize=memtag*" << TC.getTriple().str(); 158781ad6265SDimitry Andric } 158881ad6265SDimitry Andric CmdArgs.push_back( 158981ad6265SDimitry Andric Args.MakeArgString("--android-memtag-mode=" + SanArgs.getMemtagMode())); 159081ad6265SDimitry Andric if (SanArgs.hasMemtagHeap()) 159181ad6265SDimitry Andric CmdArgs.push_back("--android-memtag-heap"); 159281ad6265SDimitry Andric if (SanArgs.hasMemtagStack()) 159381ad6265SDimitry Andric CmdArgs.push_back("--android-memtag-stack"); 159481ad6265SDimitry Andric } 159581ad6265SDimitry Andric 15960b57cec5SDimitry Andric return !StaticRuntimes.empty() || !NonWholeStaticRuntimes.empty(); 15970b57cec5SDimitry Andric } 15980b57cec5SDimitry Andric 15990b57cec5SDimitry Andric bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringList &CmdArgs) { 16000b57cec5SDimitry Andric if (Args.hasArg(options::OPT_shared)) 16010b57cec5SDimitry Andric return false; 16020b57cec5SDimitry Andric 16030b57cec5SDimitry Andric if (TC.getXRayArgs().needsXRayRt()) { 160406c3fb27SDimitry Andric CmdArgs.push_back("--whole-archive"); 16050b57cec5SDimitry Andric CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray")); 16060b57cec5SDimitry Andric for (const auto &Mode : TC.getXRayArgs().modeList()) 16070b57cec5SDimitry Andric CmdArgs.push_back(TC.getCompilerRTArgString(Args, Mode)); 160806c3fb27SDimitry Andric CmdArgs.push_back("--no-whole-archive"); 16090b57cec5SDimitry Andric return true; 16100b57cec5SDimitry Andric } 16110b57cec5SDimitry Andric 16120b57cec5SDimitry Andric return false; 16130b57cec5SDimitry Andric } 16140b57cec5SDimitry Andric 16155f757f3fSDimitry Andric void tools::linkXRayRuntimeDeps(const ToolChain &TC, 16165f757f3fSDimitry Andric const llvm::opt::ArgList &Args, 16175f757f3fSDimitry Andric ArgStringList &CmdArgs) { 16185f757f3fSDimitry Andric addAsNeededOption(TC, Args, CmdArgs, false); 16190b57cec5SDimitry Andric CmdArgs.push_back("-lpthread"); 16200b57cec5SDimitry Andric if (!TC.getTriple().isOSOpenBSD()) 16210b57cec5SDimitry Andric CmdArgs.push_back("-lrt"); 16220b57cec5SDimitry Andric CmdArgs.push_back("-lm"); 16230b57cec5SDimitry Andric 16240b57cec5SDimitry Andric if (!TC.getTriple().isOSFreeBSD() && 16250b57cec5SDimitry Andric !TC.getTriple().isOSNetBSD() && 16260b57cec5SDimitry Andric !TC.getTriple().isOSOpenBSD()) 16270b57cec5SDimitry Andric CmdArgs.push_back("-ldl"); 16280b57cec5SDimitry Andric } 16290b57cec5SDimitry Andric 16300b57cec5SDimitry Andric bool tools::areOptimizationsEnabled(const ArgList &Args) { 16310b57cec5SDimitry Andric // Find the last -O arg and see if it is non-zero. 16320b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_O_Group)) 16330b57cec5SDimitry Andric return !A->getOption().matches(options::OPT_O0); 16340b57cec5SDimitry Andric // Defaults to -O0. 16350b57cec5SDimitry Andric return false; 16360b57cec5SDimitry Andric } 16370b57cec5SDimitry Andric 1638e8d8bef9SDimitry Andric const char *tools::SplitDebugName(const JobAction &JA, const ArgList &Args, 1639e8d8bef9SDimitry Andric const InputInfo &Input, 16400b57cec5SDimitry Andric const InputInfo &Output) { 1641e8d8bef9SDimitry Andric auto AddPostfix = [JA](auto &F) { 1642e8d8bef9SDimitry Andric if (JA.getOffloadingDeviceKind() == Action::OFK_HIP) 1643e8d8bef9SDimitry Andric F += (Twine("_") + JA.getOffloadingArch()).str(); 1644e8d8bef9SDimitry Andric F += ".dwo"; 1645e8d8bef9SDimitry Andric }; 16460b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_gsplit_dwarf_EQ)) 164706c3fb27SDimitry Andric if (StringRef(A->getValue()) == "single" && Output.isFilename()) 16480b57cec5SDimitry Andric return Args.MakeArgString(Output.getFilename()); 16490b57cec5SDimitry Andric 165006c3fb27SDimitry Andric SmallString<128> T; 165106c3fb27SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_dumpdir)) { 165206c3fb27SDimitry Andric T = A->getValue(); 165306c3fb27SDimitry Andric } else { 165406c3fb27SDimitry Andric Arg *FinalOutput = Args.getLastArg(options::OPT_o, options::OPT__SLASH_o); 16550b57cec5SDimitry Andric if (FinalOutput && Args.hasArg(options::OPT_c)) { 165606c3fb27SDimitry Andric T = FinalOutput->getValue(); 1657e8d8bef9SDimitry Andric llvm::sys::path::remove_filename(T); 165806c3fb27SDimitry Andric llvm::sys::path::append(T, 165906c3fb27SDimitry Andric llvm::sys::path::stem(FinalOutput->getValue())); 1660e8d8bef9SDimitry Andric AddPostfix(T); 16610b57cec5SDimitry Andric return Args.MakeArgString(T); 16620b57cec5SDimitry Andric } 16630b57cec5SDimitry Andric } 16640b57cec5SDimitry Andric 166506c3fb27SDimitry Andric T += llvm::sys::path::stem(Input.getBaseInput()); 166606c3fb27SDimitry Andric AddPostfix(T); 166706c3fb27SDimitry Andric return Args.MakeArgString(T); 166806c3fb27SDimitry Andric } 166906c3fb27SDimitry Andric 16700b57cec5SDimitry Andric void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, 16710b57cec5SDimitry Andric const JobAction &JA, const ArgList &Args, 16720b57cec5SDimitry Andric const InputInfo &Output, const char *OutFile) { 16730b57cec5SDimitry Andric ArgStringList ExtractArgs; 16740b57cec5SDimitry Andric ExtractArgs.push_back("--extract-dwo"); 16750b57cec5SDimitry Andric 16760b57cec5SDimitry Andric ArgStringList StripArgs; 16770b57cec5SDimitry Andric StripArgs.push_back("--strip-dwo"); 16780b57cec5SDimitry Andric 16790b57cec5SDimitry Andric // Grabbing the output of the earlier compile step. 16800b57cec5SDimitry Andric StripArgs.push_back(Output.getFilename()); 16810b57cec5SDimitry Andric ExtractArgs.push_back(Output.getFilename()); 16820b57cec5SDimitry Andric ExtractArgs.push_back(OutFile); 16830b57cec5SDimitry Andric 16840b57cec5SDimitry Andric const char *Exec = 16850b57cec5SDimitry Andric Args.MakeArgString(TC.GetProgramPath(CLANG_DEFAULT_OBJCOPY)); 16860b57cec5SDimitry Andric InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename()); 16870b57cec5SDimitry Andric 16880b57cec5SDimitry Andric // First extract the dwo sections. 1689e8d8bef9SDimitry Andric C.addCommand(std::make_unique<Command>(JA, T, 1690e8d8bef9SDimitry Andric ResponseFileSupport::AtFileCurCP(), 1691e8d8bef9SDimitry Andric Exec, ExtractArgs, II, Output)); 16920b57cec5SDimitry Andric 16930b57cec5SDimitry Andric // Then remove them from the original .o file. 16945ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>( 1695e8d8bef9SDimitry Andric JA, T, ResponseFileSupport::AtFileCurCP(), Exec, StripArgs, II, Output)); 16960b57cec5SDimitry Andric } 16970b57cec5SDimitry Andric 16980b57cec5SDimitry Andric // Claim options we don't want to warn if they are unused. We do this for 16990b57cec5SDimitry Andric // options that build systems might add but are unused when assembling or only 17000b57cec5SDimitry Andric // running the preprocessor for example. 17010b57cec5SDimitry Andric void tools::claimNoWarnArgs(const ArgList &Args) { 17020b57cec5SDimitry Andric // Don't warn about unused -f(no-)?lto. This can happen when we're 17030b57cec5SDimitry Andric // preprocessing, precompiling or assembling. 17040b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_flto_EQ); 17050b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_flto); 17060b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_fno_lto); 17070b57cec5SDimitry Andric } 17080b57cec5SDimitry Andric 170906c3fb27SDimitry Andric Arg *tools::getLastCSProfileGenerateArg(const ArgList &Args) { 171006c3fb27SDimitry Andric auto *CSPGOGenerateArg = Args.getLastArg(options::OPT_fcs_profile_generate, 171106c3fb27SDimitry Andric options::OPT_fcs_profile_generate_EQ, 171206c3fb27SDimitry Andric options::OPT_fno_profile_generate); 171306c3fb27SDimitry Andric if (CSPGOGenerateArg && 171406c3fb27SDimitry Andric CSPGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate)) 171506c3fb27SDimitry Andric CSPGOGenerateArg = nullptr; 171606c3fb27SDimitry Andric 171706c3fb27SDimitry Andric return CSPGOGenerateArg; 171806c3fb27SDimitry Andric } 171906c3fb27SDimitry Andric 17200b57cec5SDimitry Andric Arg *tools::getLastProfileUseArg(const ArgList &Args) { 17210b57cec5SDimitry Andric auto *ProfileUseArg = Args.getLastArg( 17220b57cec5SDimitry Andric options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ, 17230b57cec5SDimitry Andric options::OPT_fprofile_use, options::OPT_fprofile_use_EQ, 17240b57cec5SDimitry Andric options::OPT_fno_profile_instr_use); 17250b57cec5SDimitry Andric 17260b57cec5SDimitry Andric if (ProfileUseArg && 17270b57cec5SDimitry Andric ProfileUseArg->getOption().matches(options::OPT_fno_profile_instr_use)) 17280b57cec5SDimitry Andric ProfileUseArg = nullptr; 17290b57cec5SDimitry Andric 17300b57cec5SDimitry Andric return ProfileUseArg; 17310b57cec5SDimitry Andric } 17320b57cec5SDimitry Andric 17330b57cec5SDimitry Andric Arg *tools::getLastProfileSampleUseArg(const ArgList &Args) { 17340b57cec5SDimitry Andric auto *ProfileSampleUseArg = Args.getLastArg( 17350b57cec5SDimitry Andric options::OPT_fprofile_sample_use, options::OPT_fprofile_sample_use_EQ, 17360b57cec5SDimitry Andric options::OPT_fauto_profile, options::OPT_fauto_profile_EQ, 17370b57cec5SDimitry Andric options::OPT_fno_profile_sample_use, options::OPT_fno_auto_profile); 17380b57cec5SDimitry Andric 17390b57cec5SDimitry Andric if (ProfileSampleUseArg && 17400b57cec5SDimitry Andric (ProfileSampleUseArg->getOption().matches( 17410b57cec5SDimitry Andric options::OPT_fno_profile_sample_use) || 17420b57cec5SDimitry Andric ProfileSampleUseArg->getOption().matches(options::OPT_fno_auto_profile))) 17430b57cec5SDimitry Andric return nullptr; 17440b57cec5SDimitry Andric 17450b57cec5SDimitry Andric return Args.getLastArg(options::OPT_fprofile_sample_use_EQ, 17460b57cec5SDimitry Andric options::OPT_fauto_profile_EQ); 17470b57cec5SDimitry Andric } 17480b57cec5SDimitry Andric 1749bdd1243dSDimitry Andric const char *tools::RelocationModelName(llvm::Reloc::Model Model) { 1750bdd1243dSDimitry Andric switch (Model) { 1751bdd1243dSDimitry Andric case llvm::Reloc::Static: 1752bdd1243dSDimitry Andric return "static"; 1753bdd1243dSDimitry Andric case llvm::Reloc::PIC_: 1754bdd1243dSDimitry Andric return "pic"; 1755bdd1243dSDimitry Andric case llvm::Reloc::DynamicNoPIC: 1756bdd1243dSDimitry Andric return "dynamic-no-pic"; 1757bdd1243dSDimitry Andric case llvm::Reloc::ROPI: 1758bdd1243dSDimitry Andric return "ropi"; 1759bdd1243dSDimitry Andric case llvm::Reloc::RWPI: 1760bdd1243dSDimitry Andric return "rwpi"; 1761bdd1243dSDimitry Andric case llvm::Reloc::ROPI_RWPI: 1762bdd1243dSDimitry Andric return "ropi-rwpi"; 1763bdd1243dSDimitry Andric } 1764bdd1243dSDimitry Andric llvm_unreachable("Unknown Reloc::Model kind"); 1765bdd1243dSDimitry Andric } 1766bdd1243dSDimitry Andric 17670b57cec5SDimitry Andric /// Parses the various -fpic/-fPIC/-fpie/-fPIE arguments. Then, 17680b57cec5SDimitry Andric /// smooshes them together with platform defaults, to decide whether 17690b57cec5SDimitry Andric /// this compile should be using PIC mode or not. Returns a tuple of 17700b57cec5SDimitry Andric /// (RelocationModel, PICLevel, IsPIE). 17710b57cec5SDimitry Andric std::tuple<llvm::Reloc::Model, unsigned, bool> 17720b57cec5SDimitry Andric tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) { 17730b57cec5SDimitry Andric const llvm::Triple &EffectiveTriple = ToolChain.getEffectiveTriple(); 17740b57cec5SDimitry Andric const llvm::Triple &Triple = ToolChain.getTriple(); 17750b57cec5SDimitry Andric 1776349cc55cSDimitry Andric bool PIE = ToolChain.isPIEDefault(Args); 17770b57cec5SDimitry Andric bool PIC = PIE || ToolChain.isPICDefault(); 17780b57cec5SDimitry Andric // The Darwin/MachO default to use PIC does not apply when using -static. 17790b57cec5SDimitry Andric if (Triple.isOSBinFormatMachO() && Args.hasArg(options::OPT_static)) 17800b57cec5SDimitry Andric PIE = PIC = false; 17810b57cec5SDimitry Andric bool IsPICLevelTwo = PIC; 17820b57cec5SDimitry Andric 17830b57cec5SDimitry Andric bool KernelOrKext = 17840b57cec5SDimitry Andric Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); 17850b57cec5SDimitry Andric 17860b57cec5SDimitry Andric // Android-specific defaults for PIC/PIE 17870b57cec5SDimitry Andric if (Triple.isAndroid()) { 17880b57cec5SDimitry Andric switch (Triple.getArch()) { 17890b57cec5SDimitry Andric case llvm::Triple::arm: 17900b57cec5SDimitry Andric case llvm::Triple::armeb: 17910b57cec5SDimitry Andric case llvm::Triple::thumb: 17920b57cec5SDimitry Andric case llvm::Triple::thumbeb: 17930b57cec5SDimitry Andric case llvm::Triple::aarch64: 17940b57cec5SDimitry Andric case llvm::Triple::mips: 17950b57cec5SDimitry Andric case llvm::Triple::mipsel: 17960b57cec5SDimitry Andric case llvm::Triple::mips64: 17970b57cec5SDimitry Andric case llvm::Triple::mips64el: 17980b57cec5SDimitry Andric PIC = true; // "-fpic" 17990b57cec5SDimitry Andric break; 18000b57cec5SDimitry Andric 18010b57cec5SDimitry Andric case llvm::Triple::x86: 18020b57cec5SDimitry Andric case llvm::Triple::x86_64: 18030b57cec5SDimitry Andric PIC = true; // "-fPIC" 18040b57cec5SDimitry Andric IsPICLevelTwo = true; 18050b57cec5SDimitry Andric break; 18060b57cec5SDimitry Andric 18070b57cec5SDimitry Andric default: 18080b57cec5SDimitry Andric break; 18090b57cec5SDimitry Andric } 18100b57cec5SDimitry Andric } 18110b57cec5SDimitry Andric 181206c3fb27SDimitry Andric // OHOS-specific defaults for PIC/PIE 181306c3fb27SDimitry Andric if (Triple.isOHOSFamily() && Triple.getArch() == llvm::Triple::aarch64) 181406c3fb27SDimitry Andric PIC = true; 181506c3fb27SDimitry Andric 18160b57cec5SDimitry Andric // OpenBSD-specific defaults for PIE 18170b57cec5SDimitry Andric if (Triple.isOSOpenBSD()) { 18180b57cec5SDimitry Andric switch (ToolChain.getArch()) { 18190b57cec5SDimitry Andric case llvm::Triple::arm: 18200b57cec5SDimitry Andric case llvm::Triple::aarch64: 18210b57cec5SDimitry Andric case llvm::Triple::mips64: 18220b57cec5SDimitry Andric case llvm::Triple::mips64el: 18230b57cec5SDimitry Andric case llvm::Triple::x86: 18240b57cec5SDimitry Andric case llvm::Triple::x86_64: 18250b57cec5SDimitry Andric IsPICLevelTwo = false; // "-fpie" 18260b57cec5SDimitry Andric break; 18270b57cec5SDimitry Andric 18280b57cec5SDimitry Andric case llvm::Triple::ppc: 18290b57cec5SDimitry Andric case llvm::Triple::sparcv9: 18300b57cec5SDimitry Andric IsPICLevelTwo = true; // "-fPIE" 18310b57cec5SDimitry Andric break; 18320b57cec5SDimitry Andric 18330b57cec5SDimitry Andric default: 18340b57cec5SDimitry Andric break; 18350b57cec5SDimitry Andric } 18360b57cec5SDimitry Andric } 18370b57cec5SDimitry Andric 18380b57cec5SDimitry Andric // The last argument relating to either PIC or PIE wins, and no 18390b57cec5SDimitry Andric // other argument is used. If the last argument is any flavor of the 18400b57cec5SDimitry Andric // '-fno-...' arguments, both PIC and PIE are disabled. Any PIE 18410b57cec5SDimitry Andric // option implicitly enables PIC at the same level. 18420b57cec5SDimitry Andric Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, 18430b57cec5SDimitry Andric options::OPT_fpic, options::OPT_fno_pic, 18440b57cec5SDimitry Andric options::OPT_fPIE, options::OPT_fno_PIE, 18450b57cec5SDimitry Andric options::OPT_fpie, options::OPT_fno_pie); 184604eeddc0SDimitry Andric if (Triple.isOSWindows() && !Triple.isOSCygMing() && LastPICArg && 184704eeddc0SDimitry Andric LastPICArg == Args.getLastArg(options::OPT_fPIC, options::OPT_fpic, 18480b57cec5SDimitry Andric options::OPT_fPIE, options::OPT_fpie)) { 18490b57cec5SDimitry Andric ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) 18500b57cec5SDimitry Andric << LastPICArg->getSpelling() << Triple.str(); 18510b57cec5SDimitry Andric if (Triple.getArch() == llvm::Triple::x86_64) 18520b57cec5SDimitry Andric return std::make_tuple(llvm::Reloc::PIC_, 2U, false); 18530b57cec5SDimitry Andric return std::make_tuple(llvm::Reloc::Static, 0U, false); 18540b57cec5SDimitry Andric } 18550b57cec5SDimitry Andric 18560b57cec5SDimitry Andric // Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness 18570b57cec5SDimitry Andric // is forced, then neither PIC nor PIE flags will have no effect. 18580b57cec5SDimitry Andric if (!ToolChain.isPICDefaultForced()) { 18590b57cec5SDimitry Andric if (LastPICArg) { 18600b57cec5SDimitry Andric Option O = LastPICArg->getOption(); 18610b57cec5SDimitry Andric if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) || 18620b57cec5SDimitry Andric O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) { 18630b57cec5SDimitry Andric PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie); 18640b57cec5SDimitry Andric PIC = 18650b57cec5SDimitry Andric PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic); 18660b57cec5SDimitry Andric IsPICLevelTwo = 18670b57cec5SDimitry Andric O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC); 18680b57cec5SDimitry Andric } else { 18690b57cec5SDimitry Andric PIE = PIC = false; 187081ad6265SDimitry Andric if (EffectiveTriple.isPS()) { 18710b57cec5SDimitry Andric Arg *ModelArg = Args.getLastArg(options::OPT_mcmodel_EQ); 18720b57cec5SDimitry Andric StringRef Model = ModelArg ? ModelArg->getValue() : ""; 18730b57cec5SDimitry Andric if (Model != "kernel") { 18740b57cec5SDimitry Andric PIC = true; 187581ad6265SDimitry Andric ToolChain.getDriver().Diag(diag::warn_drv_ps_force_pic) 187681ad6265SDimitry Andric << LastPICArg->getSpelling() 187781ad6265SDimitry Andric << (EffectiveTriple.isPS4() ? "PS4" : "PS5"); 18780b57cec5SDimitry Andric } 18790b57cec5SDimitry Andric } 18800b57cec5SDimitry Andric } 18810b57cec5SDimitry Andric } 18820b57cec5SDimitry Andric } 18830b57cec5SDimitry Andric 188481ad6265SDimitry Andric // Introduce a Darwin and PS4/PS5-specific hack. If the default is PIC, but 188581ad6265SDimitry Andric // the PIC level would've been set to level 1, force it back to level 2 PIC 18860b57cec5SDimitry Andric // instead. 188781ad6265SDimitry Andric if (PIC && (Triple.isOSDarwin() || EffectiveTriple.isPS())) 18880b57cec5SDimitry Andric IsPICLevelTwo |= ToolChain.isPICDefault(); 18890b57cec5SDimitry Andric 18900b57cec5SDimitry Andric // This kernel flags are a trump-card: they will disable PIC/PIE 18910b57cec5SDimitry Andric // generation, independent of the argument order. 18920b57cec5SDimitry Andric if (KernelOrKext && 18930b57cec5SDimitry Andric ((!EffectiveTriple.isiOS() || EffectiveTriple.isOSVersionLT(6)) && 189481ad6265SDimitry Andric !EffectiveTriple.isWatchOS() && !EffectiveTriple.isDriverKit())) 18950b57cec5SDimitry Andric PIC = PIE = false; 18960b57cec5SDimitry Andric 18970b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) { 18980b57cec5SDimitry Andric // This is a very special mode. It trumps the other modes, almost no one 18990b57cec5SDimitry Andric // uses it, and it isn't even valid on any OS but Darwin. 19000b57cec5SDimitry Andric if (!Triple.isOSDarwin()) 19010b57cec5SDimitry Andric ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) 19020b57cec5SDimitry Andric << A->getSpelling() << Triple.str(); 19030b57cec5SDimitry Andric 19040b57cec5SDimitry Andric // FIXME: Warn when this flag trumps some other PIC or PIE flag. 19050b57cec5SDimitry Andric 19060b57cec5SDimitry Andric // Only a forced PIC mode can cause the actual compile to have PIC defines 19070b57cec5SDimitry Andric // etc., no flags are sufficient. This behavior was selected to closely 19080b57cec5SDimitry Andric // match that of llvm-gcc and Apple GCC before that. 19090b57cec5SDimitry Andric PIC = ToolChain.isPICDefault() && ToolChain.isPICDefaultForced(); 19100b57cec5SDimitry Andric 19110b57cec5SDimitry Andric return std::make_tuple(llvm::Reloc::DynamicNoPIC, PIC ? 2U : 0U, false); 19120b57cec5SDimitry Andric } 19130b57cec5SDimitry Andric 19140b57cec5SDimitry Andric bool EmbeddedPISupported; 19150b57cec5SDimitry Andric switch (Triple.getArch()) { 19160b57cec5SDimitry Andric case llvm::Triple::arm: 19170b57cec5SDimitry Andric case llvm::Triple::armeb: 19180b57cec5SDimitry Andric case llvm::Triple::thumb: 19190b57cec5SDimitry Andric case llvm::Triple::thumbeb: 19200b57cec5SDimitry Andric EmbeddedPISupported = true; 19210b57cec5SDimitry Andric break; 19220b57cec5SDimitry Andric default: 19230b57cec5SDimitry Andric EmbeddedPISupported = false; 19240b57cec5SDimitry Andric break; 19250b57cec5SDimitry Andric } 19260b57cec5SDimitry Andric 19270b57cec5SDimitry Andric bool ROPI = false, RWPI = false; 19280b57cec5SDimitry Andric Arg* LastROPIArg = Args.getLastArg(options::OPT_fropi, options::OPT_fno_ropi); 19290b57cec5SDimitry Andric if (LastROPIArg && LastROPIArg->getOption().matches(options::OPT_fropi)) { 19300b57cec5SDimitry Andric if (!EmbeddedPISupported) 19310b57cec5SDimitry Andric ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) 19320b57cec5SDimitry Andric << LastROPIArg->getSpelling() << Triple.str(); 19330b57cec5SDimitry Andric ROPI = true; 19340b57cec5SDimitry Andric } 19350b57cec5SDimitry Andric Arg *LastRWPIArg = Args.getLastArg(options::OPT_frwpi, options::OPT_fno_rwpi); 19360b57cec5SDimitry Andric if (LastRWPIArg && LastRWPIArg->getOption().matches(options::OPT_frwpi)) { 19370b57cec5SDimitry Andric if (!EmbeddedPISupported) 19380b57cec5SDimitry Andric ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) 19390b57cec5SDimitry Andric << LastRWPIArg->getSpelling() << Triple.str(); 19400b57cec5SDimitry Andric RWPI = true; 19410b57cec5SDimitry Andric } 19420b57cec5SDimitry Andric 19430b57cec5SDimitry Andric // ROPI and RWPI are not compatible with PIC or PIE. 19440b57cec5SDimitry Andric if ((ROPI || RWPI) && (PIC || PIE)) 19450b57cec5SDimitry Andric ToolChain.getDriver().Diag(diag::err_drv_ropi_rwpi_incompatible_with_pic); 19460b57cec5SDimitry Andric 19470b57cec5SDimitry Andric if (Triple.isMIPS()) { 19480b57cec5SDimitry Andric StringRef CPUName; 19490b57cec5SDimitry Andric StringRef ABIName; 19500b57cec5SDimitry Andric mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); 19510b57cec5SDimitry Andric // When targeting the N64 ABI, PIC is the default, except in the case 19520b57cec5SDimitry Andric // when the -mno-abicalls option is used. In that case we exit 19530b57cec5SDimitry Andric // at next check regardless of PIC being set below. 19540b57cec5SDimitry Andric if (ABIName == "n64") 19550b57cec5SDimitry Andric PIC = true; 19560b57cec5SDimitry Andric // When targettng MIPS with -mno-abicalls, it's always static. 19570b57cec5SDimitry Andric if(Args.hasArg(options::OPT_mno_abicalls)) 19580b57cec5SDimitry Andric return std::make_tuple(llvm::Reloc::Static, 0U, false); 19590b57cec5SDimitry Andric // Unlike other architectures, MIPS, even with -fPIC/-mxgot/multigot, 19600b57cec5SDimitry Andric // does not use PIC level 2 for historical reasons. 19610b57cec5SDimitry Andric IsPICLevelTwo = false; 19620b57cec5SDimitry Andric } 19630b57cec5SDimitry Andric 19640b57cec5SDimitry Andric if (PIC) 19650b57cec5SDimitry Andric return std::make_tuple(llvm::Reloc::PIC_, IsPICLevelTwo ? 2U : 1U, PIE); 19660b57cec5SDimitry Andric 19670b57cec5SDimitry Andric llvm::Reloc::Model RelocM = llvm::Reloc::Static; 19680b57cec5SDimitry Andric if (ROPI && RWPI) 19690b57cec5SDimitry Andric RelocM = llvm::Reloc::ROPI_RWPI; 19700b57cec5SDimitry Andric else if (ROPI) 19710b57cec5SDimitry Andric RelocM = llvm::Reloc::ROPI; 19720b57cec5SDimitry Andric else if (RWPI) 19730b57cec5SDimitry Andric RelocM = llvm::Reloc::RWPI; 19740b57cec5SDimitry Andric 19750b57cec5SDimitry Andric return std::make_tuple(RelocM, 0U, false); 19760b57cec5SDimitry Andric } 19770b57cec5SDimitry Andric 19780b57cec5SDimitry Andric // `-falign-functions` indicates that the functions should be aligned to a 19790b57cec5SDimitry Andric // 16-byte boundary. 19800b57cec5SDimitry Andric // 19810b57cec5SDimitry Andric // `-falign-functions=1` is the same as `-fno-align-functions`. 19820b57cec5SDimitry Andric // 19830b57cec5SDimitry Andric // The scalar `n` in `-falign-functions=n` must be an integral value between 19840b57cec5SDimitry Andric // [0, 65536]. If the value is not a power-of-two, it will be rounded up to 19850b57cec5SDimitry Andric // the nearest power-of-two. 19860b57cec5SDimitry Andric // 19870b57cec5SDimitry Andric // If we return `0`, the frontend will default to the backend's preferred 19880b57cec5SDimitry Andric // alignment. 19890b57cec5SDimitry Andric // 19900b57cec5SDimitry Andric // NOTE: icc only allows values between [0, 4096]. icc uses `-falign-functions` 19910b57cec5SDimitry Andric // to mean `-falign-functions=16`. GCC defaults to the backend's preferred 19920b57cec5SDimitry Andric // alignment. For unaligned functions, we default to the backend's preferred 19930b57cec5SDimitry Andric // alignment. 19940b57cec5SDimitry Andric unsigned tools::ParseFunctionAlignment(const ToolChain &TC, 19950b57cec5SDimitry Andric const ArgList &Args) { 19960b57cec5SDimitry Andric const Arg *A = Args.getLastArg(options::OPT_falign_functions, 19970b57cec5SDimitry Andric options::OPT_falign_functions_EQ, 19980b57cec5SDimitry Andric options::OPT_fno_align_functions); 19990b57cec5SDimitry Andric if (!A || A->getOption().matches(options::OPT_fno_align_functions)) 20000b57cec5SDimitry Andric return 0; 20010b57cec5SDimitry Andric 20020b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_falign_functions)) 20030b57cec5SDimitry Andric return 0; 20040b57cec5SDimitry Andric 20050b57cec5SDimitry Andric unsigned Value = 0; 20060b57cec5SDimitry Andric if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 65536) 20070b57cec5SDimitry Andric TC.getDriver().Diag(diag::err_drv_invalid_int_value) 20080b57cec5SDimitry Andric << A->getAsString(Args) << A->getValue(); 20090b57cec5SDimitry Andric return Value ? llvm::Log2_32_Ceil(std::min(Value, 65536u)) : Value; 20100b57cec5SDimitry Andric } 20110b57cec5SDimitry Andric 201206c3fb27SDimitry Andric void tools::addDebugInfoKind( 201306c3fb27SDimitry Andric ArgStringList &CmdArgs, llvm::codegenoptions::DebugInfoKind DebugInfoKind) { 201406c3fb27SDimitry Andric switch (DebugInfoKind) { 201506c3fb27SDimitry Andric case llvm::codegenoptions::DebugDirectivesOnly: 201606c3fb27SDimitry Andric CmdArgs.push_back("-debug-info-kind=line-directives-only"); 201706c3fb27SDimitry Andric break; 201806c3fb27SDimitry Andric case llvm::codegenoptions::DebugLineTablesOnly: 201906c3fb27SDimitry Andric CmdArgs.push_back("-debug-info-kind=line-tables-only"); 202006c3fb27SDimitry Andric break; 202106c3fb27SDimitry Andric case llvm::codegenoptions::DebugInfoConstructor: 202206c3fb27SDimitry Andric CmdArgs.push_back("-debug-info-kind=constructor"); 202306c3fb27SDimitry Andric break; 202406c3fb27SDimitry Andric case llvm::codegenoptions::LimitedDebugInfo: 202506c3fb27SDimitry Andric CmdArgs.push_back("-debug-info-kind=limited"); 202606c3fb27SDimitry Andric break; 202706c3fb27SDimitry Andric case llvm::codegenoptions::FullDebugInfo: 202806c3fb27SDimitry Andric CmdArgs.push_back("-debug-info-kind=standalone"); 202906c3fb27SDimitry Andric break; 203006c3fb27SDimitry Andric case llvm::codegenoptions::UnusedTypeInfo: 203106c3fb27SDimitry Andric CmdArgs.push_back("-debug-info-kind=unused-types"); 203206c3fb27SDimitry Andric break; 203306c3fb27SDimitry Andric default: 203406c3fb27SDimitry Andric break; 203506c3fb27SDimitry Andric } 203606c3fb27SDimitry Andric } 203706c3fb27SDimitry Andric 203806c3fb27SDimitry Andric // Convert an arg of the form "-gN" or "-ggdbN" or one of their aliases 203906c3fb27SDimitry Andric // to the corresponding DebugInfoKind. 204006c3fb27SDimitry Andric llvm::codegenoptions::DebugInfoKind tools::debugLevelToInfoKind(const Arg &A) { 204106c3fb27SDimitry Andric assert(A.getOption().matches(options::OPT_gN_Group) && 204206c3fb27SDimitry Andric "Not a -g option that specifies a debug-info level"); 204306c3fb27SDimitry Andric if (A.getOption().matches(options::OPT_g0) || 204406c3fb27SDimitry Andric A.getOption().matches(options::OPT_ggdb0)) 204506c3fb27SDimitry Andric return llvm::codegenoptions::NoDebugInfo; 204606c3fb27SDimitry Andric if (A.getOption().matches(options::OPT_gline_tables_only) || 204706c3fb27SDimitry Andric A.getOption().matches(options::OPT_ggdb1)) 204806c3fb27SDimitry Andric return llvm::codegenoptions::DebugLineTablesOnly; 204906c3fb27SDimitry Andric if (A.getOption().matches(options::OPT_gline_directives_only)) 205006c3fb27SDimitry Andric return llvm::codegenoptions::DebugDirectivesOnly; 205106c3fb27SDimitry Andric return llvm::codegenoptions::DebugInfoConstructor; 205206c3fb27SDimitry Andric } 205306c3fb27SDimitry Andric 2054bdd1243dSDimitry Andric static unsigned ParseDebugDefaultVersion(const ToolChain &TC, 2055480093f4SDimitry Andric const ArgList &Args) { 2056480093f4SDimitry Andric const Arg *A = Args.getLastArg(options::OPT_fdebug_default_version); 2057480093f4SDimitry Andric 2058480093f4SDimitry Andric if (!A) 2059480093f4SDimitry Andric return 0; 2060480093f4SDimitry Andric 2061480093f4SDimitry Andric unsigned Value = 0; 2062480093f4SDimitry Andric if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 5 || 2063480093f4SDimitry Andric Value < 2) 2064480093f4SDimitry Andric TC.getDriver().Diag(diag::err_drv_invalid_int_value) 2065480093f4SDimitry Andric << A->getAsString(Args) << A->getValue(); 2066480093f4SDimitry Andric return Value; 2067480093f4SDimitry Andric } 2068480093f4SDimitry Andric 2069bdd1243dSDimitry Andric unsigned tools::DwarfVersionNum(StringRef ArgValue) { 2070bdd1243dSDimitry Andric return llvm::StringSwitch<unsigned>(ArgValue) 2071bdd1243dSDimitry Andric .Case("-gdwarf-2", 2) 2072bdd1243dSDimitry Andric .Case("-gdwarf-3", 3) 2073bdd1243dSDimitry Andric .Case("-gdwarf-4", 4) 2074bdd1243dSDimitry Andric .Case("-gdwarf-5", 5) 2075bdd1243dSDimitry Andric .Default(0); 2076bdd1243dSDimitry Andric } 2077bdd1243dSDimitry Andric 2078bdd1243dSDimitry Andric const Arg *tools::getDwarfNArg(const ArgList &Args) { 2079bdd1243dSDimitry Andric return Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3, 2080bdd1243dSDimitry Andric options::OPT_gdwarf_4, options::OPT_gdwarf_5, 2081bdd1243dSDimitry Andric options::OPT_gdwarf); 2082bdd1243dSDimitry Andric } 2083bdd1243dSDimitry Andric 2084bdd1243dSDimitry Andric unsigned tools::getDwarfVersion(const ToolChain &TC, 2085bdd1243dSDimitry Andric const llvm::opt::ArgList &Args) { 2086bdd1243dSDimitry Andric unsigned DwarfVersion = ParseDebugDefaultVersion(TC, Args); 2087bdd1243dSDimitry Andric if (const Arg *GDwarfN = getDwarfNArg(Args)) 2088*0fca6ea1SDimitry Andric if (int N = DwarfVersionNum(GDwarfN->getSpelling())) { 2089bdd1243dSDimitry Andric DwarfVersion = N; 2090*0fca6ea1SDimitry Andric if (DwarfVersion == 5 && TC.getTriple().isOSAIX()) 2091*0fca6ea1SDimitry Andric TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) 2092*0fca6ea1SDimitry Andric << GDwarfN->getSpelling() << TC.getTriple().str(); 2093*0fca6ea1SDimitry Andric } 2094bdd1243dSDimitry Andric if (DwarfVersion == 0) { 2095bdd1243dSDimitry Andric DwarfVersion = TC.GetDefaultDwarfVersion(); 2096bdd1243dSDimitry Andric assert(DwarfVersion && "toolchain default DWARF version must be nonzero"); 2097bdd1243dSDimitry Andric } 2098bdd1243dSDimitry Andric return DwarfVersion; 2099bdd1243dSDimitry Andric } 2100bdd1243dSDimitry Andric 21010b57cec5SDimitry Andric void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args, 21020b57cec5SDimitry Andric ArgStringList &CmdArgs) { 21030b57cec5SDimitry Andric llvm::Reloc::Model RelocationModel; 21040b57cec5SDimitry Andric unsigned PICLevel; 21050b57cec5SDimitry Andric bool IsPIE; 21060b57cec5SDimitry Andric std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(ToolChain, Args); 21070b57cec5SDimitry Andric 21080b57cec5SDimitry Andric if (RelocationModel != llvm::Reloc::Static) 21090b57cec5SDimitry Andric CmdArgs.push_back("-KPIC"); 21100b57cec5SDimitry Andric } 21110b57cec5SDimitry Andric 21120b57cec5SDimitry Andric /// Determine whether Objective-C automated reference counting is 21130b57cec5SDimitry Andric /// enabled. 21140b57cec5SDimitry Andric bool tools::isObjCAutoRefCount(const ArgList &Args) { 21150b57cec5SDimitry Andric return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false); 21160b57cec5SDimitry Andric } 21170b57cec5SDimitry Andric 21180b57cec5SDimitry Andric enum class LibGccType { UnspecifiedLibGcc, StaticLibGcc, SharedLibGcc }; 21190b57cec5SDimitry Andric 2120fe6060f1SDimitry Andric static LibGccType getLibGccType(const ToolChain &TC, const Driver &D, 2121fe6060f1SDimitry Andric const ArgList &Args) { 21220b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static_libgcc) || 212381ad6265SDimitry Andric Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_pie) || 212481ad6265SDimitry Andric // The Android NDK only provides libunwind.a, not libunwind.so. 212581ad6265SDimitry Andric TC.getTriple().isAndroid()) 21260b57cec5SDimitry Andric return LibGccType::StaticLibGcc; 2127fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_shared_libgcc)) 2128fe6060f1SDimitry Andric return LibGccType::SharedLibGcc; 21290b57cec5SDimitry Andric return LibGccType::UnspecifiedLibGcc; 21300b57cec5SDimitry Andric } 21310b57cec5SDimitry Andric 21320b57cec5SDimitry Andric // Gcc adds libgcc arguments in various ways: 21330b57cec5SDimitry Andric // 21340b57cec5SDimitry Andric // gcc <none>: -lgcc --as-needed -lgcc_s --no-as-needed 21350b57cec5SDimitry Andric // g++ <none>: -lgcc_s -lgcc 21360b57cec5SDimitry Andric // gcc shared: -lgcc_s -lgcc 21370b57cec5SDimitry Andric // g++ shared: -lgcc_s -lgcc 21380b57cec5SDimitry Andric // gcc static: -lgcc -lgcc_eh 21390b57cec5SDimitry Andric // g++ static: -lgcc -lgcc_eh 21400b57cec5SDimitry Andric // gcc static-pie: -lgcc -lgcc_eh 21410b57cec5SDimitry Andric // g++ static-pie: -lgcc -lgcc_eh 21420b57cec5SDimitry Andric // 21430b57cec5SDimitry Andric // Also, certain targets need additional adjustments. 21440b57cec5SDimitry Andric 21450b57cec5SDimitry Andric static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, 21460b57cec5SDimitry Andric ArgStringList &CmdArgs, const ArgList &Args) { 21470b57cec5SDimitry Andric ToolChain::UnwindLibType UNW = TC.GetUnwindLibType(Args); 214806c3fb27SDimitry Andric // By default OHOS binaries are linked statically to libunwind. 214906c3fb27SDimitry Andric if (TC.getTriple().isOHOSFamily() && UNW == ToolChain::UNW_CompilerRT) { 215006c3fb27SDimitry Andric CmdArgs.push_back("-l:libunwind.a"); 215106c3fb27SDimitry Andric return; 215206c3fb27SDimitry Andric } 215306c3fb27SDimitry Andric 21540b57cec5SDimitry Andric // Targets that don't use unwind libraries. 2155fe6060f1SDimitry Andric if ((TC.getTriple().isAndroid() && UNW == ToolChain::UNW_Libgcc) || 2156fe6060f1SDimitry Andric TC.getTriple().isOSIAMCU() || TC.getTriple().isOSBinFormatWasm() || 2157bdd1243dSDimitry Andric TC.getTriple().isWindowsMSVCEnvironment() || UNW == ToolChain::UNW_None) 21580b57cec5SDimitry Andric return; 21590b57cec5SDimitry Andric 2160fe6060f1SDimitry Andric LibGccType LGT = getLibGccType(TC, D, Args); 21610b57cec5SDimitry Andric bool AsNeeded = LGT == LibGccType::UnspecifiedLibGcc && 216281ad6265SDimitry Andric (UNW == ToolChain::UNW_CompilerRT || !D.CCCIsCXX()) && 2163fe6060f1SDimitry Andric !TC.getTriple().isAndroid() && 2164fe6060f1SDimitry Andric !TC.getTriple().isOSCygMing() && !TC.getTriple().isOSAIX(); 21650b57cec5SDimitry Andric if (AsNeeded) 21665f757f3fSDimitry Andric addAsNeededOption(TC, Args, CmdArgs, true); 21670b57cec5SDimitry Andric 21680b57cec5SDimitry Andric switch (UNW) { 21690b57cec5SDimitry Andric case ToolChain::UNW_None: 21700b57cec5SDimitry Andric return; 21710b57cec5SDimitry Andric case ToolChain::UNW_Libgcc: { 21720b57cec5SDimitry Andric if (LGT == LibGccType::StaticLibGcc) 21730b57cec5SDimitry Andric CmdArgs.push_back("-lgcc_eh"); 21740b57cec5SDimitry Andric else 21750b57cec5SDimitry Andric CmdArgs.push_back("-lgcc_s"); 21760b57cec5SDimitry Andric break; 21770b57cec5SDimitry Andric } 21780b57cec5SDimitry Andric case ToolChain::UNW_CompilerRT: 2179fe6060f1SDimitry Andric if (TC.getTriple().isOSAIX()) { 2180fe6060f1SDimitry Andric // AIX only has libunwind as a shared library. So do not pass 2181fe6060f1SDimitry Andric // anything in if -static is specified. 2182fe6060f1SDimitry Andric if (LGT != LibGccType::StaticLibGcc) 2183fe6060f1SDimitry Andric CmdArgs.push_back("-lunwind"); 2184fe6060f1SDimitry Andric } else if (LGT == LibGccType::StaticLibGcc) { 2185480093f4SDimitry Andric CmdArgs.push_back("-l:libunwind.a"); 218681ad6265SDimitry Andric } else if (LGT == LibGccType::SharedLibGcc) { 218781ad6265SDimitry Andric if (TC.getTriple().isOSCygMing()) 21885ffd83dbSDimitry Andric CmdArgs.push_back("-l:libunwind.dll.a"); 2189480093f4SDimitry Andric else 219081ad6265SDimitry Andric CmdArgs.push_back("-l:libunwind.so"); 219181ad6265SDimitry Andric } else { 219281ad6265SDimitry Andric // Let the linker choose between libunwind.so and libunwind.a 21935ffd83dbSDimitry Andric // depending on what's available, and depending on the -static flag 21945ffd83dbSDimitry Andric CmdArgs.push_back("-lunwind"); 2195fe6060f1SDimitry Andric } 21960b57cec5SDimitry Andric break; 21970b57cec5SDimitry Andric } 21980b57cec5SDimitry Andric 21990b57cec5SDimitry Andric if (AsNeeded) 22005f757f3fSDimitry Andric addAsNeededOption(TC, Args, CmdArgs, false); 22010b57cec5SDimitry Andric } 22020b57cec5SDimitry Andric 22030b57cec5SDimitry Andric static void AddLibgcc(const ToolChain &TC, const Driver &D, 22040b57cec5SDimitry Andric ArgStringList &CmdArgs, const ArgList &Args) { 2205fe6060f1SDimitry Andric LibGccType LGT = getLibGccType(TC, D, Args); 220681ad6265SDimitry Andric if (LGT == LibGccType::StaticLibGcc || 220781ad6265SDimitry Andric (LGT == LibGccType::UnspecifiedLibGcc && !D.CCCIsCXX())) 22080b57cec5SDimitry Andric CmdArgs.push_back("-lgcc"); 22090b57cec5SDimitry Andric AddUnwindLibrary(TC, D, CmdArgs, Args); 221081ad6265SDimitry Andric if (LGT == LibGccType::SharedLibGcc || 221181ad6265SDimitry Andric (LGT == LibGccType::UnspecifiedLibGcc && D.CCCIsCXX())) 22120b57cec5SDimitry Andric CmdArgs.push_back("-lgcc"); 22130b57cec5SDimitry Andric } 22140b57cec5SDimitry Andric 22150b57cec5SDimitry Andric void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, 22160b57cec5SDimitry Andric ArgStringList &CmdArgs, const ArgList &Args) { 22170b57cec5SDimitry Andric // Make use of compiler-rt if --rtlib option is used 22180b57cec5SDimitry Andric ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args); 22190b57cec5SDimitry Andric 22200b57cec5SDimitry Andric switch (RLT) { 22210b57cec5SDimitry Andric case ToolChain::RLT_CompilerRT: 22220b57cec5SDimitry Andric CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins")); 22230b57cec5SDimitry Andric AddUnwindLibrary(TC, D, CmdArgs, Args); 22240b57cec5SDimitry Andric break; 22250b57cec5SDimitry Andric case ToolChain::RLT_Libgcc: 22260b57cec5SDimitry Andric // Make sure libgcc is not used under MSVC environment by default 22270b57cec5SDimitry Andric if (TC.getTriple().isKnownWindowsMSVCEnvironment()) { 22280b57cec5SDimitry Andric // Issue error diagnostic if libgcc is explicitly specified 22290b57cec5SDimitry Andric // through command line as --rtlib option argument. 2230bdd1243dSDimitry Andric Arg *A = Args.getLastArg(options::OPT_rtlib_EQ); 2231bdd1243dSDimitry Andric if (A && A->getValue() != StringRef("platform")) { 22320b57cec5SDimitry Andric TC.getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform) 2233bdd1243dSDimitry Andric << A->getValue() << "MSVC"; 22340b57cec5SDimitry Andric } 22350b57cec5SDimitry Andric } else 22360b57cec5SDimitry Andric AddLibgcc(TC, D, CmdArgs, Args); 22370b57cec5SDimitry Andric break; 22380b57cec5SDimitry Andric } 2239fe6060f1SDimitry Andric 2240fe6060f1SDimitry Andric // On Android, the unwinder uses dl_iterate_phdr (or one of 2241fe6060f1SDimitry Andric // dl_unwind_find_exidx/__gnu_Unwind_Find_exidx on arm32) from libdl.so. For 2242fe6060f1SDimitry Andric // statically-linked executables, these functions come from libc.a instead. 2243fe6060f1SDimitry Andric if (TC.getTriple().isAndroid() && !Args.hasArg(options::OPT_static) && 2244fe6060f1SDimitry Andric !Args.hasArg(options::OPT_static_pie)) 2245fe6060f1SDimitry Andric CmdArgs.push_back("-ldl"); 22460b57cec5SDimitry Andric } 22470b57cec5SDimitry Andric 22480b57cec5SDimitry Andric SmallString<128> tools::getStatsFileName(const llvm::opt::ArgList &Args, 22490b57cec5SDimitry Andric const InputInfo &Output, 22500b57cec5SDimitry Andric const InputInfo &Input, 22510b57cec5SDimitry Andric const Driver &D) { 22520b57cec5SDimitry Andric const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ); 225306c3fb27SDimitry Andric if (!A && !D.CCPrintInternalStats) 22540b57cec5SDimitry Andric return {}; 22550b57cec5SDimitry Andric 22560b57cec5SDimitry Andric SmallString<128> StatsFile; 225706c3fb27SDimitry Andric if (A) { 225806c3fb27SDimitry Andric StringRef SaveStats = A->getValue(); 22590b57cec5SDimitry Andric if (SaveStats == "obj" && Output.isFilename()) { 22600b57cec5SDimitry Andric StatsFile.assign(Output.getFilename()); 22610b57cec5SDimitry Andric llvm::sys::path::remove_filename(StatsFile); 22620b57cec5SDimitry Andric } else if (SaveStats != "cwd") { 22630b57cec5SDimitry Andric D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats; 22640b57cec5SDimitry Andric return {}; 22650b57cec5SDimitry Andric } 22660b57cec5SDimitry Andric 22670b57cec5SDimitry Andric StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput()); 22680b57cec5SDimitry Andric llvm::sys::path::append(StatsFile, BaseName); 22690b57cec5SDimitry Andric llvm::sys::path::replace_extension(StatsFile, "stats"); 227006c3fb27SDimitry Andric } else { 227106c3fb27SDimitry Andric assert(D.CCPrintInternalStats); 227206c3fb27SDimitry Andric StatsFile.assign(D.CCPrintInternalStatReportFilename.empty() 227306c3fb27SDimitry Andric ? "-" 227406c3fb27SDimitry Andric : D.CCPrintInternalStatReportFilename); 227506c3fb27SDimitry Andric } 22760b57cec5SDimitry Andric return StatsFile; 22770b57cec5SDimitry Andric } 22780b57cec5SDimitry Andric 227906c3fb27SDimitry Andric void tools::addMultilibFlag(bool Enabled, const StringRef Flag, 22800b57cec5SDimitry Andric Multilib::flags_list &Flags) { 228106c3fb27SDimitry Andric assert(Flag.front() == '-'); 228206c3fb27SDimitry Andric if (Enabled) { 228306c3fb27SDimitry Andric Flags.push_back(Flag.str()); 228406c3fb27SDimitry Andric } else { 228506c3fb27SDimitry Andric Flags.push_back(("!" + Flag.substr(1)).str()); 228606c3fb27SDimitry Andric } 22870b57cec5SDimitry Andric } 22885ffd83dbSDimitry Andric 22895ffd83dbSDimitry Andric void tools::addX86AlignBranchArgs(const Driver &D, const ArgList &Args, 2290bdd1243dSDimitry Andric ArgStringList &CmdArgs, bool IsLTO, 2291bdd1243dSDimitry Andric const StringRef PluginOptPrefix) { 22925ffd83dbSDimitry Andric auto addArg = [&, IsLTO](const Twine &Arg) { 22935ffd83dbSDimitry Andric if (IsLTO) { 2294bdd1243dSDimitry Andric assert(!PluginOptPrefix.empty() && "Cannot have empty PluginOptPrefix!"); 2295bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + Arg)); 22965ffd83dbSDimitry Andric } else { 22975ffd83dbSDimitry Andric CmdArgs.push_back("-mllvm"); 22985ffd83dbSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Arg)); 22995ffd83dbSDimitry Andric } 23005ffd83dbSDimitry Andric }; 23015ffd83dbSDimitry Andric 23025ffd83dbSDimitry Andric if (Args.hasArg(options::OPT_mbranches_within_32B_boundaries)) { 23035ffd83dbSDimitry Andric addArg(Twine("-x86-branches-within-32B-boundaries")); 23045ffd83dbSDimitry Andric } 23055ffd83dbSDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_boundary_EQ)) { 23065ffd83dbSDimitry Andric StringRef Value = A->getValue(); 23075ffd83dbSDimitry Andric unsigned Boundary; 23085ffd83dbSDimitry Andric if (Value.getAsInteger(10, Boundary) || Boundary < 16 || 23095ffd83dbSDimitry Andric !llvm::isPowerOf2_64(Boundary)) { 23105ffd83dbSDimitry Andric D.Diag(diag::err_drv_invalid_argument_to_option) 23115ffd83dbSDimitry Andric << Value << A->getOption().getName(); 23125ffd83dbSDimitry Andric } else { 23135ffd83dbSDimitry Andric addArg("-x86-align-branch-boundary=" + Twine(Boundary)); 23145ffd83dbSDimitry Andric } 23155ffd83dbSDimitry Andric } 23165ffd83dbSDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_EQ)) { 23175ffd83dbSDimitry Andric std::string AlignBranch; 23185ffd83dbSDimitry Andric for (StringRef T : A->getValues()) { 23195ffd83dbSDimitry Andric if (T != "fused" && T != "jcc" && T != "jmp" && T != "call" && 23205ffd83dbSDimitry Andric T != "ret" && T != "indirect") 23215ffd83dbSDimitry Andric D.Diag(diag::err_drv_invalid_malign_branch_EQ) 23225ffd83dbSDimitry Andric << T << "fused, jcc, jmp, call, ret, indirect"; 23235ffd83dbSDimitry Andric if (!AlignBranch.empty()) 23245ffd83dbSDimitry Andric AlignBranch += '+'; 23255ffd83dbSDimitry Andric AlignBranch += T; 23265ffd83dbSDimitry Andric } 23275ffd83dbSDimitry Andric addArg("-x86-align-branch=" + Twine(AlignBranch)); 23285ffd83dbSDimitry Andric } 23295ffd83dbSDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_mpad_max_prefix_size_EQ)) { 23305ffd83dbSDimitry Andric StringRef Value = A->getValue(); 23315ffd83dbSDimitry Andric unsigned PrefixSize; 23325ffd83dbSDimitry Andric if (Value.getAsInteger(10, PrefixSize)) { 23335ffd83dbSDimitry Andric D.Diag(diag::err_drv_invalid_argument_to_option) 23345ffd83dbSDimitry Andric << Value << A->getOption().getName(); 23355ffd83dbSDimitry Andric } else { 23365ffd83dbSDimitry Andric addArg("-x86-pad-max-prefix-size=" + Twine(PrefixSize)); 23375ffd83dbSDimitry Andric } 23385ffd83dbSDimitry Andric } 23395ffd83dbSDimitry Andric } 2340e8d8bef9SDimitry Andric 2341349cc55cSDimitry Andric /// SDLSearch: Search for Static Device Library 2342349cc55cSDimitry Andric /// The search for SDL bitcode files is consistent with how static host 2343349cc55cSDimitry Andric /// libraries are discovered. That is, the -l option triggers a search for 2344349cc55cSDimitry Andric /// files in a set of directories called the LINKPATH. The host library search 2345349cc55cSDimitry Andric /// procedure looks for a specific filename in the LINKPATH. The filename for 2346349cc55cSDimitry Andric /// a host library is lib<libname>.a or lib<libname>.so. For SDLs, there is an 2347349cc55cSDimitry Andric /// ordered-set of filenames that are searched. We call this ordered-set of 2348349cc55cSDimitry Andric /// filenames as SEARCH-ORDER. Since an SDL can either be device-type specific, 2349349cc55cSDimitry Andric /// architecture specific, or generic across all architectures, a naming 2350349cc55cSDimitry Andric /// convention and search order is used where the file name embeds the 2351349cc55cSDimitry Andric /// architecture name <arch-name> (nvptx or amdgcn) and the GPU device type 2352349cc55cSDimitry Andric /// <device-name> such as sm_30 and gfx906. <device-name> is absent in case of 2353349cc55cSDimitry Andric /// device-independent SDLs. To reduce congestion in host library directories, 2354349cc55cSDimitry Andric /// the search first looks for files in the “libdevice” subdirectory. SDLs that 2355349cc55cSDimitry Andric /// are bc files begin with the prefix “lib”. 2356349cc55cSDimitry Andric /// 2357349cc55cSDimitry Andric /// Machine-code SDLs can also be managed as an archive (*.a file). The 2358349cc55cSDimitry Andric /// convention has been to use the prefix “lib”. To avoid confusion with host 2359349cc55cSDimitry Andric /// archive libraries, we use prefix "libbc-" for the bitcode SDL archives. 2360349cc55cSDimitry Andric /// 23615f757f3fSDimitry Andric static bool SDLSearch(const Driver &D, const llvm::opt::ArgList &DriverArgs, 2362349cc55cSDimitry Andric llvm::opt::ArgStringList &CC1Args, 23635f757f3fSDimitry Andric const SmallVectorImpl<std::string> &LibraryPaths, 23645f757f3fSDimitry Andric StringRef Lib, StringRef Arch, StringRef Target, 23655f757f3fSDimitry Andric bool isBitCodeSDL) { 2366349cc55cSDimitry Andric SmallVector<std::string, 12> SDLs; 2367349cc55cSDimitry Andric 2368349cc55cSDimitry Andric std::string LibDeviceLoc = "/libdevice"; 2369349cc55cSDimitry Andric std::string LibBcPrefix = "/libbc-"; 2370349cc55cSDimitry Andric std::string LibPrefix = "/lib"; 2371349cc55cSDimitry Andric 2372349cc55cSDimitry Andric if (isBitCodeSDL) { 2373349cc55cSDimitry Andric // SEARCH-ORDER for Bitcode SDLs: 2374349cc55cSDimitry Andric // libdevice/libbc-<libname>-<arch-name>-<device-type>.a 2375349cc55cSDimitry Andric // libbc-<libname>-<arch-name>-<device-type>.a 2376349cc55cSDimitry Andric // libdevice/libbc-<libname>-<arch-name>.a 2377349cc55cSDimitry Andric // libbc-<libname>-<arch-name>.a 2378349cc55cSDimitry Andric // libdevice/libbc-<libname>.a 2379349cc55cSDimitry Andric // libbc-<libname>.a 2380349cc55cSDimitry Andric // libdevice/lib<libname>-<arch-name>-<device-type>.bc 2381349cc55cSDimitry Andric // lib<libname>-<arch-name>-<device-type>.bc 2382349cc55cSDimitry Andric // libdevice/lib<libname>-<arch-name>.bc 2383349cc55cSDimitry Andric // lib<libname>-<arch-name>.bc 2384349cc55cSDimitry Andric // libdevice/lib<libname>.bc 2385349cc55cSDimitry Andric // lib<libname>.bc 2386349cc55cSDimitry Andric 2387349cc55cSDimitry Andric for (StringRef Base : {LibBcPrefix, LibPrefix}) { 2388349cc55cSDimitry Andric const auto *Ext = Base.contains(LibBcPrefix) ? ".a" : ".bc"; 2389349cc55cSDimitry Andric 2390349cc55cSDimitry Andric for (auto Suffix : {Twine(Lib + "-" + Arch + "-" + Target).str(), 2391349cc55cSDimitry Andric Twine(Lib + "-" + Arch).str(), Twine(Lib).str()}) { 2392349cc55cSDimitry Andric SDLs.push_back(Twine(LibDeviceLoc + Base + Suffix + Ext).str()); 2393349cc55cSDimitry Andric SDLs.push_back(Twine(Base + Suffix + Ext).str()); 2394349cc55cSDimitry Andric } 2395349cc55cSDimitry Andric } 2396349cc55cSDimitry Andric } else { 2397349cc55cSDimitry Andric // SEARCH-ORDER for Machine-code SDLs: 2398349cc55cSDimitry Andric // libdevice/lib<libname>-<arch-name>-<device-type>.a 2399349cc55cSDimitry Andric // lib<libname>-<arch-name>-<device-type>.a 2400349cc55cSDimitry Andric // libdevice/lib<libname>-<arch-name>.a 2401349cc55cSDimitry Andric // lib<libname>-<arch-name>.a 2402349cc55cSDimitry Andric 2403349cc55cSDimitry Andric const auto *Ext = ".a"; 2404349cc55cSDimitry Andric 2405349cc55cSDimitry Andric for (auto Suffix : {Twine(Lib + "-" + Arch + "-" + Target).str(), 2406349cc55cSDimitry Andric Twine(Lib + "-" + Arch).str()}) { 2407349cc55cSDimitry Andric SDLs.push_back(Twine(LibDeviceLoc + LibPrefix + Suffix + Ext).str()); 2408349cc55cSDimitry Andric SDLs.push_back(Twine(LibPrefix + Suffix + Ext).str()); 2409349cc55cSDimitry Andric } 2410349cc55cSDimitry Andric } 2411349cc55cSDimitry Andric 2412349cc55cSDimitry Andric // The CUDA toolchain does not use a global device llvm-link before the LLVM 2413349cc55cSDimitry Andric // backend generates ptx. So currently, the use of bitcode SDL for nvptx is 2414349cc55cSDimitry Andric // only possible with post-clang-cc1 linking. Clang cc1 has a feature that 2415349cc55cSDimitry Andric // will link libraries after clang compilation while the LLVM IR is still in 2416349cc55cSDimitry Andric // memory. This utilizes a clang cc1 option called “-mlink-builtin-bitcode”. 2417349cc55cSDimitry Andric // This is a clang -cc1 option that is generated by the clang driver. The 2418349cc55cSDimitry Andric // option value must a full path to an existing file. 2419349cc55cSDimitry Andric bool FoundSDL = false; 2420349cc55cSDimitry Andric for (auto LPath : LibraryPaths) { 2421349cc55cSDimitry Andric for (auto SDL : SDLs) { 2422349cc55cSDimitry Andric auto FullName = Twine(LPath + SDL).str(); 2423349cc55cSDimitry Andric if (llvm::sys::fs::exists(FullName)) { 2424349cc55cSDimitry Andric CC1Args.push_back(DriverArgs.MakeArgString(FullName)); 2425349cc55cSDimitry Andric FoundSDL = true; 2426349cc55cSDimitry Andric break; 2427349cc55cSDimitry Andric } 2428349cc55cSDimitry Andric } 2429349cc55cSDimitry Andric if (FoundSDL) 2430349cc55cSDimitry Andric break; 2431349cc55cSDimitry Andric } 2432349cc55cSDimitry Andric return FoundSDL; 2433349cc55cSDimitry Andric } 2434349cc55cSDimitry Andric 2435349cc55cSDimitry Andric /// Search if a user provided archive file lib<libname>.a exists in any of 2436349cc55cSDimitry Andric /// the library paths. If so, add a new command to clang-offload-bundler to 2437349cc55cSDimitry Andric /// unbundle this archive and create a temporary device specific archive. Name 2438bdd1243dSDimitry Andric /// of this SDL is passed to the llvm-link tool. 24395f757f3fSDimitry Andric static void GetSDLFromOffloadArchive( 2440349cc55cSDimitry Andric Compilation &C, const Driver &D, const Tool &T, const JobAction &JA, 2441349cc55cSDimitry Andric const InputInfoList &Inputs, const llvm::opt::ArgList &DriverArgs, 24425f757f3fSDimitry Andric llvm::opt::ArgStringList &CC1Args, 24435f757f3fSDimitry Andric const SmallVectorImpl<std::string> &LibraryPaths, StringRef Lib, 24445f757f3fSDimitry Andric StringRef Arch, StringRef Target, bool isBitCodeSDL) { 2445349cc55cSDimitry Andric 2446349cc55cSDimitry Andric // We don't support bitcode archive bundles for nvptx 2447349cc55cSDimitry Andric if (isBitCodeSDL && Arch.contains("nvptx")) 24485f757f3fSDimitry Andric return; 2449349cc55cSDimitry Andric 2450349cc55cSDimitry Andric bool FoundAOB = false; 2451349cc55cSDimitry Andric std::string ArchiveOfBundles; 2452349cc55cSDimitry Andric 245381ad6265SDimitry Andric llvm::Triple Triple(D.getTargetTriple()); 245481ad6265SDimitry Andric bool IsMSVC = Triple.isWindowsMSVCEnvironment(); 2455bdd1243dSDimitry Andric auto Ext = IsMSVC ? ".lib" : ".a"; 24565f757f3fSDimitry Andric if (!Lib.starts_with(":") && !Lib.starts_with("-l")) { 2457bdd1243dSDimitry Andric if (llvm::sys::fs::exists(Lib)) { 2458bdd1243dSDimitry Andric ArchiveOfBundles = Lib; 2459bdd1243dSDimitry Andric FoundAOB = true; 246081ad6265SDimitry Andric } 2461bdd1243dSDimitry Andric } else { 2462647cbc5dSDimitry Andric Lib.consume_front("-l"); 2463bdd1243dSDimitry Andric for (auto LPath : LibraryPaths) { 2464bdd1243dSDimitry Andric ArchiveOfBundles.clear(); 24655f757f3fSDimitry Andric auto LibFile = (Lib.starts_with(":") ? Lib.drop_front() 24665f757f3fSDimitry Andric : IsMSVC ? Lib + Ext 24675f757f3fSDimitry Andric : "lib" + Lib + Ext) 2468bdd1243dSDimitry Andric .str(); 2469bdd1243dSDimitry Andric for (auto Prefix : {"/libdevice/", "/"}) { 2470bdd1243dSDimitry Andric auto AOB = Twine(LPath + Prefix + LibFile).str(); 2471349cc55cSDimitry Andric if (llvm::sys::fs::exists(AOB)) { 2472349cc55cSDimitry Andric ArchiveOfBundles = AOB; 2473349cc55cSDimitry Andric FoundAOB = true; 2474349cc55cSDimitry Andric break; 2475349cc55cSDimitry Andric } 2476349cc55cSDimitry Andric } 2477bdd1243dSDimitry Andric if (FoundAOB) 2478bdd1243dSDimitry Andric break; 2479bdd1243dSDimitry Andric } 2480bdd1243dSDimitry Andric } 2481349cc55cSDimitry Andric 2482349cc55cSDimitry Andric if (!FoundAOB) 24835f757f3fSDimitry Andric return; 2484bdd1243dSDimitry Andric 2485bdd1243dSDimitry Andric llvm::file_magic Magic; 2486bdd1243dSDimitry Andric auto EC = llvm::identify_magic(ArchiveOfBundles, Magic); 2487bdd1243dSDimitry Andric if (EC || Magic != llvm::file_magic::archive) 24885f757f3fSDimitry Andric return; 2489349cc55cSDimitry Andric 2490349cc55cSDimitry Andric StringRef Prefix = isBitCodeSDL ? "libbc-" : "lib"; 2491bdd1243dSDimitry Andric std::string OutputLib = 2492bdd1243dSDimitry Andric D.GetTemporaryPath(Twine(Prefix + llvm::sys::path::filename(Lib) + "-" + 2493bdd1243dSDimitry Andric Arch + "-" + Target) 2494bdd1243dSDimitry Andric .str(), 2495bdd1243dSDimitry Andric "a"); 2496349cc55cSDimitry Andric 249704eeddc0SDimitry Andric C.addTempFile(C.getArgs().MakeArgString(OutputLib)); 2498349cc55cSDimitry Andric 2499349cc55cSDimitry Andric ArgStringList CmdArgs; 2500349cc55cSDimitry Andric SmallString<128> DeviceTriple; 2501349cc55cSDimitry Andric DeviceTriple += Action::GetOffloadKindName(JA.getOffloadingDeviceKind()); 2502349cc55cSDimitry Andric DeviceTriple += '-'; 2503349cc55cSDimitry Andric std::string NormalizedTriple = T.getToolChain().getTriple().normalize(); 2504349cc55cSDimitry Andric DeviceTriple += NormalizedTriple; 2505349cc55cSDimitry Andric if (!Target.empty()) { 2506349cc55cSDimitry Andric DeviceTriple += '-'; 2507349cc55cSDimitry Andric DeviceTriple += Target; 2508349cc55cSDimitry Andric } 2509349cc55cSDimitry Andric 2510349cc55cSDimitry Andric std::string UnbundleArg("-unbundle"); 2511349cc55cSDimitry Andric std::string TypeArg("-type=a"); 251281ad6265SDimitry Andric std::string InputArg("-input=" + ArchiveOfBundles); 2513349cc55cSDimitry Andric std::string OffloadArg("-targets=" + std::string(DeviceTriple)); 251481ad6265SDimitry Andric std::string OutputArg("-output=" + OutputLib); 2515349cc55cSDimitry Andric 2516349cc55cSDimitry Andric const char *UBProgram = DriverArgs.MakeArgString( 2517349cc55cSDimitry Andric T.getToolChain().GetProgramPath("clang-offload-bundler")); 2518349cc55cSDimitry Andric 2519349cc55cSDimitry Andric ArgStringList UBArgs; 252004eeddc0SDimitry Andric UBArgs.push_back(C.getArgs().MakeArgString(UnbundleArg)); 252104eeddc0SDimitry Andric UBArgs.push_back(C.getArgs().MakeArgString(TypeArg)); 252204eeddc0SDimitry Andric UBArgs.push_back(C.getArgs().MakeArgString(InputArg)); 252304eeddc0SDimitry Andric UBArgs.push_back(C.getArgs().MakeArgString(OffloadArg)); 252404eeddc0SDimitry Andric UBArgs.push_back(C.getArgs().MakeArgString(OutputArg)); 2525349cc55cSDimitry Andric 2526349cc55cSDimitry Andric // Add this flag to not exit from clang-offload-bundler if no compatible 2527349cc55cSDimitry Andric // code object is found in heterogenous archive library. 2528349cc55cSDimitry Andric std::string AdditionalArgs("-allow-missing-bundles"); 252904eeddc0SDimitry Andric UBArgs.push_back(C.getArgs().MakeArgString(AdditionalArgs)); 2530349cc55cSDimitry Andric 253181ad6265SDimitry Andric // Add this flag to treat hip and hipv4 offload kinds as compatible with 253281ad6265SDimitry Andric // openmp offload kind while extracting code objects from a heterogenous 253381ad6265SDimitry Andric // archive library. Vice versa is also considered compatible. 253481ad6265SDimitry Andric std::string HipCompatibleArgs("-hip-openmp-compatible"); 253581ad6265SDimitry Andric UBArgs.push_back(C.getArgs().MakeArgString(HipCompatibleArgs)); 253681ad6265SDimitry Andric 2537349cc55cSDimitry Andric C.addCommand(std::make_unique<Command>( 2538349cc55cSDimitry Andric JA, T, ResponseFileSupport::AtFileCurCP(), UBProgram, UBArgs, Inputs, 253904eeddc0SDimitry Andric InputInfo(&JA, C.getArgs().MakeArgString(OutputLib)))); 2540349cc55cSDimitry Andric 2541349cc55cSDimitry Andric CC1Args.push_back(DriverArgs.MakeArgString(OutputLib)); 2542349cc55cSDimitry Andric 25435f757f3fSDimitry Andric return; 2544349cc55cSDimitry Andric } 2545349cc55cSDimitry Andric 2546349cc55cSDimitry Andric // Wrapper function used by driver for adding SDLs during link phase. 2547349cc55cSDimitry Andric void tools::AddStaticDeviceLibsLinking(Compilation &C, const Tool &T, 2548349cc55cSDimitry Andric const JobAction &JA, 2549349cc55cSDimitry Andric const InputInfoList &Inputs, 2550349cc55cSDimitry Andric const llvm::opt::ArgList &DriverArgs, 2551349cc55cSDimitry Andric llvm::opt::ArgStringList &CC1Args, 2552349cc55cSDimitry Andric StringRef Arch, StringRef Target, 25535f757f3fSDimitry Andric bool isBitCodeSDL) { 2554349cc55cSDimitry Andric AddStaticDeviceLibs(&C, &T, &JA, &Inputs, C.getDriver(), DriverArgs, CC1Args, 25555f757f3fSDimitry Andric Arch, Target, isBitCodeSDL); 2556349cc55cSDimitry Andric } 2557349cc55cSDimitry Andric 2558349cc55cSDimitry Andric // User defined Static Device Libraries(SDLs) can be passed to clang for 2559349cc55cSDimitry Andric // offloading GPU compilers. Like static host libraries, the use of a SDL is 2560349cc55cSDimitry Andric // specified with the -l command line option. The primary difference between 2561349cc55cSDimitry Andric // host and SDLs is the filenames for SDLs (refer SEARCH-ORDER for Bitcode SDLs 2562349cc55cSDimitry Andric // and SEARCH-ORDER for Machine-code SDLs for the naming convention). 2563349cc55cSDimitry Andric // SDLs are of following types: 2564349cc55cSDimitry Andric // 2565349cc55cSDimitry Andric // * Bitcode SDLs: They can either be a *.bc file or an archive of *.bc files. 2566349cc55cSDimitry Andric // For NVPTX, these libraries are post-clang linked following each 2567349cc55cSDimitry Andric // compilation. For AMDGPU, these libraries are linked one time 2568349cc55cSDimitry Andric // during the application link phase. 2569349cc55cSDimitry Andric // 2570bdd1243dSDimitry Andric // * Machine-code SDLs: They are archive files. For AMDGPU, the process for 2571bdd1243dSDimitry Andric // machine code SDLs is still in development. But they will be linked 2572bdd1243dSDimitry Andric // by the LLVM tool lld. 2573349cc55cSDimitry Andric // 2574349cc55cSDimitry Andric // * Bundled objects that contain both host and device codes: Bundled objects 2575349cc55cSDimitry Andric // may also contain library code compiled from source. For NVPTX, the 2576349cc55cSDimitry Andric // bundle contains cubin. For AMDGPU, the bundle contains bitcode. 2577349cc55cSDimitry Andric // 2578349cc55cSDimitry Andric // For Bitcode and Machine-code SDLs, current compiler toolchains hardcode the 2579349cc55cSDimitry Andric // inclusion of specific SDLs such as math libraries and the OpenMP device 2580349cc55cSDimitry Andric // library libomptarget. 2581349cc55cSDimitry Andric void tools::AddStaticDeviceLibs(Compilation *C, const Tool *T, 2582349cc55cSDimitry Andric const JobAction *JA, 2583349cc55cSDimitry Andric const InputInfoList *Inputs, const Driver &D, 2584349cc55cSDimitry Andric const llvm::opt::ArgList &DriverArgs, 2585349cc55cSDimitry Andric llvm::opt::ArgStringList &CC1Args, 2586349cc55cSDimitry Andric StringRef Arch, StringRef Target, 25875f757f3fSDimitry Andric bool isBitCodeSDL) { 2588349cc55cSDimitry Andric 2589349cc55cSDimitry Andric SmallVector<std::string, 8> LibraryPaths; 2590349cc55cSDimitry Andric // Add search directories from LIBRARY_PATH env variable 2591bdd1243dSDimitry Andric std::optional<std::string> LibPath = 2592349cc55cSDimitry Andric llvm::sys::Process::GetEnv("LIBRARY_PATH"); 2593349cc55cSDimitry Andric if (LibPath) { 2594349cc55cSDimitry Andric SmallVector<StringRef, 8> Frags; 2595349cc55cSDimitry Andric const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; 2596349cc55cSDimitry Andric llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr); 2597349cc55cSDimitry Andric for (StringRef Path : Frags) 2598349cc55cSDimitry Andric LibraryPaths.emplace_back(Path.trim()); 2599349cc55cSDimitry Andric } 2600349cc55cSDimitry Andric 2601349cc55cSDimitry Andric // Add directories from user-specified -L options 2602349cc55cSDimitry Andric for (std::string Search_Dir : DriverArgs.getAllArgValues(options::OPT_L)) 2603349cc55cSDimitry Andric LibraryPaths.emplace_back(Search_Dir); 2604349cc55cSDimitry Andric 2605349cc55cSDimitry Andric // Add path to lib-debug folders 2606349cc55cSDimitry Andric SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir); 2607bdd1243dSDimitry Andric llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME); 2608349cc55cSDimitry Andric LibraryPaths.emplace_back(DefaultLibPath.c_str()); 2609349cc55cSDimitry Andric 2610349cc55cSDimitry Andric // Build list of Static Device Libraries SDLs specified by -l option 2611349cc55cSDimitry Andric llvm::SmallSet<std::string, 16> SDLNames; 2612349cc55cSDimitry Andric static const StringRef HostOnlyArchives[] = { 2613349cc55cSDimitry Andric "omp", "cudart", "m", "gcc", "gcc_s", "pthread", "hip_hcc"}; 2614349cc55cSDimitry Andric for (auto SDLName : DriverArgs.getAllArgValues(options::OPT_l)) { 26155f757f3fSDimitry Andric if (!llvm::is_contained(HostOnlyArchives, SDLName)) { 2616bdd1243dSDimitry Andric SDLNames.insert(std::string("-l") + SDLName); 2617349cc55cSDimitry Andric } 2618349cc55cSDimitry Andric } 2619349cc55cSDimitry Andric 2620bdd1243dSDimitry Andric for (auto Input : DriverArgs.getAllArgValues(options::OPT_INPUT)) { 2621bdd1243dSDimitry Andric auto FileName = StringRef(Input); 2622bdd1243dSDimitry Andric // Clang treats any unknown file types as archives and passes them to the 2623bdd1243dSDimitry Andric // linker. Files with extension 'lib' are classified as TY_Object by clang 2624bdd1243dSDimitry Andric // but they are usually archives. It is OK if the file is not really an 2625bdd1243dSDimitry Andric // archive since GetSDLFromOffloadArchive will check the magic of the file 2626bdd1243dSDimitry Andric // and only unbundle it if it is really an archive. 2627bdd1243dSDimitry Andric const StringRef LibFileExt = ".lib"; 2628bdd1243dSDimitry Andric if (!llvm::sys::path::has_extension(FileName) || 2629bdd1243dSDimitry Andric types::lookupTypeForExtension( 2630bdd1243dSDimitry Andric llvm::sys::path::extension(FileName).drop_front()) == 2631bdd1243dSDimitry Andric types::TY_INVALID || 2632bdd1243dSDimitry Andric llvm::sys::path::extension(FileName) == LibFileExt) 2633bdd1243dSDimitry Andric SDLNames.insert(Input); 2634bdd1243dSDimitry Andric } 2635bdd1243dSDimitry Andric 2636349cc55cSDimitry Andric // The search stops as soon as an SDL file is found. The driver then provides 2637bdd1243dSDimitry Andric // the full filename of the SDL to the llvm-link command. If no SDL is found 2638bdd1243dSDimitry Andric // after searching each LINKPATH with SEARCH-ORDER, it is possible that an 2639bdd1243dSDimitry Andric // archive file lib<libname>.a exists and may contain bundled object files. 2640349cc55cSDimitry Andric for (auto SDLName : SDLNames) { 2641349cc55cSDimitry Andric // This is the only call to SDLSearch 2642349cc55cSDimitry Andric if (!SDLSearch(D, DriverArgs, CC1Args, LibraryPaths, SDLName, Arch, Target, 26435f757f3fSDimitry Andric isBitCodeSDL)) { 2644349cc55cSDimitry Andric GetSDLFromOffloadArchive(*C, D, *T, *JA, *Inputs, DriverArgs, CC1Args, 2645349cc55cSDimitry Andric LibraryPaths, SDLName, Arch, Target, 26465f757f3fSDimitry Andric isBitCodeSDL); 2647349cc55cSDimitry Andric } 2648349cc55cSDimitry Andric } 2649349cc55cSDimitry Andric } 2650349cc55cSDimitry Andric 2651fe6060f1SDimitry Andric static llvm::opt::Arg * 2652fe6060f1SDimitry Andric getAMDGPUCodeObjectArgument(const Driver &D, const llvm::opt::ArgList &Args) { 265306c3fb27SDimitry Andric return Args.getLastArg(options::OPT_mcode_object_version_EQ); 2654fe6060f1SDimitry Andric } 2655fe6060f1SDimitry Andric 2656fe6060f1SDimitry Andric void tools::checkAMDGPUCodeObjectVersion(const Driver &D, 2657fe6060f1SDimitry Andric const llvm::opt::ArgList &Args) { 26585f757f3fSDimitry Andric const unsigned MinCodeObjVer = 4; 2659*0fca6ea1SDimitry Andric const unsigned MaxCodeObjVer = 6; 2660e8d8bef9SDimitry Andric 2661fe6060f1SDimitry Andric if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args)) { 2662fe6060f1SDimitry Andric if (CodeObjArg->getOption().getID() == 2663fe6060f1SDimitry Andric options::OPT_mcode_object_version_EQ) { 2664fe6060f1SDimitry Andric unsigned CodeObjVer = MaxCodeObjVer; 2665fe6060f1SDimitry Andric auto Remnant = 2666fe6060f1SDimitry Andric StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer); 2667fe6060f1SDimitry Andric if (Remnant || CodeObjVer < MinCodeObjVer || CodeObjVer > MaxCodeObjVer) 2668fe6060f1SDimitry Andric D.Diag(diag::err_drv_invalid_int_value) 2669fe6060f1SDimitry Andric << CodeObjArg->getAsString(Args) << CodeObjArg->getValue(); 2670*0fca6ea1SDimitry Andric 2671*0fca6ea1SDimitry Andric // COV6 is only supported by LLVM at the time of writing this, and it's 2672*0fca6ea1SDimitry Andric // expected to take some time before all ROCm components fully 2673*0fca6ea1SDimitry Andric // support it. In the meantime, make sure users are aware of this. 2674*0fca6ea1SDimitry Andric if (CodeObjVer == 6) 2675*0fca6ea1SDimitry Andric D.Diag(diag::warn_drv_amdgpu_cov6); 2676fe6060f1SDimitry Andric } 2677fe6060f1SDimitry Andric } 2678e8d8bef9SDimitry Andric } 2679e8d8bef9SDimitry Andric 2680fe6060f1SDimitry Andric unsigned tools::getAMDGPUCodeObjectVersion(const Driver &D, 2681fe6060f1SDimitry Andric const llvm::opt::ArgList &Args) { 2682fe6060f1SDimitry Andric unsigned CodeObjVer = 4; // default 268306c3fb27SDimitry Andric if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args)) 2684e8d8bef9SDimitry Andric StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer); 2685e8d8bef9SDimitry Andric return CodeObjVer; 2686e8d8bef9SDimitry Andric } 2687e8d8bef9SDimitry Andric 2688fe6060f1SDimitry Andric bool tools::haveAMDGPUCodeObjectVersionArgument( 2689fe6060f1SDimitry Andric const Driver &D, const llvm::opt::ArgList &Args) { 2690fe6060f1SDimitry Andric return getAMDGPUCodeObjectArgument(D, Args) != nullptr; 2691fe6060f1SDimitry Andric } 2692fe6060f1SDimitry Andric 2693e8d8bef9SDimitry Andric void tools::addMachineOutlinerArgs(const Driver &D, 2694e8d8bef9SDimitry Andric const llvm::opt::ArgList &Args, 2695e8d8bef9SDimitry Andric llvm::opt::ArgStringList &CmdArgs, 2696bdd1243dSDimitry Andric const llvm::Triple &Triple, bool IsLTO, 2697bdd1243dSDimitry Andric const StringRef PluginOptPrefix) { 2698e8d8bef9SDimitry Andric auto addArg = [&, IsLTO](const Twine &Arg) { 2699e8d8bef9SDimitry Andric if (IsLTO) { 2700bdd1243dSDimitry Andric assert(!PluginOptPrefix.empty() && "Cannot have empty PluginOptPrefix!"); 2701bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + Arg)); 2702e8d8bef9SDimitry Andric } else { 2703e8d8bef9SDimitry Andric CmdArgs.push_back("-mllvm"); 2704e8d8bef9SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Arg)); 2705e8d8bef9SDimitry Andric } 2706e8d8bef9SDimitry Andric }; 2707e8d8bef9SDimitry Andric 2708e8d8bef9SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_moutline, 2709e8d8bef9SDimitry Andric options::OPT_mno_outline)) { 2710e8d8bef9SDimitry Andric if (A->getOption().matches(options::OPT_moutline)) { 2711e8d8bef9SDimitry Andric // We only support -moutline in AArch64 and ARM targets right now. If 2712e8d8bef9SDimitry Andric // we're not compiling for these, emit a warning and ignore the flag. 2713e8d8bef9SDimitry Andric // Otherwise, add the proper mllvm flags. 27145f757f3fSDimitry Andric if (!(Triple.isARM() || Triple.isThumb() || Triple.isAArch64())) { 2715e8d8bef9SDimitry Andric D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName(); 2716e8d8bef9SDimitry Andric } else { 2717e8d8bef9SDimitry Andric addArg(Twine("-enable-machine-outliner")); 2718e8d8bef9SDimitry Andric } 2719e8d8bef9SDimitry Andric } else { 2720e8d8bef9SDimitry Andric // Disable all outlining behaviour. 2721e8d8bef9SDimitry Andric addArg(Twine("-enable-machine-outliner=never")); 2722e8d8bef9SDimitry Andric } 2723e8d8bef9SDimitry Andric } 2724e8d8bef9SDimitry Andric } 2725fe6060f1SDimitry Andric 2726fe6060f1SDimitry Andric void tools::addOpenMPDeviceRTL(const Driver &D, 2727fe6060f1SDimitry Andric const llvm::opt::ArgList &DriverArgs, 2728fe6060f1SDimitry Andric llvm::opt::ArgStringList &CC1Args, 2729fe6060f1SDimitry Andric StringRef BitcodeSuffix, 2730*0fca6ea1SDimitry Andric const llvm::Triple &Triple, 2731*0fca6ea1SDimitry Andric const ToolChain &HostTC) { 2732fe6060f1SDimitry Andric SmallVector<StringRef, 8> LibraryPaths; 2733349cc55cSDimitry Andric 2734fe6060f1SDimitry Andric // Add user defined library paths from LIBRARY_PATH. 2735bdd1243dSDimitry Andric std::optional<std::string> LibPath = 2736fe6060f1SDimitry Andric llvm::sys::Process::GetEnv("LIBRARY_PATH"); 2737fe6060f1SDimitry Andric if (LibPath) { 2738fe6060f1SDimitry Andric SmallVector<StringRef, 8> Frags; 2739fe6060f1SDimitry Andric const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; 2740fe6060f1SDimitry Andric llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr); 2741fe6060f1SDimitry Andric for (StringRef Path : Frags) 2742fe6060f1SDimitry Andric LibraryPaths.emplace_back(Path.trim()); 2743fe6060f1SDimitry Andric } 2744fe6060f1SDimitry Andric 2745*0fca6ea1SDimitry Andric // Check all of the standard library search paths used by the compiler. 2746*0fca6ea1SDimitry Andric for (const auto &LibPath : HostTC.getFilePaths()) 2747*0fca6ea1SDimitry Andric LibraryPaths.emplace_back(LibPath); 2748*0fca6ea1SDimitry Andric 2749fe6060f1SDimitry Andric OptSpecifier LibomptargetBCPathOpt = 275081ad6265SDimitry Andric Triple.isAMDGCN() ? options::OPT_libomptarget_amdgpu_bc_path_EQ 2751fe6060f1SDimitry Andric : options::OPT_libomptarget_nvptx_bc_path_EQ; 2752fe6060f1SDimitry Andric 275381ad6265SDimitry Andric StringRef ArchPrefix = Triple.isAMDGCN() ? "amdgpu" : "nvptx"; 275481ad6265SDimitry Andric std::string LibOmpTargetName = 275581ad6265SDimitry Andric ("libomptarget-" + ArchPrefix + "-" + BitcodeSuffix + ".bc").str(); 2756349cc55cSDimitry Andric 2757fe6060f1SDimitry Andric // First check whether user specifies bc library 2758fe6060f1SDimitry Andric if (const Arg *A = DriverArgs.getLastArg(LibomptargetBCPathOpt)) { 2759349cc55cSDimitry Andric SmallString<128> LibOmpTargetFile(A->getValue()); 2760349cc55cSDimitry Andric if (llvm::sys::fs::exists(LibOmpTargetFile) && 2761349cc55cSDimitry Andric llvm::sys::fs::is_directory(LibOmpTargetFile)) { 2762349cc55cSDimitry Andric llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName); 2763349cc55cSDimitry Andric } 2764349cc55cSDimitry Andric 2765349cc55cSDimitry Andric if (llvm::sys::fs::exists(LibOmpTargetFile)) { 2766fe6060f1SDimitry Andric CC1Args.push_back("-mlink-builtin-bitcode"); 2767349cc55cSDimitry Andric CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile)); 2768fe6060f1SDimitry Andric } else { 2769fe6060f1SDimitry Andric D.Diag(diag::err_drv_omp_offload_target_bcruntime_not_found) 2770349cc55cSDimitry Andric << LibOmpTargetFile; 2771fe6060f1SDimitry Andric } 2772fe6060f1SDimitry Andric } else { 2773fe6060f1SDimitry Andric bool FoundBCLibrary = false; 2774fe6060f1SDimitry Andric 2775fe6060f1SDimitry Andric for (StringRef LibraryPath : LibraryPaths) { 2776fe6060f1SDimitry Andric SmallString<128> LibOmpTargetFile(LibraryPath); 2777fe6060f1SDimitry Andric llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName); 2778fe6060f1SDimitry Andric if (llvm::sys::fs::exists(LibOmpTargetFile)) { 2779fe6060f1SDimitry Andric CC1Args.push_back("-mlink-builtin-bitcode"); 2780fe6060f1SDimitry Andric CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile)); 2781fe6060f1SDimitry Andric FoundBCLibrary = true; 2782fe6060f1SDimitry Andric break; 2783fe6060f1SDimitry Andric } 2784fe6060f1SDimitry Andric } 2785fe6060f1SDimitry Andric 2786fe6060f1SDimitry Andric if (!FoundBCLibrary) 2787fe6060f1SDimitry Andric D.Diag(diag::err_drv_omp_offload_target_missingbcruntime) 2788fe6060f1SDimitry Andric << LibOmpTargetName << ArchPrefix; 2789fe6060f1SDimitry Andric } 2790fe6060f1SDimitry Andric } 27915f757f3fSDimitry Andric void tools::addHIPRuntimeLibArgs(const ToolChain &TC, Compilation &C, 279281ad6265SDimitry Andric const llvm::opt::ArgList &Args, 279381ad6265SDimitry Andric llvm::opt::ArgStringList &CmdArgs) { 27945f757f3fSDimitry Andric if ((C.getActiveOffloadKinds() & Action::OFK_HIP) && 279581ad6265SDimitry Andric !Args.hasArg(options::OPT_nostdlib) && 2796*0fca6ea1SDimitry Andric !Args.hasArg(options::OPT_no_hip_rt) && !Args.hasArg(options::OPT_r)) { 279781ad6265SDimitry Andric TC.AddHIPRuntimeLibArgs(Args, CmdArgs); 279881ad6265SDimitry Andric } else { 279981ad6265SDimitry Andric // Claim "no HIP libraries" arguments if any 2800bdd1243dSDimitry Andric for (auto *Arg : Args.filtered(options::OPT_no_hip_rt)) { 280181ad6265SDimitry Andric Arg->claim(); 280281ad6265SDimitry Andric } 280381ad6265SDimitry Andric } 280481ad6265SDimitry Andric } 2805*0fca6ea1SDimitry Andric 2806*0fca6ea1SDimitry Andric void tools::addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC, 2807*0fca6ea1SDimitry Andric const llvm::opt::ArgList &Args, 2808*0fca6ea1SDimitry Andric llvm::opt::ArgStringList &CmdArgs, 2809*0fca6ea1SDimitry Andric const llvm::Triple &Triple) { 2810*0fca6ea1SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_moutline_atomics, 2811*0fca6ea1SDimitry Andric options::OPT_mno_outline_atomics)) { 2812*0fca6ea1SDimitry Andric // Option -moutline-atomics supported for AArch64 target only. 2813*0fca6ea1SDimitry Andric if (!Triple.isAArch64()) { 2814*0fca6ea1SDimitry Andric D.Diag(diag::warn_drv_moutline_atomics_unsupported_opt) 2815*0fca6ea1SDimitry Andric << Triple.getArchName() << A->getOption().getName(); 2816*0fca6ea1SDimitry Andric } else { 2817*0fca6ea1SDimitry Andric if (A->getOption().matches(options::OPT_moutline_atomics)) { 2818*0fca6ea1SDimitry Andric CmdArgs.push_back("-target-feature"); 2819*0fca6ea1SDimitry Andric CmdArgs.push_back("+outline-atomics"); 2820*0fca6ea1SDimitry Andric } else { 2821*0fca6ea1SDimitry Andric CmdArgs.push_back("-target-feature"); 2822*0fca6ea1SDimitry Andric CmdArgs.push_back("-outline-atomics"); 2823*0fca6ea1SDimitry Andric } 2824*0fca6ea1SDimitry Andric } 2825*0fca6ea1SDimitry Andric } else if (Triple.isAArch64() && TC.IsAArch64OutlineAtomicsDefault(Args)) { 2826*0fca6ea1SDimitry Andric CmdArgs.push_back("-target-feature"); 2827*0fca6ea1SDimitry Andric CmdArgs.push_back("+outline-atomics"); 2828*0fca6ea1SDimitry Andric } 2829*0fca6ea1SDimitry Andric } 2830*0fca6ea1SDimitry Andric 2831*0fca6ea1SDimitry Andric void tools::addOffloadCompressArgs(const llvm::opt::ArgList &TCArgs, 2832*0fca6ea1SDimitry Andric llvm::opt::ArgStringList &CmdArgs) { 2833*0fca6ea1SDimitry Andric if (TCArgs.hasFlag(options::OPT_offload_compress, 2834*0fca6ea1SDimitry Andric options::OPT_no_offload_compress, false)) 2835*0fca6ea1SDimitry Andric CmdArgs.push_back("-compress"); 2836*0fca6ea1SDimitry Andric if (TCArgs.hasArg(options::OPT_v)) 2837*0fca6ea1SDimitry Andric CmdArgs.push_back("-verbose"); 2838*0fca6ea1SDimitry Andric if (auto *Arg = TCArgs.getLastArg(options::OPT_offload_compression_level_EQ)) 2839*0fca6ea1SDimitry Andric CmdArgs.push_back( 2840*0fca6ea1SDimitry Andric TCArgs.MakeArgString(Twine("-compression-level=") + Arg->getValue())); 2841*0fca6ea1SDimitry Andric } 2842*0fca6ea1SDimitry Andric 2843*0fca6ea1SDimitry Andric void tools::addMCModel(const Driver &D, const llvm::opt::ArgList &Args, 2844*0fca6ea1SDimitry Andric const llvm::Triple &Triple, 2845*0fca6ea1SDimitry Andric const llvm::Reloc::Model &RelocationModel, 2846*0fca6ea1SDimitry Andric llvm::opt::ArgStringList &CmdArgs) { 2847*0fca6ea1SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) { 2848*0fca6ea1SDimitry Andric StringRef CM = A->getValue(); 2849*0fca6ea1SDimitry Andric bool Ok = false; 2850*0fca6ea1SDimitry Andric if (Triple.isOSAIX() && CM == "medium") 2851*0fca6ea1SDimitry Andric CM = "large"; 2852*0fca6ea1SDimitry Andric if (Triple.isAArch64(64)) { 2853*0fca6ea1SDimitry Andric Ok = CM == "tiny" || CM == "small" || CM == "large"; 2854*0fca6ea1SDimitry Andric if (CM == "large" && !Triple.isOSBinFormatMachO() && 2855*0fca6ea1SDimitry Andric RelocationModel != llvm::Reloc::Static) 2856*0fca6ea1SDimitry Andric D.Diag(diag::err_drv_argument_only_allowed_with) 2857*0fca6ea1SDimitry Andric << A->getAsString(Args) << "-fno-pic"; 2858*0fca6ea1SDimitry Andric } else if (Triple.isLoongArch()) { 2859*0fca6ea1SDimitry Andric if (CM == "extreme" && 2860*0fca6ea1SDimitry Andric Args.hasFlagNoClaim(options::OPT_fplt, options::OPT_fno_plt, false)) 2861*0fca6ea1SDimitry Andric D.Diag(diag::err_drv_argument_not_allowed_with) 2862*0fca6ea1SDimitry Andric << A->getAsString(Args) << "-fplt"; 2863*0fca6ea1SDimitry Andric Ok = CM == "normal" || CM == "medium" || CM == "extreme"; 2864*0fca6ea1SDimitry Andric // Convert to LLVM recognizable names. 2865*0fca6ea1SDimitry Andric if (Ok) 2866*0fca6ea1SDimitry Andric CM = llvm::StringSwitch<StringRef>(CM) 2867*0fca6ea1SDimitry Andric .Case("normal", "small") 2868*0fca6ea1SDimitry Andric .Case("extreme", "large") 2869*0fca6ea1SDimitry Andric .Default(CM); 2870*0fca6ea1SDimitry Andric } else if (Triple.isPPC64() || Triple.isOSAIX()) { 2871*0fca6ea1SDimitry Andric Ok = CM == "small" || CM == "medium" || CM == "large"; 2872*0fca6ea1SDimitry Andric } else if (Triple.isRISCV()) { 2873*0fca6ea1SDimitry Andric if (CM == "medlow") 2874*0fca6ea1SDimitry Andric CM = "small"; 2875*0fca6ea1SDimitry Andric else if (CM == "medany") 2876*0fca6ea1SDimitry Andric CM = "medium"; 2877*0fca6ea1SDimitry Andric Ok = CM == "small" || CM == "medium"; 2878*0fca6ea1SDimitry Andric } else if (Triple.getArch() == llvm::Triple::x86_64) { 2879*0fca6ea1SDimitry Andric Ok = llvm::is_contained({"small", "kernel", "medium", "large", "tiny"}, 2880*0fca6ea1SDimitry Andric CM); 2881*0fca6ea1SDimitry Andric } else if (Triple.isNVPTX() || Triple.isAMDGPU() || Triple.isSPIRV()) { 2882*0fca6ea1SDimitry Andric // NVPTX/AMDGPU/SPIRV does not care about the code model and will accept 2883*0fca6ea1SDimitry Andric // whatever works for the host. 2884*0fca6ea1SDimitry Andric Ok = true; 2885*0fca6ea1SDimitry Andric } else if (Triple.isSPARC64()) { 2886*0fca6ea1SDimitry Andric if (CM == "medlow") 2887*0fca6ea1SDimitry Andric CM = "small"; 2888*0fca6ea1SDimitry Andric else if (CM == "medmid") 2889*0fca6ea1SDimitry Andric CM = "medium"; 2890*0fca6ea1SDimitry Andric else if (CM == "medany") 2891*0fca6ea1SDimitry Andric CM = "large"; 2892*0fca6ea1SDimitry Andric Ok = CM == "small" || CM == "medium" || CM == "large"; 2893*0fca6ea1SDimitry Andric } 2894*0fca6ea1SDimitry Andric if (Ok) { 2895*0fca6ea1SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-mcmodel=" + CM)); 2896*0fca6ea1SDimitry Andric } else { 2897*0fca6ea1SDimitry Andric D.Diag(diag::err_drv_unsupported_option_argument_for_target) 2898*0fca6ea1SDimitry Andric << A->getSpelling() << CM << Triple.getTriple(); 2899*0fca6ea1SDimitry Andric } 2900*0fca6ea1SDimitry Andric } 2901*0fca6ea1SDimitry Andric 2902*0fca6ea1SDimitry Andric if (Triple.getArch() == llvm::Triple::x86_64) { 2903*0fca6ea1SDimitry Andric bool IsMediumCM = false; 2904*0fca6ea1SDimitry Andric bool IsLargeCM = false; 2905*0fca6ea1SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) { 2906*0fca6ea1SDimitry Andric IsMediumCM = StringRef(A->getValue()) == "medium"; 2907*0fca6ea1SDimitry Andric IsLargeCM = StringRef(A->getValue()) == "large"; 2908*0fca6ea1SDimitry Andric } 2909*0fca6ea1SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mlarge_data_threshold_EQ)) { 2910*0fca6ea1SDimitry Andric if (!IsMediumCM && !IsLargeCM) { 2911*0fca6ea1SDimitry Andric D.Diag(diag::warn_drv_large_data_threshold_invalid_code_model) 2912*0fca6ea1SDimitry Andric << A->getOption().getRenderName(); 2913*0fca6ea1SDimitry Andric } else { 2914*0fca6ea1SDimitry Andric A->render(Args, CmdArgs); 2915*0fca6ea1SDimitry Andric } 2916*0fca6ea1SDimitry Andric } else if (IsMediumCM) { 2917*0fca6ea1SDimitry Andric CmdArgs.push_back("-mlarge-data-threshold=65536"); 2918*0fca6ea1SDimitry Andric } else if (IsLargeCM) { 2919*0fca6ea1SDimitry Andric CmdArgs.push_back("-mlarge-data-threshold=0"); 2920*0fca6ea1SDimitry Andric } 2921*0fca6ea1SDimitry Andric } 2922*0fca6ea1SDimitry Andric } 2923